From 945cc0ef2326020dd8b742068e01c6b57f45f263 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Sun, 16 Jun 2019 11:17:48 +0200 Subject: [PATCH 001/302] [grubcfg] add apparmor support --- src/modules/grubcfg/main.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/modules/grubcfg/main.py b/src/modules/grubcfg/main.py index 1d5342856..348f4fdad 100644 --- a/src/modules/grubcfg/main.py +++ b/src/modules/grubcfg/main.py @@ -3,7 +3,7 @@ # # === This file is part of Calamares - === # -# Copyright 2014-2018, Philip Müller +# Copyright 2014-2019, Philip Müller # Copyright 2015-2017, Teo Mrnjavac # Copyright 2017, Alf Gaida # Copyright 2017, 2019, Adriaan de Groot @@ -62,6 +62,8 @@ def modify_grub_default(partitions, root_mount_point, distributor): have_plymouth = plymouth_bin == 0 have_dracut = dracut_bin == 0 + enable_apparmor = "apparmor=1" + set_security = "" use_splash = "" swap_uuid = "" swap_outer_uuid = "" @@ -113,6 +115,11 @@ def modify_grub_default(partitions, root_mount_point, distributor): if use_splash and not os.path.exists(os.path.join(root_mount_point, "usr/bin/grub-set-bootflag")): kernel_params.append(use_splash) + if os.path.exists(os.path.join(root_mount_point, "usr/lib/libapparmor.so")): + set_security = "security=apparmor" + kernel_params.append(enable_apparmor) + kernel_params.append(set_security) + if swap_uuid: kernel_params.append("resume=UUID={!s}".format(swap_uuid)) @@ -157,13 +164,13 @@ def modify_grub_default(partitions, root_mount_point, distributor): line = line.rstrip("'") existing_params = line.split() - if not os.path.exists(os.path.join(root_mount_point, "usr/bin/grub-set-bootflag")): - for existing_param in existing_params: - existing_param_name = existing_param.split("=")[0] + for existing_param in existing_params: + existing_param_name = existing_param.split("=")[0] - # the only ones we ever add - if existing_param_name not in ["quiet", "resume", "splash"]: - kernel_params.append(existing_param) + # the only ones we ever add + if existing_param_name not in [ + "quiet", "resume", "splash"]: + kernel_params.append(existing_param) kernel_cmd = "GRUB_CMDLINE_LINUX_DEFAULT=\"{!s}\"".format( " ".join(kernel_params) From da8f45ae18723f63366673a9e338756a0f34bc97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Wed, 26 Jun 2019 23:41:09 +0200 Subject: [PATCH 002/302] [machineid] use force for symlink creation --- src/modules/machineid/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/machineid/main.py b/src/modules/machineid/main.py index cde47cfd9..9756055eb 100644 --- a/src/modules/machineid/main.py +++ b/src/modules/machineid/main.py @@ -4,7 +4,7 @@ # === This file is part of Calamares - === # # Copyright 2014, Kevin Kofler -# Copyright 2016, Philip Müller +# Copyright 2019, Philip Müller # Copyright 2017, Alf Gaida # Copyright 2019, Adriaan de Groot # @@ -65,7 +65,7 @@ def run(): if enable_dbus: if enable_symlink and os.path.exists(target_systemd_machineid_file): - check_target_env_call(["ln", "-s", "/etc/machine-id", + check_target_env_call(["ln", "-sf", "/etc/machine-id", "/var/lib/dbus/machine-id"]) else: check_target_env_call(["dbus-uuidgen", "--ensure"]) From 920184202544da56caa18482e4176dd9340aa10d Mon Sep 17 00:00:00 2001 From: bill-auger Date: Fri, 28 Jun 2019 13:32:35 -0400 Subject: [PATCH 003/302] implement definable job weights --- src/libcalamares/Job.cpp | 7 +++++++ src/libcalamares/Job.h | 1 + src/libcalamares/JobQueue.cpp | 28 +++++++++++++++++++++++++++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/libcalamares/Job.cpp b/src/libcalamares/Job.cpp index d2118451f..116ed77e2 100644 --- a/src/libcalamares/Job.cpp +++ b/src/libcalamares/Job.cpp @@ -97,6 +97,13 @@ Job::~Job() {} +qreal +Job::getJobWeight() const +{ + return qreal( 1.0 ); +} + + QString Job::prettyDescription() const { diff --git a/src/libcalamares/Job.h b/src/libcalamares/Job.h index f590ef0ee..e0b24fa9b 100644 --- a/src/libcalamares/Job.h +++ b/src/libcalamares/Job.h @@ -83,6 +83,7 @@ public: explicit Job( QObject* parent = nullptr ); virtual ~Job(); + virtual qreal getJobWeight() const; virtual QString prettyName() const = 0; virtual QString prettyDescription() const; virtual QString prettyStatusMessage() const; diff --git a/src/libcalamares/JobQueue.cpp b/src/libcalamares/JobQueue.cpp index 3a76aa099..49a70bca8 100644 --- a/src/libcalamares/JobQueue.cpp +++ b/src/libcalamares/JobQueue.cpp @@ -48,6 +48,17 @@ public: void setJobs( const JobList& jobs ) { m_jobs = jobs; + + qreal totalJobsWeight = 0.0; + for( auto job : m_jobs ) + { + totalJobsWeight += job->getJobWeight(); + } + for( auto job : m_jobs ) + { + qreal jobWeight = qreal( job->getJobWeight() / totalJobsWeight ); + m_jobWeights.append( jobWeight ) ; + } } void run() override @@ -87,6 +98,7 @@ public: private: JobList m_jobs; + QList< qreal > m_jobWeights; JobQueue* m_queue; int m_jobIndex; @@ -101,8 +113,22 @@ private: ? m_jobs.at( m_jobIndex )->prettyStatusMessage() : tr( "Done" ); - qreal percent = ( m_jobIndex + jobPercent ) / qreal( jobCount ); + qreal cumulativeProgress = 0.0; + for( auto jobWeight : m_jobWeights.mid( 0, m_jobIndex ) ) + { + cumulativeProgress += jobWeight; + } + qreal percent = m_jobIndex < jobCount + ? cumulativeProgress + ( ( m_jobWeights.at( m_jobIndex ) ) * jobPercent ) + : 1.0; + if (m_jobIndex < jobCount) + { + cDebug(Logger::LOGVERBOSE) << "[JOBQUEUE]: Progress for Job[" << m_jobIndex << "]: " << ( jobPercent * 100 ) << "% completed"; + cDebug(Logger::LOGVERBOSE) << "[JOBQUEUE]: Progress Overall: " << ( cumulativeProgress * 100 ) << "% (accumulated) + " + << ( ( ( m_jobWeights.at( m_jobIndex ) ) * jobPercent ) * 100 ) << "% (this job) = " + << ( percent * 100 ) << "% (total)"; + } QMetaObject::invokeMethod( m_queue, "progress", Qt::QueuedConnection, Q_ARG( qreal, percent ), Q_ARG( QString, message ) From e7960474d4cbe6fa1cd5004845d369628e3ba4da Mon Sep 17 00:00:00 2001 From: bill-auger Date: Fri, 28 Jun 2019 12:16:13 -0400 Subject: [PATCH 004/302] implement post log to paste server --- src/libcalamaresui/ViewManager.cpp | 105 ++++++++++++++++++++++++++--- 1 file changed, 96 insertions(+), 9 deletions(-) diff --git a/src/libcalamaresui/ViewManager.cpp b/src/libcalamaresui/ViewManager.cpp index 16c38b1bc..18c0cbfb8 100644 --- a/src/libcalamaresui/ViewManager.cpp +++ b/src/libcalamaresui/ViewManager.cpp @@ -32,8 +32,10 @@ #include #include +#include #include #include +#include namespace Calamares { @@ -133,6 +135,8 @@ ViewManager::ViewManager( QObject* parent ) if (Calamares::Settings::instance()->disableCancel()) m_quit->setVisible( false ); + +onInstallationFailed("amessage","somedetails"); // TODO: remove this } @@ -189,6 +193,10 @@ ViewManager::insertViewStep( int before, ViewStep* step ) void ViewManager::onInstallationFailed( const QString& message, const QString& details ) { +bool shouldOfferWebPaste = true; // TODO: config var +QString ficheHost = "termbin.com"; // TODO: config var +quint16 fichePort = 9999; // TODO: config var + cError() << "Installation failed:"; cDebug() << "- message:" << message; cDebug() << "- details:" << details; @@ -196,21 +204,100 @@ ViewManager::onInstallationFailed( const QString& message, const QString& detail QString heading = Calamares::Settings::instance()->isSetupMode() ? tr( "Setup Failed" ) : tr( "Installation Failed" ); + QString pasteMsg = tr( "Would you like to paste the install log to the web?" ); + QString pasteUrlFmt = tr( "Install log posted to:\n%1" ); + QString pasteUrlTitle = tr( "Install Log Paste URL" ); + QString text = "

" + message + "

"; + if ( !details.isEmpty() ) + text += "

" + details + "

"; + if ( shouldOfferWebPaste ) + text += "

" + pasteMsg + "

"; + QMessageBox* msgBox = new QMessageBox(); msgBox->setIcon( QMessageBox::Critical ); msgBox->setWindowTitle( tr( "Error" ) ); msgBox->setText( "" + heading + "" ); - msgBox->setStandardButtons( QMessageBox::Close ); - msgBox->button( QMessageBox::Close )->setText( tr( "&Close" ) ); - - QString text = "

" + message + "

"; - if ( !details.isEmpty() ) - text += "

" + details + "

"; msgBox->setInformativeText( text ); - - connect( msgBox, &QMessageBox::buttonClicked, qApp, &QApplication::quit ); - cDebug() << "Calamares will quit when the dialog closes."; + if ( shouldOfferWebPaste ) + { + msgBox->setStandardButtons( QMessageBox::Yes | QMessageBox::No ); + msgBox->setDefaultButton( QMessageBox::No ); + msgBox->button( QMessageBox::Yes )->setText( tr( "&Yes" ) ); + msgBox->button( QMessageBox::No )->setText( tr( "&No" ) ); + } + else + { + msgBox->setStandardButtons( QMessageBox::Close ); + msgBox->setDefaultButton( QMessageBox::Close ); + msgBox->button( QMessageBox::Close )->setText( tr( "&Close" ) ); + } msgBox->show(); + + cDebug() << "Calamares will quit when the dialog closes."; + connect( msgBox, &QMessageBox::buttonClicked, + [msgBox, ficheHost, fichePort, pasteUrlFmt, pasteUrlTitle] ( QAbstractButton* button ) + { + if ( button->text() != tr( "&Yes" ) ) + QApplication::quit(); + else + { + QFile pasteSourceFile( Logger::logFile() ); + if ( !pasteSourceFile.open( QIODevice::ReadOnly | QIODevice::Text ) ) + cError() << "Could not open log file"; + else + { + QByteArray pasteData; + while ( !pasteSourceFile.atEnd() ) + { + pasteData += pasteSourceFile.readLine(); + } + + QTcpSocket* socket = new QTcpSocket(msgBox); + socket->connectToHost( ficheHost, fichePort ); + + if ( !socket->waitForConnected() ) + cError() << "Could not connect to paste server"; + else + { + cDebug() << "Connected to paste server"; + + socket->write( pasteData ); + + if ( !socket->waitForBytesWritten() ) + cError() << "Could not write to paste server"; + else + { + cDebug() << "Paste data written to paste server"; + + if ( !socket->waitForReadyRead() ) + cError() << "No data from paste server"; + else + { + cDebug() << "Reading response from paste server"; + + char resp[1024]; + socket->readLine(resp, 1024); + socket->close(); + + QString pasteUrl = QString( resp ) ; + QString pasteUrlMsg = QString( pasteUrlFmt ).arg( pasteUrl ); + + cDebug() << pasteUrlMsg; + + QMessageBox* pasteUrlMsgBox = new QMessageBox(); + pasteUrlMsgBox->setIcon( QMessageBox::Critical ); + pasteUrlMsgBox->setWindowTitle( tr( pasteUrlTitle ) ); + pasteUrlMsgBox->setStandardButtons( QMessageBox::Close ); + pasteUrlMsgBox->setText( pasteUrlMsg ); + pasteUrlMsgBox->show(); + + connect( pasteUrlMsgBox, &QMessageBox::buttonClicked, qApp, &QApplication::quit ); + } + } + } + } + } + }); } From e096631c5436301270f0b7f19eefe0392b217772 Mon Sep 17 00:00:00 2001 From: bill-auger Date: Sun, 30 Jun 2019 06:13:22 -0400 Subject: [PATCH 005/302] squashme WIP upload log to paste server - refactor error checking --- src/libcalamaresui/ViewManager.cpp | 122 +++++++++++++++-------------- 1 file changed, 65 insertions(+), 57 deletions(-) diff --git a/src/libcalamaresui/ViewManager.cpp b/src/libcalamaresui/ViewManager.cpp index 18c0cbfb8..0efc7080d 100644 --- a/src/libcalamaresui/ViewManager.cpp +++ b/src/libcalamaresui/ViewManager.cpp @@ -238,65 +238,73 @@ quint16 fichePort = 9999; // TODO: config var [msgBox, ficheHost, fichePort, pasteUrlFmt, pasteUrlTitle] ( QAbstractButton* button ) { if ( button->text() != tr( "&Yes" ) ) - QApplication::quit(); - else { - QFile pasteSourceFile( Logger::logFile() ); - if ( !pasteSourceFile.open( QIODevice::ReadOnly | QIODevice::Text ) ) - cError() << "Could not open log file"; - else - { - QByteArray pasteData; - while ( !pasteSourceFile.atEnd() ) - { - pasteData += pasteSourceFile.readLine(); - } - - QTcpSocket* socket = new QTcpSocket(msgBox); - socket->connectToHost( ficheHost, fichePort ); - - if ( !socket->waitForConnected() ) - cError() << "Could not connect to paste server"; - else - { - cDebug() << "Connected to paste server"; - - socket->write( pasteData ); - - if ( !socket->waitForBytesWritten() ) - cError() << "Could not write to paste server"; - else - { - cDebug() << "Paste data written to paste server"; - - if ( !socket->waitForReadyRead() ) - cError() << "No data from paste server"; - else - { - cDebug() << "Reading response from paste server"; - - char resp[1024]; - socket->readLine(resp, 1024); - socket->close(); - - QString pasteUrl = QString( resp ) ; - QString pasteUrlMsg = QString( pasteUrlFmt ).arg( pasteUrl ); - - cDebug() << pasteUrlMsg; - - QMessageBox* pasteUrlMsgBox = new QMessageBox(); - pasteUrlMsgBox->setIcon( QMessageBox::Critical ); - pasteUrlMsgBox->setWindowTitle( tr( pasteUrlTitle ) ); - pasteUrlMsgBox->setStandardButtons( QMessageBox::Close ); - pasteUrlMsgBox->setText( pasteUrlMsg ); - pasteUrlMsgBox->show(); - - connect( pasteUrlMsgBox, &QMessageBox::buttonClicked, qApp, &QApplication::quit ); - } - } - } - } + QApplication::quit(); + return; } + + QFile pasteSourceFile( Logger::logFile() ); + if ( !pasteSourceFile.open( QIODevice::ReadOnly | QIODevice::Text ) ) + { + cError() << "Could not open log file"; + return; + } + + QByteArray pasteData; + while ( !pasteSourceFile.atEnd() ) + { + pasteData += pasteSourceFile.readLine(); + } + + QTcpSocket* socket = new QTcpSocket(msgBox); + socket->connectToHost( ficheHost, fichePort ); + + if ( !socket->waitForConnected() ) + { + cError() << "Could not connect to paste server"; + socket->close(); + return; + } + + cDebug() << "Connected to paste server"; + + socket->write( pasteData ); + + if ( !socket->waitForBytesWritten() ) + { + cError() << "Could not write to paste server"; + socket->close(); + return; + } + + cDebug() << "Paste data written to paste server"; + + if ( !socket->waitForReadyRead() ) + { + cError() << "No data from paste server"; + socket->close(); + return; + } + + cDebug() << "Reading response from paste server"; + + char resp[1024]; + socket->readLine(resp, 1024); + socket->close(); + + QString pasteUrl = QString( resp ) ; + QString pasteUrlMsg = QString( pasteUrlFmt ).arg( pasteUrl ); + + cDebug() << pasteUrlMsg; + + QMessageBox* pasteUrlMsgBox = new QMessageBox(); + pasteUrlMsgBox->setIcon( QMessageBox::Critical ); + pasteUrlMsgBox->setWindowTitle( pasteUrlTitle ); + pasteUrlMsgBox->setStandardButtons( QMessageBox::Close ); + pasteUrlMsgBox->setText( pasteUrlMsg ); + pasteUrlMsgBox->show(); + + connect( pasteUrlMsgBox, &QMessageBox::buttonClicked, qApp, &QApplication::quit ); }); } From c90d3b201690d5bb33b7dc842fcfaeb0fc122451 Mon Sep 17 00:00:00 2001 From: bill-auger Date: Sun, 30 Jun 2019 05:58:35 -0400 Subject: [PATCH 006/302] squashme WIP upload log to paste server - more error checks and validations --- src/libcalamaresui/ViewManager.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/libcalamaresui/ViewManager.cpp b/src/libcalamaresui/ViewManager.cpp index 0efc7080d..b0f2b00a8 100644 --- a/src/libcalamaresui/ViewManager.cpp +++ b/src/libcalamaresui/ViewManager.cpp @@ -35,7 +35,9 @@ #include #include #include +#include #include +#include namespace Calamares { @@ -288,12 +290,21 @@ quint16 fichePort = 9999; // TODO: config var cDebug() << "Reading response from paste server"; - char resp[1024]; - socket->readLine(resp, 1024); + char resp[1024]; resp[0] = '\0'; + qint64 nBytesRead = socket->readLine(resp, 1024); socket->close(); - QString pasteUrl = QString( resp ) ; - QString pasteUrlMsg = QString( pasteUrlFmt ).arg( pasteUrl ); + QUrl pasteUrl = QUrl( QString( resp ).trimmed(), QUrl::StrictMode ); + QString pasteUrlStr = pasteUrl.toString() ; + QRegularExpression pasteUrlRegex( "^http[s]?://" + ficheHost ); + QString pasteUrlMsg = QString( pasteUrlFmt ).arg( pasteUrlStr ); + + if ( nBytesRead < 8 || !pasteUrl.isValid() || + !pasteUrlRegex.match( pasteUrlStr ).hasMatch() ) + { + cError() << "No data from paste server"; + return; + } cDebug() << pasteUrlMsg; From 938b1ac4aabaaabf1158f5341ca3d4bf005c3650 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 4 Jul 2019 11:47:27 +0200 Subject: [PATCH 007/302] [libcalamares] Make API more type-explicit with std::chrono - Having an int timeoutSec is suggestive -- it's probably a number of seconds -- but having an explicit type that says it's seconds is better. - Doesn't compile, because the implementation and consumers have not changed. --- src/libcalamares/utils/CalamaresUtilsSystem.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.h b/src/libcalamares/utils/CalamaresUtilsSystem.h index c17d52e93..734dbff4b 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.h +++ b/src/libcalamares/utils/CalamaresUtilsSystem.h @@ -27,6 +27,8 @@ #include #include +#include + namespace CalamaresUtils { class ProcessResult : public QPair< int, QString > @@ -138,7 +140,7 @@ public: const QStringList &args, const QString& workingPath = QString(), const QString& stdInput = QString(), - int timeoutSec = 0 ); + std::chrono::seconds timeoutSec = std::chrono::seconds(0) ); /** @brief Convenience wrapper for runCommand(). * Runs the command in the location specified through the boolean @@ -149,7 +151,7 @@ public: const QStringList &args, const QString& workingPath = QString(), const QString& stdInput = QString(), - int timeoutSec = 0 ) + std::chrono::seconds timeoutSec = std::chrono::seconds(0) ) { return runCommand( m_doChroot ? RunLocation::RunInTarget : RunLocation::RunInHost, @@ -163,7 +165,7 @@ public: inline int targetEnvCall( const QStringList& args, const QString& workingPath = QString(), const QString& stdInput = QString(), - int timeoutSec = 0 ) + std::chrono::seconds timeoutSec = std::chrono::seconds(0) ) { return targetEnvCommand( args, workingPath, stdInput, timeoutSec ).first; } @@ -172,7 +174,7 @@ public: inline int targetEnvCall( const QString& command, const QString& workingPath = QString(), const QString& stdInput = QString(), - int timeoutSec = 0 ) + std::chrono::seconds timeoutSec = std::chrono::seconds(0) ) { return targetEnvCall( QStringList{ command }, workingPath, stdInput, timeoutSec ); } @@ -185,7 +187,7 @@ public: QString& output, const QString& workingPath = QString(), const QString& stdInput = QString(), - int timeoutSec = 0 ) + std::chrono::seconds timeoutSec = std::chrono::seconds(0) ) { auto r = targetEnvCommand( args, workingPath, stdInput, timeoutSec ); output = r.second; @@ -200,7 +202,7 @@ public: QString& output, const QString& workingPath = QString(), const QString& stdInput = QString(), - int timeoutSec = 0 ) + std::chrono::seconds timeoutSec = std::chrono::seconds(0) ) { return targetEnvOutput( QStringList{ command }, output, workingPath, stdInput, timeoutSec ); } From 91644b4ba22b837a7c1f5927f0065d8e51592775 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 4 Jul 2019 11:50:14 +0200 Subject: [PATCH 008/302] [libcalamares] Partially fix implementation of timeout - Adjust most call sites to use std::chrono::duration, - Call to QProcess::waitForFinished() needs work, since that takes milliseconds. --- src/libcalamares/utils/CalamaresUtilsSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.cpp b/src/libcalamares/utils/CalamaresUtilsSystem.cpp index 5990fbc42..73e457239 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.cpp +++ b/src/libcalamares/utils/CalamaresUtilsSystem.cpp @@ -152,7 +152,7 @@ System::runCommand( const QStringList& args, const QString& workingPath, const QString& stdInput, - int timeoutSec ) + std::chrono::seconds timeoutSec ) { QString output; From ca58b67eb95d7f4488e4dc662a8d09c6724dab11 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 6 Jul 2019 01:16:28 +0200 Subject: [PATCH 009/302] Changes: post-release housekeeping --- CHANGES | 11 ++++++++++- CMakeLists.txt | 4 ++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 37dc7a71c..a73684e6a 100644 --- a/CHANGES +++ b/CHANGES @@ -3,7 +3,16 @@ 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.11 (unreleased) # +# 3.2.12 (unreleased) # + +This release contains contributions from (alphabetically by first name): + +## Core ## + +## Modules ## + + +# 3.2.11 (2019-07-06) # This release contains contributions from (alphabetically by first name): - No other contributors this time around. diff --git a/CMakeLists.txt b/CMakeLists.txt index ca2a6f98a..cae89fc91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,10 +37,10 @@ cmake_minimum_required( VERSION 3.2 FATAL_ERROR ) project( CALAMARES - VERSION 3.2.11 + VERSION 3.2.12 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 5b4e1d1686fea0d0477f9e2ba48f1554a57c9d4e Mon Sep 17 00:00:00 2001 From: embar- Date: Sat, 27 Jul 2019 14:38:00 +0300 Subject: [PATCH 010/302] add missing ";" in calamares.desktop --- calamares.desktop.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/calamares.desktop.in b/calamares.desktop.in index 0c4041bcb..9bfbf8fd9 100644 --- a/calamares.desktop.in +++ b/calamares.desktop.in @@ -3,7 +3,7 @@ Type=Application Version=1.0 Name=Install System GenericName=System Installer -Keywords=calamares;system;installer +Keywords=calamares;system;installer; TryExec=calamares Exec=pkexec /usr/bin/calamares Comment=Calamares — System Installer From 3bd73a97ce0bdf80bb749a14e58a19f45e9e14d6 Mon Sep 17 00:00:00 2001 From: embar- Date: Sat, 27 Jul 2019 14:40:39 +0300 Subject: [PATCH 011/302] add missing ";" in calamares.desktop --- calamares.desktop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/calamares.desktop b/calamares.desktop index 954c77123..47dd281e5 100644 --- a/calamares.desktop +++ b/calamares.desktop @@ -3,7 +3,7 @@ Type=Application Version=1.0 Name=Install System GenericName=System Installer -Keywords=calamares;system;installer +Keywords=calamares;system;installer; TryExec=calamares Exec=pkexec /usr/bin/calamares Comment=Calamares — System Installer From 6aec65ec7065fcdc6a11408d5ae1cdf40855e319 Mon Sep 17 00:00:00 2001 From: Calamares CI Date: Mon, 29 Jul 2019 13:29:03 +0200 Subject: [PATCH 012/302] i18n: [calamares] Automatic merge of Transifex translations --- lang/calamares_ar.ts | 148 +++++--- lang/calamares_ast.ts | 150 +++++--- lang/calamares_be.ts | 148 +++++--- lang/calamares_bg.ts | 148 +++++--- lang/calamares_ca.ts | 148 +++++--- lang/calamares_ca@valencia.ts | 148 +++++--- lang/calamares_cs_CZ.ts | 148 +++++--- lang/calamares_da.ts | 148 +++++--- lang/calamares_de.ts | 154 +++++--- lang/calamares_el.ts | 148 +++++--- lang/calamares_en.ts | 148 +++++--- lang/calamares_en_GB.ts | 148 +++++--- lang/calamares_eo.ts | 148 +++++--- lang/calamares_es.ts | 148 +++++--- lang/calamares_es_MX.ts | 148 +++++--- lang/calamares_es_PR.ts | 148 +++++--- lang/calamares_et.ts | 156 +++++--- lang/calamares_eu.ts | 148 +++++--- lang/calamares_fa.ts | 148 +++++--- lang/calamares_fi_FI.ts | 148 +++++--- lang/calamares_fr.ts | 148 +++++--- lang/calamares_fr_CH.ts | 148 +++++--- lang/calamares_gl.ts | 148 +++++--- lang/calamares_gu.ts | 148 +++++--- lang/calamares_he.ts | 148 +++++--- lang/calamares_hi.ts | 647 ++++++++++++++++++---------------- lang/calamares_hr.ts | 148 +++++--- lang/calamares_hu.ts | 156 +++++--- lang/calamares_id.ts | 148 +++++--- lang/calamares_is.ts | 148 +++++--- lang/calamares_it_IT.ts | 148 +++++--- lang/calamares_ja.ts | 148 +++++--- lang/calamares_kk.ts | 148 +++++--- lang/calamares_kn.ts | 148 +++++--- lang/calamares_ko.ts | 148 +++++--- lang/calamares_lo.ts | 148 +++++--- lang/calamares_lt.ts | 148 +++++--- lang/calamares_mk.ts | 148 +++++--- lang/calamares_mr.ts | 148 +++++--- lang/calamares_nb.ts | 148 +++++--- lang/calamares_ne_NP.ts | 148 +++++--- lang/calamares_nl.ts | 148 +++++--- lang/calamares_pl.ts | 148 +++++--- lang/calamares_pt_BR.ts | 148 +++++--- lang/calamares_pt_PT.ts | 148 +++++--- lang/calamares_ro.ts | 148 +++++--- lang/calamares_ru.ts | 289 ++++++++------- lang/calamares_sk.ts | 148 +++++--- lang/calamares_sl.ts | 148 +++++--- lang/calamares_sq.ts | 148 +++++--- lang/calamares_sr.ts | 148 +++++--- lang/calamares_sr@latin.ts | 148 +++++--- lang/calamares_sv.ts | 148 +++++--- lang/calamares_th.ts | 148 +++++--- lang/calamares_tr_TR.ts | 148 +++++--- lang/calamares_uk.ts | 148 +++++--- lang/calamares_ur.ts | 148 +++++--- lang/calamares_uz.ts | 148 +++++--- lang/calamares_zh_CN.ts | 148 +++++--- lang/calamares_zh_TW.ts | 148 +++++--- 60 files changed, 6213 insertions(+), 3331 deletions(-) diff --git a/lang/calamares_ar.ts b/lang/calamares_ar.ts index 60f47f127..c512e316b 100644 --- a/lang/calamares_ar.ts +++ b/lang/calamares_ar.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,159 +226,155 @@ Calamares::ViewManager - + &Back &رجوع - - + &Next &التالي - - + &Cancel &إلغاء - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. الغاء الـ تثبيت من دون احداث تغيير في النظام - + Setup Failed - + 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 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> - + &Set up now - + &Set up - + &Install &ثبت - + Setup is complete. Close the setup program. - + 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. أتريد إلغاء عمليّة التّثبيت الحاليّة؟ سيخرج المثبّت وتضيع كلّ التّغييرات. - + &Yes &نعم - + &No &لا - + &Close &اغلاق - + Continue with setup? الإستمرار في التثبيت؟ - + 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> مثبّت %1 على وشك بإجراء تعديلات على قرصك لتثبيت %2.<br/><strong>لن تستطيع التّراجع عن هذا.</strong> - + &Install now &ثبت الأن - + Go &back &إرجع - + &Done - + The installation is complete. Close the installer. اكتمل التثبيت , اغلق المثبِت - + Error خطأ - + Installation Failed فشل التثبيت @@ -1289,6 +1285,22 @@ The installer will quit and all changes will be lost. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1512,6 +1524,42 @@ The installer will quit and all changes will be lost. الموقع + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2219,65 +2267,65 @@ The installer will quit and all changes will be lost. 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. @@ -2326,7 +2374,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_ast.ts b/lang/calamares_ast.ts index f3a613d35..75702a383 100644 --- a/lang/calamares_ast.ts +++ b/lang/calamares_ast.ts @@ -135,7 +135,7 @@ Programmed job failure was explicitly requested. - + El fallu del trabayu programáu solicitóse esplicitamente. @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). Esperando por %n móduluEsperando por %n módulos - + (%n second(s)) (%n segundu)(%n segundos) - + System-requirements checking is complete. Completóse la comprobación de los requirimientos del sistema. @@ -226,160 +226,156 @@ Calamares::ViewManager - + &Back &Atrás - - + &Next &Siguiente - - + &Cancel &Encaboxar - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. Encaboxa la instalación ensin camudar el sistema. - + Setup Failed - + Calamares Initialization Failed Falló l'aniciu de Calamares - + %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 nun pue instalase. Calamares nun foi a cargar tolos módulos configuraos. Esto ye un problema col mou nel que la distribución usa Calamares. - + <br/>The following modules could not be loaded: <br/>Nun pudieron cargase los módulos de darréu: - + Continue with installation? ¿Siguir cola instalación? - + 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> El programa d'instalación de %1 ta a piques de facer cambeos nel discu pa configurar %2.<br/><strong>Nun vas ser a desfacer estos cambeos.<strong> - + &Set up now - + &Set up - + &Install &Instalar - + Setup is complete. Close the setup program. Completóse la configuración. Zarra'l programa de configuración. - + Cancel setup? ¿Encaboxar la configuración? - + Cancel installation? ¿Encaboxar la instalación? - + Do you really want to cancel the current setup process? The setup program will quit and all changes will be lost. ¿De xuru que quies encaboxar el procesu actual de configuración? El programa de configuración va colar y van perdese tolos cambeos. - + Do you really want to cancel the current install process? The installer will quit and all changes will be lost. ¿De xuru que quies encaboxar el procesu actual d'instalación? L'instalador va colar y van perdese tolos cambeos. - + &Yes &Sí - + &No &Non - + &Close &Zarrar - + Continue with setup? ¿Siguir cola instalación? - + 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> L'instalador de %1 ta a piques de facer cambeos nel discu pa instalar %2.<br/><strong>Nun vas ser a desfacer esos cambeos.</strong> - + &Install now &Instalar agora - + Go &back Dir p'&atrás - + &Done &Fecho - + The installation is complete. Close the installer. Completóse la instalación. Zarra l'instalador. - + Error Fallu - + Installation Failed Falló la instalación @@ -1290,6 +1286,22 @@ L'instalador va colar y van perdese tolos cambeos. Nun pudo escribise nel ficheru <code>%1</code>. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1513,6 +1525,42 @@ L'instalador va colar y van perdese tolos cambeos. Allugamientu + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2220,14 +2268,14 @@ L'instalador va colar y van perdese tolos cambeos. ProcessResult - + There was no output from the command. El comandu nun produxo denguna salida. - + Output: @@ -2236,52 +2284,52 @@ Salida: - + External command crashed. El comandu esternu cascó. - + Command <i>%1</i> crashed. El comandu <i>%1</i> cascó. - + External command failed to start. El comandu esternu falló al aniciar. - + Command <i>%1</i> failed to start. El comandu <i>%1</i> falló al aniciar. - + Internal error when starting command. Fallu internu al aniciar el comandu. - + Bad parameters for process job call. Los parámetros son incorreutos pa la llamada del trabayu de procesos. - + External command failed to finish. El comandu esternu finó al finar. - + Command <i>%1</i> failed to finish in %2 seconds. El comandu <i>%1</i> falló al finar en %2 segundos. - + External command finished with errors. El comandu esternu finó con fallos. - + Command <i>%1</i> finished with exit code %2. El comandu <i>%1</i> finó col códigu de salida %2. @@ -2330,7 +2378,7 @@ Salida: - + Requirements checking for module <i>%1</i> is complete. Completóse la comprobación de requirimientos del módulu <i>%1</i> diff --git a/lang/calamares_be.ts b/lang/calamares_be.ts index 4fe3c6da9..543313cfc 100644 --- a/lang/calamares_be.ts +++ b/lang/calamares_be.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,158 +226,154 @@ Calamares::ViewManager - + &Back - - + &Next - - + &Cancel - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. - + Setup Failed - + 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 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> - + &Set up now - + &Set up - + &Install - + Setup is complete. Close the setup program. - + 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. - + &Yes - + &No - + &Close - + Continue with setup? - + 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> - + &Install now - + Go &back - + &Done - + The installation is complete. Close the installer. - + Error - + Installation Failed @@ -1288,6 +1284,22 @@ The installer will quit and all changes will be lost. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1511,6 +1523,42 @@ The installer will quit and all changes will be lost. + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2218,65 +2266,65 @@ The installer will quit and all changes will be lost. 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. @@ -2325,7 +2373,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_bg.ts b/lang/calamares_bg.ts index b69a56a67..b4d466017 100644 --- a/lang/calamares_bg.ts +++ b/lang/calamares_bg.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,159 +226,155 @@ Calamares::ViewManager - + &Back &Назад - - + &Next &Напред - - + &Cancel &Отказ - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. Отказ от инсталацията без промяна на системата. - + Setup Failed - + Calamares Initialization Failed Инициализацията на Calamares се провали - + %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 не може да се инсталира. Calamares не можа да зареди всичките конфигурирани модули. Това е проблем с начина, по който Calamares е използван от дистрибуцията. - + <br/>The following modules could not be loaded: <br/>Следните модули не могат да се заредят: - + 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> - + &Set up now - + &Set up - + &Install &Инсталирай - + Setup is complete. Close the setup program. - + 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. Наистина ли искате да отмените текущият процес на инсталиране? Инсталатора ще прекъсне и всичките промени ще бъдат загубени. - + &Yes &Да - + &No &Не - + &Close &Затвори - + Continue with setup? Продължаване? - + 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> Инсталатора на %1 ще направи промени по вашия диск за да инсталира %2. <br><strong>Промените ще бъдат окончателни.</strong> - + &Install now &Инсталирай сега - + Go &back В&ръщане - + &Done &Готово - + The installation is complete. Close the installer. Инсталацията е завършена. Затворете инсталаторa. - + Error Грешка - + Installation Failed Неуспешна инсталация @@ -1289,6 +1285,22 @@ The installer will quit and all changes will be lost. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1512,6 +1524,42 @@ The installer will quit and all changes will be lost. Местоположение + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2219,13 +2267,13 @@ The installer will quit and all changes will be lost. ProcessResult - + There was no output from the command. - + Output: @@ -2234,52 +2282,52 @@ 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. @@ -2328,7 +2376,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_ca.ts b/lang/calamares_ca.ts index 7272159c7..de88d550c 100644 --- a/lang/calamares_ca.ts +++ b/lang/calamares_ca.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). S'espera %n mòdul.S'esperen %n mòduls. - + (%n second(s)) (%n segon)(%n segons) - + System-requirements checking is complete. S'ha completat la comprovació dels requeriments del sistema. @@ -226,160 +226,156 @@ Calamares::ViewManager - + &Back &Enrere - - + &Next &Següent - - + &Cancel &Cancel·la - - + Cancel setup without changing the system. Cancel·la la configuració sense canviar el sistema. - - + Cancel installation without changing the system. Cancel·leu la instal·lació sense canviar el sistema. - + Setup Failed Ha fallat la configuració. - + Calamares Initialization Failed Ha fallat la inicialització de Calamares - + %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. No es pot instal·lar %1. El Calamares no ha pogut carregar tots els mòduls configurats. Aquest és un problema amb la manera com el Calamares és utilitzat per la distribució. - + <br/>The following modules could not be loaded: <br/>No s'han pogut carregar els mòduls següents: - + Continue with installation? Voleu continuar la instal·lació? - + 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> El programa de configuració %1 està a punt de fer canvis al disc per tal de configurar %2.<br/><strong>No podreu desfer aquests canvis.</strong> - + &Set up now Con&figura-ho ara - + &Set up Con&figura-ho - + &Install &Instal·la - + Setup is complete. Close the setup program. La configuració s'ha acabat. Tanqueu el programa de configuració. - + Cancel setup? Voleu cancel·lar la configuració? - + Cancel installation? Cancel·lar la instal·lació? - + Do you really want to cancel the current setup process? The setup program will quit and all changes will be lost. Realment voleu cancel·lar el procés de configuració actual? El programa de configuració es tancarà i es perdran tots els canvis. - + Do you really want to cancel the current install process? The installer will quit and all changes will be lost. Voleu cancel·lar el procés d'instal·lació actual? L'instal·lador es tancarà i tots els canvis es perdran. - + &Yes &Sí - + &No &No - + &Close Tan&ca - + Continue with setup? Voleu continuar la configuració? - + 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> L'instal·lador de %1 està a punt de fer canvis al disc per tal d'instal·lar-hi %2.<br/><strong>No podreu desfer aquests canvis.</strong> - + &Install now &Instal·la ara - + Go &back Ves &enrere - + &Done &Fet - + The installation is complete. Close the installer. La instal·lació s'ha acabat. Tanqueu l'instal·lador. - + Error Error - + Installation Failed La instal·lació ha fallat @@ -1290,6 +1286,22 @@ L'instal·lador es tancarà i tots els canvis es perdran. No s'ha pogut escriure al fitxer <code>%1</code>. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + Es creen initramfs amb mkinitcpio. + + + + InitramfsJob + + + Creating initramfs. + Es creen initramfs. + + InteractiveTerminalPage @@ -1513,6 +1525,42 @@ L'instal·lador es tancarà i tots els canvis es perdran. Ubicació + + LuksBootKeyFileJob + + + Configuring LUKS key file. + Es configura el fitxer de clau LUKS. + + + + + No partitions are defined. + No s'ha definit cap partició. + + + + + + Encrypted rootfs setup error + Error de configuració de rootfs encriptat. + + + + Root partition %1 is LUKS but no passphrase has been set. + La partició d'arrel %1 és LUKS però no se n'ha establert cap contrasenya. + + + + Could not create LUKS key file for root partition %1. + No s'ha pogut crear el fitxer de clau de LUKS per a la partició d'arrel %1. + + + + Could configure LUKS key file on partition %1. + S'ha pogut configurar el fitxer de clau de LUKS a la partició %1. + + NetInstallPage @@ -2220,14 +2268,14 @@ L'instal·lador es tancarà i tots els canvis es perdran. ProcessResult - + There was no output from the command. No hi ha hagut sortida de l'ordre. - + Output: @@ -2236,52 +2284,52 @@ Sortida: - + External command crashed. L'ordre externa ha fallat. - + Command <i>%1</i> crashed. L'ordre <i>%1</i> ha fallat. - + External command failed to start. L'ordre externa no s'ha pogut iniciar. - + Command <i>%1</i> failed to start. L'ordre <i>%1</i> no s'ha pogut iniciar. - + Internal error when starting command. Error intern en iniciar l'ordre. - + Bad parameters for process job call. Paràmetres incorrectes per a la crida de la tasca del procés. - + External command failed to finish. L'ordre externa no ha acabat correctament. - + Command <i>%1</i> failed to finish in %2 seconds. L'ordre <i>%1</i> no ha pogut acabar en %2 segons. - + External command finished with errors. L'ordre externa ha acabat amb errors. - + Command <i>%1</i> finished with exit code %2. L'ordre <i>%1</i> ha acabat amb el codi de sortida %2. @@ -2330,7 +2378,7 @@ Sortida: (sense punt de muntatge) - + Requirements checking for module <i>%1</i> is complete. S'ha completat la comprovació dels requeriments per al mòdul <i>%1</i>. diff --git a/lang/calamares_ca@valencia.ts b/lang/calamares_ca@valencia.ts index f3a9b1166..3d7448670 100644 --- a/lang/calamares_ca@valencia.ts +++ b/lang/calamares_ca@valencia.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,158 +226,154 @@ Calamares::ViewManager - + &Back - - + &Next - - + &Cancel - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. - + Setup Failed - + 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 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> - + &Set up now - + &Set up - + &Install - + Setup is complete. Close the setup program. - + 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. - + &Yes - + &No - + &Close - + Continue with setup? - + 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> - + &Install now - + Go &back - + &Done - + The installation is complete. Close the installer. - + Error - + Installation Failed @@ -1288,6 +1284,22 @@ The installer will quit and all changes will be lost. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1511,6 +1523,42 @@ The installer will quit and all changes will be lost. + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2218,65 +2266,65 @@ The installer will quit and all changes will be lost. 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. @@ -2325,7 +2373,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_cs_CZ.ts b/lang/calamares_cs_CZ.ts index 1f6ef2129..beb4142fe 100644 --- a/lang/calamares_cs_CZ.ts +++ b/lang/calamares_cs_CZ.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). Čeká se na %n modulČeká se na %n modulyČeká se na %n modulůČeká se na %n moduly - + (%n second(s)) (%n sekundu)(%n sekundy)(%n sekund)(%n sekundy) - + System-requirements checking is complete. Kontrola požadavků na systém dokončena. @@ -226,160 +226,156 @@ Calamares::ViewManager - + &Back &Zpět - - + &Next &Další - - + &Cancel &Storno - - + Cancel setup without changing the system. Zrušit nastavení bez změny v systému. - - + Cancel installation without changing the system. Zrušení instalace bez provedení změn systému. - + Setup Failed Nastavení se nezdařilo - + Calamares Initialization Failed Inicializace Calamares se nezdařila - + %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 nemůže být nainstalováno. Calamares se nepodařilo načíst všechny nastavené moduly. Toto je problém způsobu použití Calamares ve vámi používané distribuci. - + <br/>The following modules could not be loaded: <br/> Následující moduly se nepodařilo načíst: - + Continue with installation? Pokračovat v instalaci? - + 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> Instalátor %1 provede změny na datovém úložišti, aby bylo nainstalováno %2.<br/><strong>Změny nebude možné vrátit zpět.</strong> - + &Set up now Na&stavit nyní - + &Set up Na&stavit - + &Install Na&instalovat - + Setup is complete. Close the setup program. Nastavení je dokončeno. Ukončete nastavovací program. - + Cancel setup? Zrušit nastavování? - + Cancel installation? Přerušit instalaci? - + Do you really want to cancel the current setup process? The setup program will quit and all changes will be lost. Opravdu chcete přerušit instalaci? Instalační program bude ukončen a všechny změny ztraceny. - + Do you really want to cancel the current install process? The installer will quit and all changes will be lost. Opravdu chcete instalaci přerušit? Instalační program bude ukončen a všechny změny ztraceny. - + &Yes &Ano - + &No &Ne - + &Close &Zavřít - + Continue with setup? Pokračovat s instalací? - + 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> Instalátor %1 provede změny na datovém úložišti, aby bylo nainstalováno %2.<br/><strong>Změny nebude možné vrátit zpět.</strong> - + &Install now &Spustit instalaci - + Go &back Jít &zpět - + &Done &Hotovo - + The installation is complete. Close the installer. Instalace je dokončena. Ukončete instalátor. - + Error Chyba - + Installation Failed Instalace se nezdařila @@ -1290,6 +1286,22 @@ Instalační program bude ukončen a všechny změny ztraceny. Nedaří se zapsat do souboru <code>%1</code>. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + Vytváření initramfs pomocí mkinitcpio. + + + + InitramfsJob + + + Creating initramfs. + Vytváření initramfs. + + InteractiveTerminalPage @@ -1513,6 +1525,42 @@ Instalační program bude ukončen a všechny změny ztraceny. Poloha + + LuksBootKeyFileJob + + + Configuring LUKS key file. + Nastavování souboru s klíčem pro LUKS šifrování. + + + + + No partitions are defined. + + + + + + + Encrypted rootfs setup error + Chyba nastavení šifrovaného kořenového oddílu + + + + Root partition %1 is LUKS but no passphrase has been set. + + + + + Could not create LUKS key file for root partition %1. + + + + + Could configure LUKS key file on partition %1. + + + NetInstallPage @@ -2220,14 +2268,14 @@ Instalační program bude ukončen a všechny změny ztraceny. ProcessResult - + There was no output from the command. Příkaz neposkytl žádný výstup. - + Output: @@ -2236,52 +2284,52 @@ Výstup: - + External command crashed. Vnější příkaz byl neočekávaně ukončen. - + Command <i>%1</i> crashed. Příkaz <i>%1</i> byl neočekávaně ukončen. - + External command failed to start. Vnější příkaz se nepodařilo spustit. - + Command <i>%1</i> failed to start. Příkaz <i>%1</i> se nepodařilo spustit. - + Internal error when starting command. Vnitřní chyba při spouštění příkazu. - + Bad parameters for process job call. Chybné parametry volání úlohy procesu. - + External command failed to finish. Vnější příkaz se nepodařilo dokončit. - + Command <i>%1</i> failed to finish in %2 seconds. Příkaz <i>%1</i> se nepodařilo dokončit do %2 sekund. - + External command finished with errors. Vnější příkaz skončil s chybami. - + Command <i>%1</i> finished with exit code %2. Příkaz <i>%1</i> skončil s návratovým kódem %2. @@ -2330,7 +2378,7 @@ Výstup: (žádný přípojný bod) - + Requirements checking for module <i>%1</i> is complete. Kontrola požadavků pro modul <i>%1</i> dokončena. diff --git a/lang/calamares_da.ts b/lang/calamares_da.ts index 1787fe3bf..c4e9a0456 100644 --- a/lang/calamares_da.ts +++ b/lang/calamares_da.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). Venter på %n modul.Venter på %n moduler. - + (%n second(s)) (%n sekund)(%n sekunder) - + System-requirements checking is complete. Tjek af systemkrav er fuldført. @@ -226,160 +226,156 @@ Calamares::ViewManager - + &Back &Tilbage - - + &Next &Næste - - + &Cancel &Annullér - - + Cancel setup without changing the system. Annullér opsætningen uden at ændre systemet. - - + Cancel installation without changing the system. Annullér installation uden at ændre systemet. - + Setup Failed Opsætningen mislykkedes - + Calamares Initialization Failed Initiering af Calamares mislykkedes - + %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 ikke installeres. Calamares kunne ikke indlæse alle de konfigurerede moduler. Det er et problem med den måde Calamares bruges på af distributionen. - + <br/>The following modules could not be loaded: <br/>Følgende moduler kunne ikke indlæses: - + Continue with installation? Fortsæt installationen? - + 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-opsætningsprogrammet er ved at foretage ændringer til din disk for at opsætte %2.<br/><strong>Det vil ikke være muligt at fortryde ændringerne.</strong> - + &Set up now &Sæt op nu - + &Set up &Sæt op - + &Install &Installér - + Setup is complete. Close the setup program. Opsætningen er fuldført. Luk opsætningsprogrammet. - + Cancel setup? Annullér opsætningen? - + Cancel installation? Annullér installationen? - + Do you really want to cancel the current setup process? The setup program will quit and all changes will be lost. Vil du virkelig annullere den igangværende opsætningsproces? Opsætningsprogrammet vil stoppe og alle ændringer vil gå tabt. - + Do you really want to cancel the current install process? The installer will quit and all changes will be lost. Vil du virkelig annullere den igangværende installationsproces? Installationsprogrammet vil stoppe og alle ændringer vil gå tabt. - + &Yes &Ja - + &No &Nej - + &Close &Luk - + Continue with setup? Fortsæt med opsætningen? - + 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> %1-installationsprogrammet er ved at foretage ændringer til din disk for at installere %2.<br/><strong>Det vil ikke være muligt at fortryde ændringerne.</strong> - + &Install now &Installér nu - + Go &back Gå &tilbage - + &Done &Færdig - + The installation is complete. Close the installer. Installationen er fuldført. Luk installationsprogrammet. - + Error Fejl - + Installation Failed Installation mislykkedes @@ -1290,6 +1286,22 @@ Installationsprogrammet vil stoppe og alle ændringer vil gå tabt.Kunne ikke skrive til filen <code>%1</code>. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + Opretter initramfs med mkinitcpio. + + + + InitramfsJob + + + Creating initramfs. + Opretter initramfs. + + InteractiveTerminalPage @@ -1513,6 +1525,42 @@ Installationsprogrammet vil stoppe og alle ændringer vil gå tabt.Placering + + LuksBootKeyFileJob + + + Configuring LUKS key file. + Konfigurerer LUKS-nøglefil. + + + + + No partitions are defined. + Der er ikke defineret nogen partitioner. + + + + + + Encrypted rootfs setup error + Fejl ved opsætning af krypteret rootfs + + + + Root partition %1 is LUKS but no passphrase has been set. + Rodpartitionen %1 er LUKS men der er ikke indstillet nogen adgangskode. + + + + Could not create LUKS key file for root partition %1. + Kunne ikke oprette LUKS-nøglefil for rodpartitionen %1. + + + + Could configure LUKS key file on partition %1. + Kunne ikke konfigurere LUKS-nøglefil på partitionen %1. + + NetInstallPage @@ -2220,14 +2268,14 @@ Installationsprogrammet vil stoppe og alle ændringer vil gå tabt. ProcessResult - + There was no output from the command. Der var ikke nogen output fra kommandoen. - + Output: @@ -2236,52 +2284,52 @@ Output: - + External command crashed. Ekstern kommando holdt op med at virke. - + Command <i>%1</i> crashed. Kommandoen <i>%1</i> holdte op med at virke. - + External command failed to start. Ekstern kommando kunne ikke starte. - + Command <i>%1</i> failed to start. Kommandoen <i>%1</i> kunne ikke starte. - + Internal error when starting command. Intern fejl ved start af kommando. - + Bad parameters for process job call. Ugyldige parametre til kald af procesjob. - + External command failed to finish. Ekstern kommando blev ikke færdig. - + Command <i>%1</i> failed to finish in %2 seconds. Kommandoen <i>%1</i> blev ikke færdig på %2 sekunder. - + External command finished with errors. Ekstern kommando blev færdig med fejl. - + Command <i>%1</i> finished with exit code %2. Kommandoen <i>%1</i> blev færdig med afslutningskoden %2. @@ -2330,7 +2378,7 @@ Output: (intet monteringspunkt) - + Requirements checking for module <i>%1</i> is complete. Tjek at krav for modulet <i>%1</i> er fuldført. diff --git a/lang/calamares_de.ts b/lang/calamares_de.ts index ce0435f95..997fb8f02 100644 --- a/lang/calamares_de.ts +++ b/lang/calamares_de.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). Warten auf %n Modul.Warten auf %n Modul(e). - + (%n second(s)) (%n Sekunde)(%n Sekunde(n)) - + System-requirements checking is complete. Die Überprüfung der Systemvoraussetzungen ist abgeschlossen. @@ -226,160 +226,156 @@ Calamares::ViewManager - + &Back &Zurück - - + &Next &Weiter - - + &Cancel &Abbrechen - - + Cancel setup without changing the system. Brechen Sie die Installation ab, ohne das System zu verändern. - - + Cancel installation without changing the system. Installation abbrechen, ohne das System zu verändern. - + Setup Failed Setup fehlgeschlagen - + Calamares Initialization Failed Initialisierung von Calamares fehlgeschlagen - + %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 kann nicht installiert werden. Calamares war nicht in der Lage, alle konfigurierten Module zu laden. Dieses Problem hängt mit der Art und Weise zusammen, wie Calamares von der jeweiligen Distribution eingesetzt wird. - + <br/>The following modules could not be loaded: <br/>Die folgenden Module konnten nicht geladen werden: - + Continue with installation? Installation fortsetzen? - + 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> Das %1 Installationsprogramm ist dabei, Änderungen an Ihrer Festplatte vorzunehmen, um %2 einzurichten.<br/><strong> Sie werden diese Änderungen nicht rückgängig machen können.</strong> - + &Set up now &Jetzt einrichten - + &Set up &Einrichten - + &Install &Installieren - + Setup is complete. Close the setup program. Setup ist abgeschlossen. Schließe das Installationsprogramm. - + Cancel setup? Installation abbrechen? - + Cancel installation? Installation abbrechen? - + Do you really want to cancel the current setup process? The setup program will quit and all changes will be lost. Wollen Sie wirklich die aktuelle Installation abbrechen? Dies wird das Installationsprogramm beenden und alle Änderungen gehen verloren. - + Do you really want to cancel the current install process? The installer will quit and all changes will be lost. Wollen Sie wirklich die aktuelle Installation abbrechen? Dies wird das Installationsprogramm beenden und alle Änderungen gehen verloren. - + &Yes &Ja - + &No &Nein - + &Close &Schließen - + Continue with setup? Setup fortsetzen? - + 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> Das %1 Installationsprogramm wird Änderungen an Ihrer Festplatte vornehmen, um %2 zu installieren.<br/><strong>Diese Änderungen können nicht rückgängig gemacht werden.</strong> - + &Install now Jetzt &installieren - + Go &back Gehe &zurück - + &Done &Erledigt - + The installation is complete. Close the installer. Die Installation ist abgeschlossen. Schließe das Installationsprogramm. - + Error Fehler - + Installation Failed Installation gescheitert @@ -1160,7 +1156,7 @@ Dies wird das Installationsprogramm beenden und alle Änderungen gehen verloren. Setup Complete - Installation komplett + Installation abgeschlossen @@ -1290,6 +1286,22 @@ Dies wird das Installationsprogramm beenden und alle Änderungen gehen verloren. Konnte nicht in die Datei <code>%1</code> schreiben. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + Erstelle initramfs mit mkinitcpio. + + + + InitramfsJob + + + Creating initramfs. + Erstelle initramfs. + + InteractiveTerminalPage @@ -1438,7 +1450,7 @@ Dies wird das Installationsprogramm beenden und alle Änderungen gehen verloren. Shows the complete license text - Zeigt den vollständigen Lizenztext an. + Zeigt den vollständigen Lizenztext an @@ -1513,6 +1525,42 @@ Dies wird das Installationsprogramm beenden und alle Änderungen gehen verloren. Standort + + LuksBootKeyFileJob + + + Configuring LUKS key file. + LUKS-Schlüsseldatei konfigurieren. + + + + + No partitions are defined. + Keine Partitionen definiert. + + + + + + Encrypted rootfs setup error + Verschlüsselter Rootfs-Setup-Fehler + + + + Root partition %1 is LUKS but no passphrase has been set. + Root-Partition %1 ist mit LUKS verschlüsselt, aber es wurde kein Passwort gesetzt. + + + + Could not create LUKS key file for root partition %1. + Konnte die LUKS-Schlüsseldatei für die Root-Partition %1 nicht erstellen. + + + + Could configure LUKS key file on partition %1. + Konnte die LUKS-Schlüsseldatei auf der Root-Partition %1 konfigurieren. + + NetInstallPage @@ -2220,14 +2268,14 @@ Dies wird das Installationsprogramm beenden und alle Änderungen gehen verloren. ProcessResult - + There was no output from the command. Dieser Befehl hat keine Ausgabe erzeugt. - + Output: @@ -2236,52 +2284,52 @@ Ausgabe: - + External command crashed. Externes Programm abgestürzt. - + Command <i>%1</i> crashed. Programm <i>%1</i> abgestürzt. - + External command failed to start. Externes Programm konnte nicht gestartet werden. - + Command <i>%1</i> failed to start. Das Programm <i>%1</i> konnte nicht gestartet werden. - + Internal error when starting command. Interner Fehler beim Starten des Programms. - + Bad parameters for process job call. Ungültige Parameter für Prozessaufruf. - + External command failed to finish. Externes Programm konnte nicht abgeschlossen werden. - + Command <i>%1</i> failed to finish in %2 seconds. Programm <i>%1</i> konnte nicht innerhalb von %2 Sekunden abgeschlossen werden. - + External command finished with errors. Externes Programm mit Fehlern beendet. - + Command <i>%1</i> finished with exit code %2. Befehl <i>%1</i> beendet mit Exit-Code %2. @@ -2330,7 +2378,7 @@ Ausgabe: (kein Einhängepunkt) - + Requirements checking for module <i>%1</i> is complete. Die Anforderungsprüfung für das Modul <i>%1</i> ist abgeschlossen. @@ -2462,7 +2510,7 @@ Ausgabe: Calamares cannot start KPMCore for the file-system resize job. - Calamares konnte KPMCore nicht zur Änderung der Dateisystemgröße starten. + Calamares kann KPMCore zur Änderung der Dateisystemgröße nicht starten. diff --git a/lang/calamares_el.ts b/lang/calamares_el.ts index e7b4d8131..f6351f912 100644 --- a/lang/calamares_el.ts +++ b/lang/calamares_el.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,159 +226,155 @@ Calamares::ViewManager - + &Back &Προηγούμενο - - + &Next &Επόμενο - - + &Cancel &Ακύρωση - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. Ακύρωση της εγκατάστασης χωρίς αλλαγές στο σύστημα. - + Setup Failed - + Calamares Initialization Failed Η αρχικοποίηση του Calamares απέτυχε - + %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 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> - + &Set up now - + &Set up - + &Install &Εγκατάσταση - + Setup is complete. Close the setup program. - + 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. Θέλετε πραγματικά να ακυρώσετε τη διαδικασία εγκατάστασης; Το πρόγραμμα εγκατάστασης θα τερματιστεί και όλες οι αλλαγές θα χαθούν. - + &Yes &Ναι - + &No &Όχι - + &Close &Κλείσιμο - + Continue with setup? Συνέχεια με την εγκατάσταση; - + 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> Το πρόγραμμα εγκατάστασης %1 θα κάνει αλλαγές στον δίσκο για να εγκαταστήσετε το %2.<br/><strong>Δεν θα είστε σε θέση να αναιρέσετε τις αλλαγές.</strong> - + &Install now &Εγκατάσταση τώρα - + Go &back Μετάβαση &πίσω - + &Done &Ολοκληρώθηκε - + The installation is complete. Close the installer. Η εγκτάσταση ολοκληρώθηκε. Κλείστε το πρόγραμμα εγκατάστασης. - + Error Σφάλμα - + Installation Failed Η εγκατάσταση απέτυχε @@ -1289,6 +1285,22 @@ The installer will quit and all changes will be lost. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1512,6 +1524,42 @@ The installer will quit and all changes will be lost. Τοποθεσία + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2219,65 +2267,65 @@ The installer will quit and all changes will be lost. 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. @@ -2326,7 +2374,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_en.ts b/lang/calamares_en.ts index 66d90f109..628f22a83 100644 --- a/lang/calamares_en.ts +++ b/lang/calamares_en.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). Waiting for %n module(s).Waiting for %n module(s). - + (%n second(s)) (%n second(s))(%n second(s)) - + System-requirements checking is complete. System-requirements checking is complete. @@ -226,160 +226,156 @@ Calamares::ViewManager - + &Back &Back - - + &Next &Next - - + &Cancel &Cancel - - + Cancel setup without changing the system. Cancel setup without changing the system. - - + Cancel installation without changing the system. Cancel installation without changing the system. - + Setup Failed Setup Failed - + Calamares Initialization Failed 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. %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: <br/>The following modules could not be loaded: - + 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> - + &Set up now &Set up now - + &Set up &Set up - + &Install &Install - + Setup is complete. Close the setup program. Setup is complete. Close the setup program. - + 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? The installer will quit and all changes will be lost. - + &Yes &Yes - + &No &No - + &Close &Close - + Continue with setup? Continue with setup? - + 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> - + &Install now &Install now - + Go &back Go &back - + &Done &Done - + The installation is complete. Close the installer. The installation is complete. Close the installer. - + Error Error - + Installation Failed Installation Failed @@ -1290,6 +1286,22 @@ The installer will quit and all changes will be lost. Could not write to file <code>%1</code>. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + Creating initramfs with mkinitcpio. + + + + InitramfsJob + + + Creating initramfs. + Creating initramfs. + + InteractiveTerminalPage @@ -1513,6 +1525,42 @@ The installer will quit and all changes will be lost. Location + + LuksBootKeyFileJob + + + Configuring LUKS key file. + Configuring LUKS key file. + + + + + No partitions are defined. + No partitions are defined. + + + + + + Encrypted rootfs setup error + Encrypted rootfs setup error + + + + Root partition %1 is LUKS but no passphrase has been set. + Root partition %1 is LUKS but no passphrase has been set. + + + + Could not create LUKS key file for root partition %1. + Could not create LUKS key file for root partition %1. + + + + Could configure LUKS key file on partition %1. + Could configure LUKS key file on partition %1. + + NetInstallPage @@ -2220,14 +2268,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: @@ -2236,52 +2284,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. @@ -2330,7 +2378,7 @@ Output: (no mount point) - + Requirements checking for module <i>%1</i> is complete. Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_en_GB.ts b/lang/calamares_en_GB.ts index 366b778b9..61d62d04a 100644 --- a/lang/calamares_en_GB.ts +++ b/lang/calamares_en_GB.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,159 +226,155 @@ Calamares::ViewManager - + &Back &Back - - + &Next &Next - - + &Cancel &Cancel - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. Cancel installation without changing the system. - + Setup Failed - + Calamares Initialization Failed Calamares Initialisation 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. %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: <br/>The following modules could not be loaded: - + 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> - + &Set up now - + &Set up - + &Install &Install - + Setup is complete. Close the setup program. - + 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 install process? The installer 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. - + &Yes &Yes - + &No &No - + &Close &Close - + Continue with setup? Continue with setup? - + 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> - + &Install now &Install now - + Go &back Go &back - + &Done &Done - + The installation is complete. Close the installer. The installation is complete. Close the installer. - + Error Error - + Installation Failed Installation Failed @@ -1289,6 +1285,22 @@ The installer will quit and all changes will be lost. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1512,6 +1524,42 @@ The installer will quit and all changes will be lost. 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2219,14 +2267,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: @@ -2235,52 +2283,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. @@ -2329,7 +2377,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_eo.ts b/lang/calamares_eo.ts index 86685fe8f..725791019 100644 --- a/lang/calamares_eo.ts +++ b/lang/calamares_eo.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,159 +226,155 @@ Calamares::ViewManager - + &Back - - + &Next - - + &Cancel &Nuligi - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. Nuligi instalado sen ŝanĝante la sistemo. - + Setup Failed - + 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 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> - + &Set up now - + &Set up - + &Install &Instali - + Setup is complete. Close the setup program. - + Cancel setup? - + Cancel installation? Nuligi instalado? - + 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. Ĉu vi vere volas nuligi la instalan procedon? La instalilo forlasos kaj ĉiuj ŝanĝoj perdos. - + &Yes &Jes - + &No &Ne - + &Close &Fermi - + Continue with setup? - + 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> - + &Install now &Instali nun - + Go &back - + &Done &Finita - + The installation is complete. Close the installer. - + Error Eraro - + Installation Failed @@ -1289,6 +1285,22 @@ La instalilo forlasos kaj ĉiuj ŝanĝoj perdos. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1512,6 +1524,42 @@ La instalilo forlasos kaj ĉiuj ŝanĝoj perdos. + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2219,65 +2267,65 @@ La instalilo forlasos kaj ĉiuj ŝanĝoj perdos. 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. @@ -2326,7 +2374,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_es.ts b/lang/calamares_es.ts index 2af1459f3..8c367e353 100644 --- a/lang/calamares_es.ts +++ b/lang/calamares_es.ts @@ -209,17 +209,17 @@ Para configurar el arranque desde un entorno BIOS, este instalador debe instalar Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -227,159 +227,155 @@ Para configurar el arranque desde un entorno BIOS, este instalador debe instalar Calamares::ViewManager - + &Back &Atrás - - + &Next &Siguiente - - + &Cancel &Cancelar - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. Cancelar instalación sin cambiar el sistema. - + Setup Failed - + Calamares Initialization Failed La inicialización de Calamares falló - + %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 no se pudo instalar. Calamares no fue capaz de cargar todos los módulos configurados. Esto es un problema con la forma en que Calamares es usado por la distribución - + <br/>The following modules could not be loaded: Los siguientes módulos no se pudieron cargar: - + 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> - + &Set up now - + &Set up - + &Install &Instalar - + Setup is complete. Close the setup program. - + Cancel setup? - + Cancel installation? ¿Cancelar la instalación? - + 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. ¿Realmente quiere cancelar el proceso de instalación? Saldrá del instalador y se perderán todos los cambios. - + &Yes &Sí - + &No &No - + &Close &Cerrar - + Continue with setup? ¿Continuar con la configuración? - + 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> El instalador %1 va a realizar cambios en su disco para instalar %2.<br/><strong>No podrá deshacer estos cambios.</strong> - + &Install now &Instalar ahora - + Go &back Regresar - + &Done &Hecho - + The installation is complete. Close the installer. La instalación se ha completado. Cierre el instalador. - + Error Error - + Installation Failed Error en la Instalación @@ -1290,6 +1286,22 @@ Saldrá del instalador y se perderán todos los cambios. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1513,6 +1525,42 @@ Saldrá del instalador y se perderán todos los cambios. Ubicación + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2220,14 +2268,14 @@ Saldrá del instalador y se perderán todos los cambios. ProcessResult - + There was no output from the command. No hubo salida del comando. - + Output: @@ -2236,52 +2284,52 @@ Salida: - + External command crashed. El comando externo falló. - + Command <i>%1</i> crashed. El comando <i>%1</i> falló. - + External command failed to start. El comando externo no se pudo iniciar. - + Command <i>%1</i> failed to start. El comando <i>%1</i> no se pudo iniciar. - + Internal error when starting command. Error interno al iniciar el comando. - + Bad parameters for process job call. Parámetros erróneos para la llamada de la tarea del procreso. - + External command failed to finish. El comando externo no se pudo finalizar. - + Command <i>%1</i> failed to finish in %2 seconds. El comando <i>%1</i> no se pudo finalizar en %2 segundos. - + External command finished with errors. El comando externo finalizó con errores. - + Command <i>%1</i> finished with exit code %2. El comando <i>%1</i> finalizó con un código de salida %2. @@ -2330,7 +2378,7 @@ Salida: (sin punto de montaje) - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_es_MX.ts b/lang/calamares_es_MX.ts index 4a698bd18..f3a9b2db1 100644 --- a/lang/calamares_es_MX.ts +++ b/lang/calamares_es_MX.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. Chequeo de requerimientos del sistema completado. @@ -226,160 +226,156 @@ Calamares::ViewManager - + &Back &Atrás - - + &Next &Siguiente - - + &Cancel &Cancelar - - + Cancel setup without changing the system. Cancelar la configuración sin cambiar el sistema. - - + Cancel installation without changing the system. Cancelar instalación sin cambiar el sistema. - + Setup Failed Fallo en la configuración. - + Calamares Initialization Failed La inicialización de Calamares ha fallado - + %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 no pudo ser instalado. Calamares no pudo cargar todos los módulos configurados. Este es un problema con la forma en que Calamares esta siendo usada por la distribución. - + <br/>The following modules could not be loaded: <br/>Los siguientes módulos no pudieron ser cargados: - + Continue with installation? ¿Continuar con la instalación? - + 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> El %1 programa de instalación esta a punto de realizar cambios a su disco con el fin de establecer %2.<br/><strong>Usted no podrá deshacer estos cambios.</strong> - + &Set up now &Configurar ahora - + &Set up &Configurar - + &Install &Instalar - + Setup is complete. Close the setup program. Configuración completa. Cierre el programa de instalación. - + Cancel setup? ¿Cancelar la configuración? - + Cancel installation? ¿Cancelar la instalación? - + Do you really want to cancel the current setup process? The setup program will quit and all changes will be lost. ¿Realmente desea cancelar el actual proceso de configuración? El programa de instalación se cerrará y todos los cambios se perderán. - + Do you really want to cancel the current install process? The installer will quit and all changes will be lost. ¿Realmente desea cancelar el proceso de instalación actual? El instalador terminará y se perderán todos los cambios. - + &Yes &Si - + &No &No - + &Close &Cerrar - + Continue with setup? ¿Continuar con la instalación? - + 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> El instalador %1 va a realizar cambios en su disco para instalar %2.<br/><strong>No podrá deshacer estos cambios.</strong> - + &Install now &Instalar ahora - + Go &back &Regresar - + &Done &Hecho - + The installation is complete. Close the installer. Instalación completa. Cierre el instalador. - + Error Error - + Installation Failed Instalación Fallida @@ -1291,6 +1287,22 @@ El instalador terminará y se perderán todos los cambios. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1514,6 +1526,42 @@ El instalador terminará y se perderán todos los cambios. Ubicación + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2221,14 +2269,14 @@ El instalador terminará y se perderán todos los cambios. ProcessResult - + There was no output from the command. No hubo salida desde el comando. - + Output: @@ -2237,52 +2285,52 @@ Salida - + External command crashed. El comando externo ha fallado. - + Command <i>%1</i> crashed. El comando <i>%1</i> ha fallado. - + External command failed to start. El comando externo falló al iniciar. - + Command <i>%1</i> failed to start. El comando <i>%1</i> Falló al iniciar. - + Internal error when starting command. Error interno al iniciar el comando. - + Bad parameters for process job call. Parámetros erróneos en la llamada al proceso. - + External command failed to finish. Comando externo falla al finalizar - + Command <i>%1</i> failed to finish in %2 seconds. Comando <i>%1</i> falló al finalizar en %2 segundos. - + External command finished with errors. Comando externo finalizado con errores - + Command <i>%1</i> finished with exit code %2. Comando <i>%1</i> finalizó con código de salida %2. @@ -2331,7 +2379,7 @@ Salida - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_es_PR.ts b/lang/calamares_es_PR.ts index 29df800cc..4eacba4a9 100644 --- a/lang/calamares_es_PR.ts +++ b/lang/calamares_es_PR.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,158 +226,154 @@ Calamares::ViewManager - + &Back &Atrás - - + &Next &Próximo - - + &Cancel - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. - + Setup Failed - + 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 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> - + &Set up now - + &Set up - + &Install - + Setup is complete. Close the setup program. - + 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. - + &Yes - + &No - + &Close - + Continue with setup? - + 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> - + &Install now - + Go &back - + &Done - + The installation is complete. Close the installer. - + Error Error - + Installation Failed Falló la instalación @@ -1288,6 +1284,22 @@ The installer will quit and all changes will be lost. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1511,6 +1523,42 @@ The installer will quit and all changes will be lost. Ubicación + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2218,65 +2266,65 @@ The installer will quit and all changes will be lost. 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. Parámetros erróneos para el trabajo en proceso. - + 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. @@ -2325,7 +2373,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_et.ts b/lang/calamares_et.ts index ccff140ab..82674b075 100644 --- a/lang/calamares_et.ts +++ b/lang/calamares_et.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,159 +226,155 @@ Calamares::ViewManager - + &Back &Tagasi - - + &Next &Edasi - - + &Cancel &Tühista - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. Tühista paigaldamine ilma süsteemi muutmata. - + Setup Failed - + Calamares Initialization Failed Calamarese alglaadimine ebaõnnestus - + %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 ei saa paigaldada. Calamares ei saanud laadida kõiki konfigureeritud mooduleid. See on distributsiooni põhjustatud Calamarese kasutamise viga. - + <br/>The following modules could not be loaded: <br/>Järgnevaid mooduleid ei saanud laadida: - + 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> - + &Set up now - + &Seadista kohe - + &Set up - + &Seadista - + &Install &Paigalda - + Setup is complete. Close the setup program. - + Cancel setup? - + Cancel installation? Tühista paigaldamine? - + 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. Kas sa tõesti soovid tühistada praeguse paigaldusprotsessi? Paigaldaja sulgub ning kõik muutused kaovad. - + &Yes &Jah - + &No &Ei - + &Close &Sulge - + Continue with setup? Jätka seadistusega? - + 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> %1 paigaldaja on tegemas muudatusi sinu kettale, et paigaldada %2.<br/><strong>Sa ei saa neid muudatusi tagasi võtta.</strong> - + &Install now &Paigalda kohe - + Go &back Mine &tagasi - + &Done &Valmis - + The installation is complete. Close the installer. Paigaldamine on lõpetatud. Sulge paigaldaja. - + Error Viga - + Installation Failed Paigaldamine ebaõnnestus @@ -1111,7 +1107,7 @@ Paigaldaja sulgub ning kõik muutused kaovad. <Restart checkbox tooltip> - + <Restart checkbox tooltip> @@ -1159,7 +1155,7 @@ Paigaldaja sulgub ning kõik muutused kaovad. Setup Complete - + Seadistus valmis @@ -1289,6 +1285,22 @@ Paigaldaja sulgub ning kõik muutused kaovad. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1512,6 +1524,42 @@ Paigaldaja sulgub ning kõik muutused kaovad. Asukoht + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2219,14 +2267,14 @@ Paigaldaja sulgub ning kõik muutused kaovad. ProcessResult - + There was no output from the command. Käsul polnud väljundit. - + Output: @@ -2235,52 +2283,52 @@ Väljund: - + External command crashed. Väline käsk jooksis kokku. - + Command <i>%1</i> crashed. Käsk <i>%1</i> jooksis kokku. - + External command failed to start. Välise käsu käivitamine ebaõnnestus. - + Command <i>%1</i> failed to start. Käsu <i>%1</i> käivitamine ebaõnnestus. - + Internal error when starting command. Käsu käivitamisel esines sisemine viga. - + Bad parameters for process job call. Protsessi töö kutsel olid halvad parameetrid. - + External command failed to finish. Väline käsk ei suutnud lõpetada. - + Command <i>%1</i> failed to finish in %2 seconds. Käsk <i>%1</i> ei suutnud lõpetada %2 sekundi jooksul. - + External command finished with errors. Väline käsk lõpetas vigadega. - + Command <i>%1</i> finished with exit code %2. Käsk <i>%1</i> lõpetas sulgemiskoodiga %2. @@ -2329,7 +2377,7 @@ Väljund: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_eu.ts b/lang/calamares_eu.ts index 7365976a6..0698b7b78 100644 --- a/lang/calamares_eu.ts +++ b/lang/calamares_eu.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,159 +226,155 @@ Calamares::ViewManager - + &Back &Atzera - - + &Next &Hurrengoa - - + &Cancel &Utzi - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. Instalazioa bertan behera utsi da sisteman aldaketarik gabe. - + Setup Failed - + Calamares Initialization Failed Calamares instalazioak huts egin du - + %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 ezin da instalatu. Calamares ez da gai konfiguratutako modulu guztiak kargatzeko. Arazao hau banaketak Calamares erabiltzen duen eragatik da. - + <br/>The following modules could not be loaded: <br/> Ondorengo moduluak ezin izan dira kargatu: - + 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> - + &Set up now - + &Set up - + &Install &Instalatu - + Setup is complete. Close the setup program. - + Cancel setup? - + Cancel installation? Bertan behera utzi instalazioa? - + 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. Ziur uneko instalazio prozesua bertan behera utzi nahi duzula? Instalatzailea irten egingo da eta aldaketa guztiak galduko dira. - + &Yes &Bai - + &No &Ez - + &Close &Itxi - + Continue with setup? Ezarpenarekin jarraitu? - + 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> %1 instalatzailea zure diskoan aldaketak egitera doa %2 instalatzeko.<br/><strong>Ezingo dituzu desegin aldaketa hauek.</strong> - + &Install now &Instalatu orain - + Go &back &Atzera - + &Done E&ginda - + The installation is complete. Close the installer. Instalazioa burutu da. Itxi instalatzailea. - + Error Akatsa - + Installation Failed Instalazioak huts egin du @@ -1289,6 +1285,22 @@ Instalatzailea irten egingo da eta aldaketa guztiak galduko dira. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1512,6 +1524,42 @@ Instalatzailea irten egingo da eta aldaketa guztiak galduko dira. Kokapena + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2219,13 +2267,13 @@ Instalatzailea irten egingo da eta aldaketa guztiak galduko dira. ProcessResult - + There was no output from the command. - + Output: @@ -2234,52 +2282,52 @@ Irteera: - + External command crashed. Kanpo-komandoak huts egin du. - + Command <i>%1</i> crashed. <i>%1</i> komandoak huts egin du. - + External command failed to start. Ezin izan da %1 kanpo-komandoa abiarazi. - + Command <i>%1</i> failed to start. Ezin izan da <i>%1</i> komandoa abiarazi. - + Internal error when starting command. Barne-akatsa komandoa abiarazterakoan. - + Bad parameters for process job call. - + External command failed to finish. Kanpo-komandoa ez da bukatu. - + Command <i>%1</i> failed to finish in %2 seconds. - + External command finished with errors. Kanpo-komandoak akatsekin bukatu da. - + Command <i>%1</i> finished with exit code %2. @@ -2328,7 +2376,7 @@ Irteera: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_fa.ts b/lang/calamares_fa.ts index 1b2cbf823..43c251241 100644 --- a/lang/calamares_fa.ts +++ b/lang/calamares_fa.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,158 +226,154 @@ Calamares::ViewManager - + &Back - - + &Next - - + &Cancel - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. - + Setup Failed - + 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 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> - + &Set up now - + &Set up - + &Install - + Setup is complete. Close the setup program. - + 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. - + &Yes - + &No - + &Close - + Continue with setup? - + 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> - + &Install now - + Go &back - + &Done - + The installation is complete. Close the installer. - + Error - + Installation Failed @@ -1288,6 +1284,22 @@ The installer will quit and all changes will be lost. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1511,6 +1523,42 @@ The installer will quit and all changes will be lost. + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2218,65 +2266,65 @@ The installer will quit and all changes will be lost. 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. @@ -2325,7 +2373,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_fi_FI.ts b/lang/calamares_fi_FI.ts index be8928448..047a6fbaf 100644 --- a/lang/calamares_fi_FI.ts +++ b/lang/calamares_fi_FI.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). Odotetaan %n moduuli(t).Odotetaan %n moduuli(t). - + (%n second(s)) (%n sekunttia(s))(%n sekunttia(s)) - + System-requirements checking is complete. Järjestelmävaatimusten tarkistus on valmis. @@ -226,160 +226,156 @@ Calamares::ViewManager - + &Back &Takaisin - - + &Next &Seuraava - - + &Cancel &Peruuta - - + Cancel setup without changing the system. Peruuta asennus muuttamatta järjestelmää. - - + Cancel installation without changing the system. Peruuta asennus tekemättä muutoksia järjestelmään. - + Setup Failed Asennus epäonnistui - + Calamares Initialization Failed Calamares-alustustaminen epäonnistui - + %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 ei voida asentaa. Calamares ei voinut ladata kaikkia määritettyjä moduuleja. Ongelma on siinä, miten jakelu käyttää Calamaresia. - + <br/>The following modules could not be loaded: <br/>Seuraavia moduuleja ei voitu ladata: - + Continue with installation? Jatka asennusta? - + 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 asennusohjelma on aikeissa tehdä muutoksia levylle, jotta voit määrittää kohteen %2.<br/><strong>Et voi kumota näitä muutoksia.</strong> - + &Set up now &Määritä nyt - + &Set up &Määritä - + &Install &Asenna - + Setup is complete. Close the setup program. Asennus on valmis. Sulje asennusohjelma. - + Cancel setup? Peruuta asennus? - + Cancel installation? Peruuta asennus? - + Do you really want to cancel the current setup process? The setup program will quit and all changes will be lost. Haluatko todella peruuttaa nykyisen asennuksen? Asennusohjelma lopetetaan ja kaikki muutokset menetetään. - + Do you really want to cancel the current install process? The installer will quit and all changes will be lost. Oletko varma että haluat peruuttaa käynnissä olevan asennusprosessin? Asennusohjelma sulkeutuu ja kaikki muutoksesi katoavat. - + &Yes &Kyllä - + &No &Ei - + &Close &Sulje - + Continue with setup? Jatka asennusta? - + 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> Asennus ohjelman %1 on tehtävä muutoksia levylle, jotta %2 voidaan asentaa.<br/><strong>Et voi kumota näitä muutoksia.</strong> - + &Install now &Asenna nyt - + Go &back Mene &takaisin - + &Done &Valmis - + The installation is complete. Close the installer. Asennus on valmis. Sulje asennusohjelma. - + Error Virhe - + Installation Failed Asennus Epäonnistui @@ -1290,6 +1286,22 @@ Asennusohjelma sulkeutuu ja kaikki muutoksesi katoavat. Tiedostoon ei voitu kirjoittaa <code>%1</code>. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + Initramfs luominen mkinitcpion avulla. + + + + InitramfsJob + + + Creating initramfs. + Luodaan initramfs. + + InteractiveTerminalPage @@ -1513,6 +1525,42 @@ Asennusohjelma sulkeutuu ja kaikki muutoksesi katoavat. Sijainti + + LuksBootKeyFileJob + + + Configuring LUKS key file. + LUKS-avaintiedoston määrittäminen. + + + + + No partitions are defined. + Osioita ei ole määritelty. + + + + + + Encrypted rootfs setup error + Salattu rootfs asennusvirhe + + + + Root partition %1 is LUKS but no passphrase has been set. + Juuriosio %1 on LUKS, mutta salasanaa ei ole asetettu. + + + + Could not create LUKS key file for root partition %1. + LUKS-avaintiedostoa ei voitu luoda juuriosioon %1. + + + + Could configure LUKS key file on partition %1. + Voit määrittää LUKS-avaimen osioon %1. + + NetInstallPage @@ -2220,14 +2268,14 @@ Asennusohjelma sulkeutuu ja kaikki muutoksesi katoavat. ProcessResult - + There was no output from the command. Komentoa ei voitu ajaa. - + Output: @@ -2236,52 +2284,52 @@ Ulostulo: - + External command crashed. Ulkoinen komento kaatui. - + Command <i>%1</i> crashed. Komento <i>%1</i> kaatui. - + External command failed to start. Ulkoisen komennon käynnistäminen epäonnistui. - + Command <i>%1</i> failed to start. Komennon <i>%1</i> käynnistäminen epäonnistui. - + Internal error when starting command. Sisäinen virhe käynnistettäessä komentoa. - + Bad parameters for process job call. Huonot parametrit prosessin kutsuun. - + External command failed to finish. Ulkoinen komento ei onnistunut. - + Command <i>%1</i> failed to finish in %2 seconds. Komento <i>%1</i> epäonnistui %2 sekunnissa. - + External command finished with errors. Ulkoinen komento päättyi virheisiin. - + Command <i>%1</i> finished with exit code %2. Komento <i>%1</i> päättyi koodiin %2. @@ -2330,7 +2378,7 @@ Ulostulo: (ei liitoskohtaa) - + Requirements checking for module <i>%1</i> is complete. Moduulin vaatimusten tarkistaminen <i>%1</i> on valmis. diff --git a/lang/calamares_fr.ts b/lang/calamares_fr.ts index d6d2f0017..b3e8f620c 100644 --- a/lang/calamares_fr.ts +++ b/lang/calamares_fr.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). En attente de %n module(s).En attente de %n module(s). - + (%n second(s)) (%n seconde(s))(%n seconde(s)) - + System-requirements checking is complete. La vérification des prérequis système est terminée. @@ -226,160 +226,156 @@ Calamares::ViewManager - + &Back &Précédent - - + &Next &Suivant - - + &Cancel &Annuler - - + Cancel setup without changing the system. Annuler la configuration sans toucher au système. - - + Cancel installation without changing the system. Annuler l'installation sans modifier votre système. - + Setup Failed Échec de la configuration - + Calamares Initialization Failed L'initialisation de Calamares a échoué - + %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 n'a pas pu être installé. Calamares n'a pas pu charger tous les modules configurés. C'est un problème avec la façon dont Calamares est utilisé par la distribution. - + <br/>The following modules could not be loaded: Les modules suivants n'ont pas pu être chargés : - + Continue with installation? Continuer avec l'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> Le programme de configuration de %1 est sur le point de procéder aux changements sur le disque afin de configurer %2.<br/> <strong>Vous ne pourrez pas annulez ces changements.</strong> - + &Set up now &Configurer maintenant - + &Set up &Configurer - + &Install &Installer - + Setup is complete. Close the setup program. La configuration est terminée. Fermer le programme de configuration. - + Cancel setup? Annuler la configuration ? - + Cancel installation? Abandonner l'installation ? - + Do you really want to cancel the current setup process? The setup program will quit and all changes will be lost. Voulez-vous réellement abandonner le processus de configuration ? Le programme de configuration se fermera et les changements seront perdus. - + Do you really want to cancel the current install process? The installer will quit and all changes will be lost. Voulez-vous réellement abandonner le processus d'installation ? L'installateur se fermera et les changements seront perdus. - + &Yes &Oui - + &No &Non - + &Close &Fermer - + Continue with setup? Poursuivre la configuration ? - + 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> L'installateur %1 est sur le point de procéder aux changements sur le disque afin d'installer %2.<br/> <strong>Vous ne pourrez pas annulez ces changements.<strong> - + &Install now &Installer maintenant - + Go &back &Retour - + &Done &Terminé - + The installation is complete. Close the installer. L'installation est terminée. Fermer l'installateur. - + Error Erreur - + Installation Failed L'installation a échoué @@ -1290,6 +1286,22 @@ L'installateur se fermera et les changements seront perdus. Impossible d'écrire dans le fichier <code>%1</code>. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + Création de l'initramfs avec mkinitcpio. + + + + InitramfsJob + + + Creating initramfs. + création du initramfs + + InteractiveTerminalPage @@ -1513,6 +1525,42 @@ L'installateur se fermera et les changements seront perdus. Localisation + + LuksBootKeyFileJob + + + Configuring LUKS key file. + Configuration de la clé de fichier LUKS. + + + + + No partitions are defined. + Aucune partition n'est définie. + + + + + + Encrypted rootfs setup error + Erreur du chiffrement du setup rootfs + + + + Root partition %1 is LUKS but no passphrase has been set. + La partition racine %1 est LUKS mais aucune passphrase n'a été configurée. + + + + Could not create LUKS key file for root partition %1. + Impossible de créer le fichier de clé LUKS pour la partition racine %1. + + + + Could configure LUKS key file on partition %1. + Succès de la création du fichier de clé LUKS pour la partition racine %1. + + NetInstallPage @@ -2221,14 +2269,14 @@ Vous pouvez obtenir un aperçu des différentes apparences en cliquant sur celle ProcessResult - + There was no output from the command. Il y a eu aucune sortie de la commande - + Output: @@ -2237,52 +2285,52 @@ Sortie - + External command crashed. La commande externe s'est mal terminée. - + Command <i>%1</i> crashed. La commande <i>%1</i> s'est arrêtée inopinément. - + External command failed to start. La commande externe n'a pas pu être lancée. - + Command <i>%1</i> failed to start. La commande <i>%1</i> n'a pas pu être lancée. - + Internal error when starting command. Erreur interne au lancement de la commande - + Bad parameters for process job call. Mauvais paramètres pour l'appel au processus de job. - + External command failed to finish. La commande externe ne s'est pas terminée. - + Command <i>%1</i> failed to finish in %2 seconds. La commande <i>%1</i> ne s'est pas terminée en %2 secondes. - + External command finished with errors. La commande externe s'est terminée avec des erreurs. - + Command <i>%1</i> finished with exit code %2. La commande <i>%1</i> s'est terminée avec le code de sortie %2. @@ -2331,7 +2379,7 @@ Sortie (aucun point de montage) - + Requirements checking for module <i>%1</i> is complete. La vérification des prérequis pour le module <i>%1</i> est terminée. diff --git a/lang/calamares_fr_CH.ts b/lang/calamares_fr_CH.ts index 7d8969f66..abd87a2ca 100644 --- a/lang/calamares_fr_CH.ts +++ b/lang/calamares_fr_CH.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,158 +226,154 @@ Calamares::ViewManager - + &Back - - + &Next - - + &Cancel - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. - + Setup Failed - + 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 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> - + &Set up now - + &Set up - + &Install - + Setup is complete. Close the setup program. - + 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. - + &Yes - + &No - + &Close - + Continue with setup? - + 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> - + &Install now - + Go &back - + &Done - + The installation is complete. Close the installer. - + Error - + Installation Failed @@ -1288,6 +1284,22 @@ The installer will quit and all changes will be lost. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1511,6 +1523,42 @@ The installer will quit and all changes will be lost. + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2218,65 +2266,65 @@ The installer will quit and all changes will be lost. 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. @@ -2325,7 +2373,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_gl.ts b/lang/calamares_gl.ts index befb59012..d8bd5006d 100644 --- a/lang/calamares_gl.ts +++ b/lang/calamares_gl.ts @@ -209,17 +209,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -227,159 +227,155 @@ Calamares::ViewManager - + &Back &Atrás - - + &Next &Seguinte - - + &Cancel &Cancelar - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. Cancelar a instalación sen cambiar o sistema - + Setup Failed - + Calamares Initialization Failed Fallou a inicialización do Calamares - + %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. Non é posíbel instalar %1. O calamares non foi quen de cargar todos os módulos configurados. Este é un problema relacionado con como esta distribución utiliza o Calamares. - + <br/>The following modules could not be loaded: <br/> Non foi posíbel cargar os módulos seguintes: - + 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> - + &Set up now - + &Set up - + &Install &Instalar - + Setup is complete. Close the setup program. - + Cancel setup? - + Cancel installation? Cancelar a instalación? - + 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. Desexa realmente cancelar o proceso actual de instalación? O instalador pecharase e perderanse todos os cambios. - + &Yes &Si - + &No &Non - + &Close &Pechar - + Continue with setup? Continuar coa posta en marcha? - + 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> O %1 instalador está a piques de realizar cambios no seu disco para instalar %2.<br/><strong>Estes cambios non poderán desfacerse.</strong> - + &Install now &Instalar agora - + Go &back Ir &atrás - + &Done &Feito - + The installation is complete. Close the installer. Completouse a instalacion. Peche o instalador - + Error Erro - + Installation Failed Erro na instalación @@ -1290,6 +1286,22 @@ O instalador pecharase e perderanse todos os cambios. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1513,6 +1525,42 @@ O instalador pecharase e perderanse todos os cambios. Localización... + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2220,14 +2268,14 @@ O instalador pecharase e perderanse todos os cambios. ProcessResult - + There was no output from the command. A saída non produciu ningunha saída. - + Output: @@ -2236,52 +2284,52 @@ Saída: - + External command crashed. A orde externa fallou - + Command <i>%1</i> crashed. A orde <i>%1</i> fallou. - + External command failed to start. Non foi posíbel iniciar a orde externa. - + Command <i>%1</i> failed to start. Non foi posíbel iniciar a orde <i>%1</i>. - + Internal error when starting command. Produciuse un erro interno ao iniciar a orde. - + Bad parameters for process job call. Erro nos parámetros ao chamar o traballo - + External command failed to finish. A orde externa non se puido rematar. - + Command <i>%1</i> failed to finish in %2 seconds. A orde <i>%1</i> non se puido rematar en %2s segundos. - + External command finished with errors. A orde externa rematou con erros. - + Command <i>%1</i> finished with exit code %2. A orde <i>%1</i> rematou co código de erro %2. @@ -2330,7 +2378,7 @@ Saída: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_gu.ts b/lang/calamares_gu.ts index 1e9c71185..79c880be9 100644 --- a/lang/calamares_gu.ts +++ b/lang/calamares_gu.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,158 +226,154 @@ Calamares::ViewManager - + &Back - - + &Next - - + &Cancel - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. - + Setup Failed - + 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 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> - + &Set up now - + &Set up - + &Install - + Setup is complete. Close the setup program. - + 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. - + &Yes - + &No - + &Close - + Continue with setup? - + 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> - + &Install now - + Go &back - + &Done - + The installation is complete. Close the installer. - + Error - + Installation Failed @@ -1288,6 +1284,22 @@ The installer will quit and all changes will be lost. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1511,6 +1523,42 @@ The installer will quit and all changes will be lost. + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2218,65 +2266,65 @@ The installer will quit and all changes will be lost. 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. @@ -2325,7 +2373,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_he.ts b/lang/calamares_he.ts index 3dc37fd5f..bba1c30e8 100644 --- a/lang/calamares_he.ts +++ b/lang/calamares_he.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). בהמתנה למודול אחד.בהמתנה לשני מודולים.בהמתנה ל־%n מודולים.בהמתנה ל־%n מודולים. - + (%n second(s)) ((שנייה אחת)(שתי שניות)(%n שניות)(%n שניות) - + System-requirements checking is complete. בדיקת דרישות המערכת הושלמה. @@ -226,160 +226,156 @@ Calamares::ViewManager - + &Back ה&קודם - - + &Next הב&א - - + &Cancel &ביטול - - + Cancel setup without changing the system. ביטול ההתקנה ללא שינוי המערכת. - - + Cancel installation without changing the system. ביטול התקנה ללא ביצוע שינוי במערכת. - + Setup Failed ההתקנה נכשלה - + Calamares Initialization Failed הפעלת Calamares נכשלה - + %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. ל־Calamares אין אפשרות לטעון את המודולים המוגדרים. מדובר בתקלה באופן בו ההפצה משתמשת ב־Calamares. - + <br/>The following modules could not be loaded: <br/>לא ניתן לטעון את המודולים הבאים: - + 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> תכנית ההתקנה של %1 עומדת לבצע שינויים בכונן הקשיח שלך לטובת התקנת %2.<br/><strong>לא תהיה לך אפשרות לבטל את השינויים האלה.</strong> - + &Set up now להת&קין כעת - + &Set up להת&קין - + &Install הת&קנה - + Setup is complete. Close the setup program. ההתקנה הושלמה. נא לסגור את תכנית ההתקנה. - + 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. לבטל את תהליך ההתקנה? אשף ההתקנה ייסגר וכל השינויים יאבדו. - + &Yes &כן - + &No &לא - + &Close &סגירה - + Continue with setup? להמשיך בהתקנה? - + 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> אשף ההתקנה של %1 הולך לבצע שינויים בכונן שלך לטובת התקנת %2.<br/><strong>לא תוכל לבטל את השינויים הללו.</strong> - + &Install now להת&קין כעת - + Go &back ח&זרה - + &Done &סיום - + The installation is complete. Close the installer. תהליך ההתקנה הושלם. נא לסגור את אשף ההתקנה. - + Error שגיאה - + Installation Failed ההתקנה נכשלה @@ -1290,6 +1286,22 @@ The installer will quit and all changes will be lost. לא ניתן לכתוב לקובץ <code>%1</code>. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + נוצר initramfs עם mkinitcpio. + + + + InitramfsJob + + + Creating initramfs. + נוצר initramfs. + + InteractiveTerminalPage @@ -1513,6 +1525,42 @@ The installer will quit and all changes will be lost. מיקום + + LuksBootKeyFileJob + + + Configuring LUKS key file. + קובץ מפתח ה־LUKS מוגדר. + + + + + No partitions are defined. + לא הוגדרו מחיצות. + + + + + + Encrypted rootfs setup error + שגיאת התקנת מחיצת שורש מוצפנת + + + + Root partition %1 is LUKS but no passphrase has been set. + מחיצת השורש %1 היא LUKS אבל לא הוגדרה מילת צופן. + + + + Could not create LUKS key file for root partition %1. + לא ניתן ליצור קובץ מפתח LUKS למחיצת השורש %1. + + + + Could configure LUKS key file on partition %1. + לא ניתן להגדיר קובץ מפתח LUKS למחיצה %1. + + NetInstallPage @@ -2220,14 +2268,14 @@ The installer will quit and all changes will be lost. ProcessResult - + There was no output from the command. לא היה פלט מהפקודה. - + Output: @@ -2236,52 +2284,52 @@ Output: - + External command crashed. הפקודה החיצונית נכשלה. - + Command <i>%1</i> crashed. הפקודה <i>%1</i> קרסה. - + External command failed to start. הפעלת הפעולה החיצונית נכשלה. - + Command <i>%1</i> failed to start. הפעלת הפקודה <i>%1</i> נכשלה. - + 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. הפקודה <i>%1</i> לא הסתיימה תוך %2 שניות. - + External command finished with errors. הפקודה החיצונית הסתיימה עם שגיאות. - + Command <i>%1</i> finished with exit code %2. הפקודה <i>%1</i> הסתיימה עם קוד היציאה %2. @@ -2330,7 +2378,7 @@ Output: (אין נקודת עגינה) - + Requirements checking for module <i>%1</i> is complete. בדיקת הדרישות למודול <i>%1</i> הושלמה. diff --git a/lang/calamares_hi.ts b/lang/calamares_hi.ts index 8fcd48dcb..127346027 100644 --- a/lang/calamares_hi.ts +++ b/lang/calamares_hi.ts @@ -14,7 +14,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>Master Boot Record</strong> पर विभाजन तालिका की शुरुआत में इंस्टॉल (सुझाया जाता है) करना होगा। यह स्वत: होता है, परंतु अगर आप मैनुअल विभाजन करना चुनते है; तो आपको इसे खुद ही बनाना होगा। + यह सिस्टम <strong>BIOS</strong>बूट वातावरण के साथ शुरू किया गया।<br><br>BIOS वातावरण से स्टार्टअप विन्यस्त करने के लिए इंस्टॉलर को <strong>GRUB</strong> जैसे बूट लोडर को, या तो विभाजन की शुरुआत में या फिर <strong>मास्टर बूट रिकॉर्ड</strong> पर विभाजन तालिका की शुरुआत में इंस्टॉल (सुझाया जाता है) करना होगा। यह स्वत: होता है, परंतु अगर आप मैनुअल विभाजन करना चुनते है; तो आपको इसे खुद ही बनाना होगा। @@ -22,7 +22,7 @@ Master Boot Record of %1 - %1 का Master Boot Record + %1 का मास्टर बूट रिकॉर्ड @@ -63,22 +63,22 @@ GlobalStorage - GlobalStorage + ग्लोबल स्टोरेज JobQueue - JobQueue + कार्य पंक्ति Modules - मापांक + मॉड्यूल Type: - प्रकार + प्रकार : @@ -89,7 +89,7 @@ Interface: - अंतरफलक : + इंटरफ़ेस : @@ -99,17 +99,17 @@ Reload Stylesheet - + शैली पत्रक पुनः लोड करें Widget Tree - + विजेट ट्री Debug information - डीबग संबंधी जानकारी + डीबग जानकारी @@ -117,7 +117,7 @@ Set up - + सेटअप @@ -130,12 +130,12 @@ Job failed (%1) - + कार्य विफल रहा (%1) Programmed job failure was explicitly requested. - + प्रोग्राम किए गए कार्य की विफलता स्पष्ट रूप से अनुरोध की गई थी। @@ -143,7 +143,7 @@ Done - पूर्ण + पूर्ण हुआ @@ -151,7 +151,7 @@ Example job (%1) - + उदाहरण कार्य (%1) @@ -159,12 +159,12 @@ Run command '%1' in target system. - + लक्षित सिस्टम में कमांड '%1' चलाएँ। Run command '%1'. - + कमांड '%1' चलाएँ। @@ -187,200 +187,197 @@ Working directory %1 for python job %2 is not readable. - Python job %2 के लिए कार्यरत डायरेक्टरी %1 रीड करने योग्य नहीं है। + पाइथन कार्य %2 के लिए कार्यरत डायरेक्टरी %1 रीड करने योग्य नहीं है। Bad main script file - मुख्य स्क्रिप्ट फ़ाइल गलत है + ख़राब मुख्य स्क्रिप्ट फ़ाइल Main script file %1 for python job %2 is not readable. - Python job %2 के लिए मुख्य स्क्रिप्ट फ़ाइल %1 रीड करने योग्य नहीं है। + पाइथन कार्य %2 हेतु मुख्य स्क्रिप्ट फ़ाइल %1 रीड करने योग्य नहीं है। Boost.Python error in job "%1". - Job "%1" में Boost.Python त्रुटि। + कार्य "%1" में Boost.Python त्रुटि। Calamares::RequirementsChecker - + Waiting for %n module(s). - + %n मॉड्यूल की प्रतीक्षा में।%n मॉड्यूल की प्रतीक्षा में। - + (%n second(s)) - + (%n सेकंड)(%n सेकंड) - + System-requirements checking is complete. - + सिस्टम हेतु आवश्यकताओं की जाँच पूर्ण हुई। Calamares::ViewManager - + &Back वापस (&B) - - + &Next आगे (&N) - - + &Cancel रद्द करें (&C) - - + Cancel setup without changing the system. - + सिस्टम में बदलाव किये बिना सेटअप रद्द करें। - - + Cancel installation without changing the system. सिस्टम में बदलाव किये बिना इंस्टॉल रद्द करें। - + Setup Failed - + सेटअप विफल रहा - + Calamares Initialization Failed Calamares का आरंभीकरण विफल रहा - + %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 को इंस्टॉल नहीं किया जा सका। Calamares सारे विन्यस्त मापांकों को लोड करने में विफल रहा। इस समस्या का कारण लिनक्स-वितरण द्वारा Calamares के उपयोग-संबंधी कोई त्रुटि है। + %1 को इनस्टॉल नहीं किया जा सका। Calamares सभी विन्यस्त मापांकों को लोड करने में विफल रहा। यह आपके लिनक्स वितरण द्वारा Calamares के उपयोग से संबंधित एक समस्या है। - + <br/>The following modules could not be loaded: <br/>निम्नलिखित मापांक लोड नहीं हो सकें : - + 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> - + %2 सेटअप करने हेतु %1 सेटअप प्रोग्राम आपकी डिस्क में बदलाव करने वाला है।<br/><strong>आप इन बदलावों को पूर्ववत नहीं कर पाएंगे।</strong> - + &Set up now - + अभी सेटअप करें (&S) - + &Set up - + सेटअप करें (&S) - + &Install इंस्टॉल करें (&I) - + Setup is complete. Close the setup program. - + सेटअप पूर्ण हुआ। सेटअप प्रोग्राम बंद कर दें। - + 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. क्या आप वाकई वर्तमान इंस्टॉल प्रक्रिया रद्द करना चाहते हैं? इंस्टॉलर बंद हो जाएगा व सभी बदलाव नष्ट। - + &Yes हाँ (&Y) - + &No नहीं (&N) - + &Close बंद करें (&C) - + Continue with setup? सेटअप करना जारी रखें? - + 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> - + &Install now अभी इंस्टॉल करें (&I) - + Go &back वापस जाएँ (&b) - + &Done - पूर्ण हुआ (&D) + हो गया (&D) - + The installation is complete. Close the installer. - इंस्टॉल पूर्ण हुआ। अब इंस्टॉलर को बंद करें। + इंस्टॉल पूर्ण हुआ।अब इंस्टॉलर को बंद करें। - + Error त्रुटि - + Installation Failed - इंस्टॉल विफल रहा। + इंस्टॉल विफल रहा @@ -388,22 +385,22 @@ The installer will quit and all changes will be lost. Unknown exception type - अपवाद का प्रकार अज्ञात है + अपवाद का प्रकार अज्ञात unparseable Python error - unparseable Python त्रुटि + अप्राप्य पाइथन त्रुटि unparseable Python traceback - unparseable Python traceback + अप्राप्य पाइथन ट्रेसबैक Unfetchable Python error. - Unfetchable Python त्रुटि। + पहुँच से बाहर पाइथन त्रुटि। @@ -411,7 +408,7 @@ The installer will quit and all changes will be lost. %1 Setup Program - + %1 सेटअप प्रोग्राम @@ -421,7 +418,7 @@ The installer will quit and all changes will be lost. Show debug information - डीबग संबंधी जानकारी दिखाएँ + डीबग जानकारी दिखाएँ @@ -442,7 +439,7 @@ The installer will quit and all changes will be lost. After: - बाद में: + बाद में : @@ -452,7 +449,7 @@ The installer will quit and all changes will be lost. Boot loader location: - बूट लोडर का स्थान: + बूट लोडर का स्थान : @@ -475,17 +472,17 @@ 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> %1 will be shrunk to %2MiB and a new %3MiB partition will be created for %4. - + %1 को छोटा करके %2MiB किया जाएगा व %4 हेतु %3MiB का एक नया विभाजन बनेगा। <strong>Select a partition to install on</strong> - <strong>इंस्टॉल के लिए विभाजन चुनें</strong> + <strong>इंस्टॉल हेतु विभाजन चुनें</strong> @@ -523,27 +520,27 @@ The installer will quit and all changes will be lost. No Swap - + कोई स्वैप नहीं Reuse Swap - + स्वैप पुनः उपयोग करें Swap (no Hibernate) - + स्वैप (हाइबरनेशन/सिस्टम सुप्त रहित) Swap (with Hibernate) - + स्वैप (हाइबरनेशन/सिस्टम सुप्त सहित) Swap to file - + स्वैप फाइल बनाएं @@ -587,7 +584,7 @@ The installer will quit and all changes will be lost. Cleared all mounts for %1 - %1 के लिए सभी माउंट हटा दिए गए + %1 हेतु सभी माउंट हटा दिए गए @@ -624,12 +621,12 @@ The installer will quit and all changes will be lost. 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. - + कमांड हेतु उपयोक्ता का नाम आवश्यक है परन्तु कोई नाम परिभाषित नहीं है। @@ -637,7 +634,7 @@ The installer will quit and all changes will be lost. Contextual Processes Job - Contextual Processes Job + प्रासंगिक प्रक्रिया कार्य @@ -680,7 +677,7 @@ The installer will quit and all changes will be lost. Flags: - Flags: + फ्लैग : @@ -723,12 +720,12 @@ The installer will quit and all changes will be lost. Create new %2MiB partition on %4 (%3) with file system %1. - + फ़ाइल सिस्टम %1 के साथ %4 (%3) पर नया %2MiB का विभाजन बनाएँ। Create new <strong>%2MiB</strong> partition on <strong>%4</strong> (%3) with file system <strong>%1</strong>. - + फ़ाइल सिस्टम <strong>%1</strong> के साथ <strong>%4</strong> (%3) पर नया <strong>%2MiB</strong> का विभाजन बनाएँ। @@ -761,7 +758,7 @@ The installer will quit and all changes will be lost. Master Boot Record (MBR) - Master Boot Record (MBR) + मास्टर बूट रिकॉर्ड (MBR) @@ -835,7 +832,7 @@ The installer will quit and all changes will be lost. Create Volume Group - + वॉल्यूम समूह बनाएँ @@ -843,22 +840,22 @@ The installer will quit and all changes will be lost. Create new volume group named %1. - + %1 नामक नया वॉल्यूम समूह बनाएं। Create new volume group named <strong>%1</strong>. - + <strong>%1</strong> नामक नया वॉल्यूम समूह बनाएं। Creating new volume group named %1. - + %1 नामक नया वॉल्यूम समूह बनाया जा रहा है। The installer failed to create a volume group named '%1'. - + इंस्टालर '%1' नामक वॉल्यूम समूह को बनाने में विफल रहा। @@ -867,17 +864,17 @@ The installer will quit and all changes will be lost. Deactivate volume group named %1. - + %1 नामक वॉल्यूम समूह को निष्क्रिय करें। Deactivate volume group named <strong>%1</strong>. - + <strong>%1</strong> नामक वॉल्यूम समूह को निष्क्रिय करें। The installer failed to deactivate a volume group named %1. - + इंस्टॉलर %1 नामक वॉल्यूम समूह को निष्क्रिय करने में विफल रहा। @@ -948,7 +945,7 @@ The installer will quit and all changes will be lost. %1 - (%2) device[name] - (device-node[name]) - + %1 - (%2) @@ -956,12 +953,12 @@ The installer will quit and all changes will be lost. Write LUKS configuration for Dracut to %1 - + Dracut हेतु LUKS विन्यास %1 पर राइट करना Skip writing LUKS configuration for Dracut: "/" partition is not encrypted - + Dracut हेतु LUKS विन्यास %1 पर राइट करना छोड़ें : "/" विभाजन एन्क्रिप्टेड नहीं है @@ -974,7 +971,7 @@ The installer will quit and all changes will be lost. Dummy C++ Job - Dummy C++ Job + डमी सी++ कार्य @@ -1027,7 +1024,7 @@ The installer will quit and all changes will be lost. Flags: - Flags: + फ्लैग : @@ -1111,7 +1108,7 @@ The installer will quit and all changes will be lost. <Restart checkbox tooltip> - + <Restart checkbox tooltip> @@ -1121,12 +1118,12 @@ The installer will quit and all changes will be lost. <h1>All done.</h1><br/>%1 has been set up on your computer.<br/>You may now start using your new system. - + <h1>सब हो गया।</h1><br/>आपके कंप्यूटर पर %1 को सेटअप कर दिया गया है।<br/>अब आप अपने नए सिस्टम का उपयोग कर सकते है। <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>यह विकल्प चयनित होने पर आपका सिस्टम तुरंत पुनः आरंभ हो जाएगा जब आप <span style="font-style:italic;">हो गया</span>पर क्लिक करेंगे या सेटअप प्रोग्राम को बंद करेंगे।</p></body></html> @@ -1136,12 +1133,12 @@ The installer will quit and all changes will be lost. <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>यह विकल्प चयनित होने पर आपका सिस्टम तुरंत पुनः आरंभ हो जाएगा जब आप <span style="font-style:italic;">हो गया</span>पर क्लिक करेंगे या इंस्टॉलर बंद करेंगे।</p></body></html> <h1>Setup Failed</h1><br/>%1 has not been set up on your computer.<br/>The error message was: %2. - + <h1>सेटअप विफल रहा</h1><br/>%1 आपके कंप्यूटर पर सेटअप नहीं हुआ।<br/>त्रुटि संदेश : %2। @@ -1159,7 +1156,7 @@ The installer will quit and all changes will be lost. Setup Complete - + सेटअप पूर्ण हुआ @@ -1169,7 +1166,7 @@ The installer will quit and all changes will be lost. The setup of %1 is complete. - + %1 का सेटअप पूर्ण हुआ। @@ -1182,12 +1179,12 @@ The installer will quit and all changes will be lost. Format partition %1 (file system: %2, size: %3 MiB) on %4. - + विभाजन %1 (फ़ाइल सिस्टम: %2, आकार: %3 MiB) को %4 पर फॉर्मेट करें। Format <strong>%3MiB</strong> partition <strong>%1</strong> with file system <strong>%2</strong>. - + फ़ाइल सिस्टम <strong>%2</strong> के साथ <strong>%3MiB</strong> के विभाजन <strong>%1</strong> को फॉर्मेट करें। @@ -1205,37 +1202,37 @@ The installer will quit and all changes will be lost. has at least %1 GiB available drive space - + कम-से-कम %1 GiB स्पेस ड्राइव पर उपलब्ध हो There is not enough drive space. At least %1 GiB is required. - + ड्राइव में पर्याप्त स्पेस नहीं है। कम-से-कम %1 GiB होना आवश्यक है। has at least %1 GiB working memory - + कम-से-कम %1 GiB मेमोरी उपलब्ध हो The system does not have enough working memory. At least %1 GiB is required. - + सिस्टम में पर्याप्त मेमोरी नहीं है। कम-से-कम %1 GiB होनी आवश्यक है। is plugged in to a power source - बिजली से कनेक्ट है। + पॉवर के स्रोत से कनेक्ट है The system is not plugged in to a power source. - सिस्टम बिजली से कनेक्ट नहीं है। + सिस्टम पॉवर के स्रोत से कनेक्ट नहीं है। is connected to the Internet - इंटरनेट से कनेक्ट है। + इंटरनेट से कनेक्ट है @@ -1245,7 +1242,7 @@ The installer will quit and all changes will be lost. The setup program is not running with administrator rights. - + सेटअप प्रोग्राम के पास प्रबंधक अधिकार नहीं है। @@ -1255,12 +1252,12 @@ The installer will quit and all changes will be lost. The screen is too small to display the setup program. - + सेटअप प्रोग्राम प्रदर्शित करने हेतु स्क्रीन काफ़ी छोटी है। The screen is too small to display the installer. - इंस्टॉलर दिखाने के लिए स्क्रीन बहुत छोटी है। + इंस्टॉलर प्रदर्शित करने हेतु स्क्रीन काफ़ी छोटी है। @@ -1271,22 +1268,38 @@ The installer will quit and all changes will be lost. OEM Batch Identifier - + OEM (मूल उपकरण निर्माता) बैच पहचानकर्ता Could not create directories <code>%1</code>. - + <code>%1</code> डायरेक्टरी बनाई नहीं जा सकीं। Could not open file <code>%1</code>. - + <code>%1</code> फाइल खोली नहीं जा सकीं। Could not write to file <code>%1</code>. - + <code>%1</code> फाइल पर राइट नहीं किया जा सका। + + + + InitcpioJob + + + Creating initramfs with mkinitcpio. + mkinitcpio के साथ initramfs बनाना। + + + + InitramfsJob + + + Creating initramfs. + initramfs बनाना। @@ -1304,7 +1317,7 @@ The installer will quit and all changes will be lost. Executing script: &nbsp;<code>%1</code> - + निष्पादित स्क्रिप्ट : &nbsp;<code>%1</code> @@ -1312,7 +1325,7 @@ The installer will quit and all changes will be lost. Script - Script + स्क्रिप्ट @@ -1369,7 +1382,7 @@ The installer will quit and all changes will be lost. I accept the terms and conditions above. - मैं उपर्युक्त नियम व शर्तें स्वीकार करता हूँ। + मैं उपरोक्त नियम व शर्तें स्वीकार करता हूँ। @@ -1384,7 +1397,7 @@ The installer will quit and all changes will be lost. <h1>License Agreement</h1>This setup procedure can install proprietary software that is subject to licensing terms in order to provide additional features and enhance the user experience. - + <h1>लाइसेंस अनुबंध</h1> यह सेटअप प्रक्रिया अतिरिक्त सुविधाएँ प्रदान करने व उपयोक्ता अनुभव में वृद्धि हेतु लाइसेंस शर्तों के अधीन अमुक्त सॉफ्टवेयर को इंस्टॉल कर सकती है। @@ -1437,32 +1450,32 @@ The installer will quit and all changes will be lost. Shows the complete license text - + लाइसेंस को उसके पूर्ण स्वरुप में दिखाएँ Hide license text - + लाइसेंस लेख छिपाएँ Show license agreement - + लाइसेंस अनुबंध दिखाएँ Hide license agreement - + लाइसेंस अनुबंध छिपाएँ Opens the license agreement in a browser window. - + लाइसेंस अनुबंध को ब्राउज़र विंडो में खोलें। <a href="%1">View license agreement</a> - + <a href="%1">लाइसेंस अनुबंध देखें</a> @@ -1485,7 +1498,7 @@ The installer will quit and all changes will be lost. Zone: - क्षेत्र : + ज़ोन : @@ -1504,7 +1517,7 @@ The installer will quit and all changes will be lost. Loading location data... - स्थान संबंधी डाटा लोड किया जा रहा है... + स्थान संबंधी डाटा लोड हो रहा है... @@ -1512,6 +1525,42 @@ The installer will quit and all changes will be lost. स्थान + + LuksBootKeyFileJob + + + Configuring LUKS key file. + LUKS कुंजी फाइल विन्यस्त करना। + + + + + No partitions are defined. + कोई विभाजन परिभाषित नहीं हैं। + + + + + + Encrypted rootfs setup error + एन्क्रिप्टेड rootfs सेटअप में त्रुटि + + + + Root partition %1 is LUKS but no passphrase has been set. + रूट विभाजन %1 LUKS है, लेकिन कोई कूटशब्द सेट नहीं किया गया है। + + + + Could not create LUKS key file for root partition %1. + रूट विभाजन %1 हेतु LUKS कुंजी फाइल बनाने में विफल। + + + + Could configure LUKS key file on partition %1. + विभाजन %1 पर LUKS कुंजी फ़ाइल को विन्यस्त कर सकता है। + + NetInstallPage @@ -1527,12 +1576,12 @@ The installer will quit and all changes will be lost. Network Installation. (Disabled: Unable to fetch package lists, check your network connection) - + नेटवर्क इंस्टॉल। (निष्क्रिय है : पैकेज सूची प्राप्त करने में असमर्थ, अपना नेटवर्क कनेक्शन जाँचें) Network Installation. (Disabled: Received invalid groups data) - + नेटवर्क इंस्टॉल (निष्क्रिय है : प्राप्त किया गया समूह डाटा अमान्य है) @@ -1548,17 +1597,17 @@ The installer will quit and all changes will be lost. Ba&tch: - + बैच (&t) : <html><head/><body><p>Enter a batch-identifier here. This will be stored in the target system.</p></body></html> - + <html><head/><body><p>यहां एक बैच-पहचानकर्ता दर्ज करें। इसे लक्षित सिस्टम में संचित किया जाएगा।</p></body></html> <html><head/><body><h1>OEM Configuration</h1><p>Calamares will use OEM settings while configuring the target system.</p></body></html> - + <html><head/><body><h1>OEM (मूल उपकरण निर्माता) विन्यास सेटिंग्स</h1><p>लक्षित सिस्टम को विन्यस्त करते समय Calamares OEM (मूल उपकरण निर्माता) सेटिंग्स का उपयोग करेगा।</p></body></html> @@ -1566,12 +1615,12 @@ The installer will quit and all changes will be lost. OEM Configuration - + OEM (मूल उपकरण निर्माता) विन्यास सेटिंग्स Set the OEM Batch Identifier to <code>%1</code>. - + OEM (मूल उपकरण निर्माता) बैच पहचानकर्ता को <code>%1</code>पर सेट करें। @@ -1579,17 +1628,17 @@ The installer will quit and all changes will be lost. Password is too short - कूटशब्द बहुत छोटा है + कूटशब्द काफ़ी छोटा है Password is too long - कूटशब्द बहुत लंबा है + कूटशब्द काफ़ी लंबा है Password is too weak - कूटशब्द बहुत कमज़ोर है + कूटशब्द काफ़ी कमज़ोर है @@ -1684,7 +1733,7 @@ The installer will quit and all changes will be lost. The password is too short - कूटशब्द बहुत छोटा है + कूटशब्द काफ़ी छोटा है @@ -1744,7 +1793,7 @@ The installer will quit and all changes will be lost. Password generation failed - required entropy too low for settings - कूटशब्द बनाना विफल रहा - सेटिंग्स के लिए आवश्यक entropy बहुत कम है + कूटशब्द बनाना विफल रहा - सेटिंग्स के लिए आवश्यक एन्ट्रापी काफ़ी कम है @@ -1769,32 +1818,32 @@ The installer will quit and all changes will be lost. Bad integer value of setting - %1 - सेटिंग का गलत integer मान - %1 + सेटिंग का गलत पूर्णांक मान - %1 Bad integer value - गलत integer मान + गलत पूर्णांक मान Setting %1 is not of integer type - सेटिंग %1 integer नहीं है + सेटिंग %1 पूर्णांक नहीं है Setting is not of integer type - सेटिंग integer नहीं है + सेटिंग पूर्णांक नहीं है Setting %1 is not of string type - सेटिंग %1 string नहीं है + सेटिंग %1 स्ट्रिंग नहीं है Setting is not of string type - सेटिंग string नहीं है + सेटिंग स्ट्रिंग नहीं है @@ -1855,12 +1904,12 @@ The installer will quit and all changes will be lost. 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> @@ -1875,7 +1924,7 @@ The installer will quit and all changes will be lost. Log in automatically without asking for the password. - कूटशब्द बिना पूछे ही स्वतः लॉग इन करें। + कूटशब्द पूछे बिना स्वतः लॉग इन करें। @@ -1885,7 +1934,7 @@ The installer will quit and all changes will be lost. Choose a password for the administrator account. - प्रबंधक अकाउंट के लिए कूटशब्द चुनें। + प्रबंधक अकाउंट हेतु कूटशब्द चुनें। @@ -1943,7 +1992,7 @@ The installer will quit and all changes will be lost. Free Space - खाली स्पेस + रिक्त स्पेस @@ -1982,7 +2031,7 @@ The installer will quit and all changes will be lost. Storage de&vice: - डिवाइस (&v): + स्टोरेज डिवाइस (&v): @@ -2012,27 +2061,27 @@ The installer will quit and all changes will be lost. New Volume Group - + नया वॉल्यूम समूह Resize Volume Group - + वॉल्यूम समूह का आकार बदलें Deactivate Volume Group - + वॉल्यूम समूह को निष्क्रिय करें Remove Volume Group - + वॉल्यूम समूह को हटाएँ I&nstall boot loader on: - + बूट लोडर इंस्टॉल करें (&l) : @@ -2042,12 +2091,12 @@ The installer will quit and all changes will be lost. 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. - + %1 पर विभाजन तालिका में पहले से ही %2 मुख्य विभाजन हैं व और अधिक नहीं जोड़ें जा सकते। कृपया एक मुख्य विभाजन को हटाकर उसके स्थान पर एक विस्तृत विभाजन जोड़ें। @@ -2115,7 +2164,7 @@ The installer will quit and all changes will be lost. After: - बाद में: + बाद में : @@ -2130,12 +2179,12 @@ The installer will quit and all changes will be lost. EFI system partition flag not set - EFI सिस्टम विभाजन flag सेट नहीं है + EFI सिस्टम विभाजन फ्लैग सेट नहीं है An EFI system partition is necessary to start %1.<br/><br/>A partition was configured with mount point <strong>%2</strong> but its <strong>esp</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>esp</strong> flag सेट नहीं था।<br/> Flag सेट करने के लिए, वापस जाएँ और विभाजन को edit करें।<br/><br/>आप बिना सेट भी आगे बढ़ सकते है पर सिस्टम चालू नहीं होगा। + %1 को शुरू करने हेतु EFI सिस्टम विभाजन ज़रूरी है।<br/><br/>विभाजन को माउंट पॉइंट <strong>%2</strong> के साथ विन्यस्त किया गया परंतु उसका <strong>esp</strong> फ्लैग सेट नहीं था।<br/> फ्लैग सेट करने के लिए, वापस जाएँ और विभाजन को edit करें।<br/><br/>आप बिना सेट भी आगे बढ़ सकते है पर सिस्टम चालू नहीं होगा। @@ -2150,12 +2199,12 @@ The installer will quit and all changes will be lost. has at least one disk device available. - + कम-से-कम एक डिस्क डिवाइस उपलब्ध हो। There are no partitons to install on. - + इनस्टॉल हेतु कोई विभाजन नहीं हैं। @@ -2182,7 +2231,7 @@ The installer will quit and all changes will be lost. 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. - + कृपया केडीई प्लाज़्मा डेस्कटॉप के लिए एक look-and-feel चुनें। आप अभी इस चरण को छोड़ सकते हैं व सिस्टम सेटअप होने के उपरांत इसे सेट कर सकते हैं। look-and-feel विकल्पों पर क्लिक कर आप चयनित look-and-feel का तुरंत ही पूर्वावलोकन कर सकते हैं। @@ -2203,84 +2252,84 @@ The installer will quit and all changes will be lost. 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. कमांड <i>%1</i> क्रैश हो गई। - + External command failed to start. बाह्य​ कमांड शुरू होने में विफल। - + Command <i>%1</i> failed to start. कमांड <i>%1</i> शुरू होने में विफल। - + 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. कमांड <i>%1</i> %2 सेकंड में समाप्त होने में विफल। - + External command finished with errors. बाहरी कमांड त्रुटि के साथ समाप्त। - + Command <i>%1</i> finished with exit code %2. कमांड <i>%1</i> exit कोड %2 के साथ समाप्त। @@ -2326,12 +2375,12 @@ Output: (no mount point) - + (कोई माउंट पॉइंट नहीं) - + Requirements checking for module <i>%1</i> is complete. - + मापांक <i>%1</i> हेतु आवश्यकताओं की जाँच पूर्ण हुई। @@ -2346,17 +2395,17 @@ Output: Remove Volume Group named %1. - + %1 नामक वॉल्यूम समूह हटाएँ। Remove Volume Group named <strong>%1</strong>. - + <strong>%1</strong> नामक वॉल्यूम समूह हटाएँ। The installer failed to remove a volume group named '%1'. - + इंस्टालर '%1' नामक वॉल्यूम समूह को हटाने में विफल रहा। @@ -2369,7 +2418,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> यह चयनित विभाजन पर मौजूद सभी फ़ाइलों को हटा देगा। @@ -2379,12 +2428,12 @@ Output: %1 cannot be installed on empty space. Please select an existing partition. - %1 को खाली स्पेस पर इंस्टॉल नहीं किया जा सकता।कृपया कोई मौजूदा विभाजन चुनें। + %1 को खाली स्पेस पर इंस्टॉल नहीं किया जा सकता। कृपया कोई मौजूदा विभाजन चुनें। %1 cannot be installed on an extended partition. Please select an existing primary or logical partition. - %1 को विस्तृत विभाजन पर इंस्टॉल नहीं किया जा सकता।कृपया कोई मौजूदा मुख्य या तार्किक विभाजन चुनें। + %1 को विस्तृत विभाजन पर इंस्टॉल नहीं किया जा सकता। कृपया कोई मौजूदा मुख्य या तार्किक विभाजन चुनें। @@ -2409,7 +2458,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 की क्षमता वाला कोई विभाजन चुनें। @@ -2431,7 +2480,7 @@ Output: EFI system partition: - EFI सिस्टम विभाजन: + EFI सिस्टम विभाजन : @@ -2439,29 +2488,29 @@ Output: Resize Filesystem Job - + फ़ाइल सिस्टम कार्य का आकार बदलें Invalid configuration - + अमान्य विन्यास The file-system resize job has an invalid configuration and will not run. - + फाइल सिस्टम का आकार बदलने हेतु कार्य का विन्यास अमान्य है व यह नहीं चलेगा। KPMCore not Available - + KPMCore उपलब्ध नहीं है Calamares cannot start KPMCore for the file-system resize job. - + Calamares फाइल सिस्टम का आकार बदलने कार्य हेतु KPMCore को आरंभ नहीं कर सका। @@ -2470,39 +2519,39 @@ Output: Resize Failed - + आकार बदलना विफल रहा The filesystem %1 could not be found in this system, and cannot be resized. - + इस सिस्टम पर फाइल सिस्टम %1 नहीं मिला, व उसका आकार बदला नहीं जा सकता। The device %1 could not be found in this system, and cannot be resized. - + इस सिस्टम पर डिवाइस %1 नहीं मिला, व उसका आकार बदला नहीं जा सकता। The filesystem %1 cannot be resized. - + फाइल सिस्टम %1 का आकार बदला नहीं जा सकता। The device %1 cannot be resized. - + डिवाइस %1 का आकार बदला नहीं जा सकता। The filesystem %1 must be resized, but cannot. - + फाइल सिस्टम %1 का आकार बदला जाना चाहिए लेकिन बदला नहीं जा सकता। The device %1 must be resized, but cannot - + डिवाइस %1 का आकार बदला जाना चाहिए लेकिन बदला नहीं जा सकता @@ -2515,12 +2564,12 @@ Output: Resize <strong>%2MiB</strong> partition <strong>%1</strong> to <strong>%3MiB</strong>. - + <strong>%2MiB</strong> के <strong>%1</strong> विभाजन का आकार बदलकर <strong>%3MiB</strong> करें। Resizing %2MiB partition %1 to %3MiB. - + %2MiB के %1 विभाजन का आकार बदलकर %3MiB किया जा रहा है। @@ -2533,7 +2582,7 @@ Output: Resize Volume Group - + वॉल्यूम समूह का आकार बदलें @@ -2542,17 +2591,17 @@ Output: Resize volume group named %1 from %2 to %3. - + %1 नामक वॉल्यूम समूह का आकार %2 से बदलकर %3 करें। Resize volume group named <strong>%1</strong> from <strong>%2</strong> to <strong>%3</strong>. - + <strong>%1</strong> नामक वॉल्यूम समूह का आकार <strong>%2</strong> से बदलकर <strong>%3</strong> करें। The installer failed to resize a volume group named '%1'. - + इंस्टालर '%1' नाम के वॉल्यूम समूह का आकार बदलने में विफल रहा। @@ -2560,7 +2609,7 @@ Output: 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> @@ -2570,22 +2619,22 @@ Output: 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/>सेटअप जारी रखा जा सकता है, लेकिन कुछ विशेषताएँ को निष्क्रिय किया जा सकता हैं। 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 को सेट करेगा। For best results, please ensure that this computer: - उत्तम परिणामों के लिए, कृपया सुनिश्चित करें कि यह कंप्यूटर: + उत्तम परिणाम हेतु, कृपया सुनिश्चित करें कि यह कंप्यूटर : @@ -2646,7 +2695,7 @@ Output: Failed to write keyboard configuration for the virtual console. - Virtual console हेतु कुंजीपटल की सेटिंग्स राइट करने में विफल रहा। + वर्चुअल कंसोल हेतु कुंजीपटल की सेटिंग्स राइट करने में विफल रहा। @@ -2663,7 +2712,7 @@ Output: Failed to write keyboard configuration to existing /etc/default directory. - मौजूदा /etc /default डायरेक्टरी में कुंजीपटल की सेटिंग्स write करने में विफल रहा। + मौजूदा /etc /default डायरेक्टरी में कुंजीपटल की सेटिंग्स राइट करने में विफल रहा। @@ -2671,82 +2720,82 @@ Output: Set flags on partition %1. - %1 विभाजन पर flag सेट करें। + %1 विभाजन पर फ्लैग सेट करें। Set flags on %1MiB %2 partition. - + %1MiB के %2 विभाजन पर फ्लैग सेट करें। Set flags on new partition. - नए विभाजन पर flag सेट करें। + नए विभाजन पर फ्लैग सेट करें। Clear flags on partition <strong>%1</strong>. - <strong>%1</strong> विभाजन पर से flag हटाएँ। + <strong>%1</strong> विभाजन पर से फ्लैग हटाएँ। Clear flags on %1MiB <strong>%2</strong> partition. - + %1MiB के <strong>%2</strong> विभाजन पर से फ्लैग हटाएँ। Flag %1MiB <strong>%2</strong> partition as <strong>%3</strong>. - + %1MiB के <strong>%2</strong> विभाजन पर <strong>%3</strong> का फ्लैग लगाएँ। Clearing flags on %1MiB <strong>%2</strong> partition. - + %1MiB के <strong>%2</strong> विभाजन पर से फ्लैग हटाएँ जा रहे हैं। Setting flags <strong>%3</strong> on %1MiB <strong>%2</strong> partition. - + %1MiB के <strong>%2</strong> विभाजन पर फ्लैग <strong>%3</strong> सेट किए जा रहे हैं। Clear flags on new partition. - नए विभाजन पर से flag हटाएँ। + नए विभाजन पर से फ्लैग हटाएँ। Flag partition <strong>%1</strong> as <strong>%2</strong>. - <strong>%1</strong> विभाजन पर <strong>%2</strong> का flag लगाएँ। + <strong>%1</strong> विभाजन पर <strong>%2</strong> का फ्लैग लगाएँ। Flag new partition as <strong>%1</strong>. - नए विभाजन पर<strong>%1</strong>का flag लगाएँ। + नए विभाजन पर<strong>%1</strong>का फ्लैग लगाएँ। Clearing flags on partition <strong>%1</strong>. - <strong>%1</strong> विभाजन पर से flag हटाएँ जा रहे हैं। + <strong>%1</strong> विभाजन पर से फ्लैग हटाएँ जा रहे हैं। Clearing flags on new partition. - नए विभाजन पर से flag हटाएँ जा रहे हैं। + नए विभाजन पर से फ्लैग हटाएँ जा रहे हैं। Setting flags <strong>%2</strong> on partition <strong>%1</strong>. - <strong>%1</strong> विभाजन पर flag <strong>%2</strong> सेट किए जा रहे हैं। + <strong>%1</strong> विभाजन पर फ्लैग <strong>%2</strong> सेट किए जा रहे हैं। Setting flags <strong>%1</strong> on new partition. - नए विभाजन पर flag <strong>%1</strong> सेट किए जा रहे हैं। + नए विभाजन पर फ्लैग <strong>%1</strong> सेट किए जा रहे हैं। The installer failed to set flags on partition %1. - इंस्टॉलर विभाजन %1 पर flag सेट करने में विफल रहा। + इंस्टॉलर विभाजन %1 पर फ्लैग सेट करने में विफल रहा। @@ -2769,7 +2818,7 @@ Output: rootMountPoint is %1 - rootMountPoint %1 है + रूट माउंट पॉइंट %1 है @@ -2784,7 +2833,7 @@ Output: Cannot set password for user %1. - उपयोक्ता %1 के लिए पासवर्ड सेट नहीं किया जा सकता। + उपयोक्ता %1 हेतु पासवर्ड सेट नहीं किया जा सकता। @@ -2822,12 +2871,12 @@ Output: Cannot set timezone, - समय क्षेत्र सेट नहीं हो सका। + समय क्षेत्र सेट नहीं हो सका, Cannot open /etc/timezone for writing - राइट करने हेतु /etc /timezone खोला नहीं जा सका। + राइट करने हेतु /etc /timezone खोला नहीं जा सका @@ -2835,7 +2884,7 @@ Output: Shell Processes Job - + शेल प्रक्रिया कार्य @@ -2852,7 +2901,7 @@ Output: This is an overview of what will happen once you start the setup procedure. - + यह एक अवलोकन है कि सेटअप प्रक्रिया आरंभ होने के उपरांत क्या होगा। @@ -2865,7 +2914,7 @@ Output: Summary - सार + सारांश @@ -2873,22 +2922,22 @@ Output: Installation feedback - + इंस्टॉल संबंधी प्रतिक्रिया Sending installation feedback. - + इंस्टॉल संबंधी प्रतिक्रिया भेजना। Internal error in install-tracking. - + इंस्टॉल-ट्रैकिंग में आंतरिक त्रुटि। HTTP request timed out. - + एचटीटीपी अनुरोध हेतु समय समाप्त। @@ -2896,28 +2945,28 @@ Output: Machine feedback - + मशीन संबंधी प्रतिक्रिया Configuring machine feedback. - + मशीन संबंधी प्रतिक्रिया विन्यस्त करना। Error in machine feedback configuration. - + मशीन संबंधी प्रतिक्रिया विन्यास में त्रुटि। Could not configure machine feedback correctly, script error %1. - + मशीन प्रतिक्रिया को सही रूप से विन्यस्त नहीं किया जा सका, स्क्रिप्ट त्रुटि %1। Could not configure machine feedback correctly, Calamares error %1. - + मशीन प्रतिक्रिया को सही रूप से विन्यस्त नहीं किया जा सका, Calamares त्रुटि %1। @@ -2930,37 +2979,37 @@ Output: Placeholder - 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>इसे चयनित करने पर, आपके इंस्टॉल संबंधी <span style=" font-weight:600;">किसी प्रकार की कोई जानकारी नहीं </span>भेजी जाएँगी।</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> - + <html><head/><body><p><a href="placeholder"><span style=" text-decoration: underline; color:#2980b9;">उपयोक्ता प्रतिक्रिया के बारे में अधिक जानकारी हेतु यहाँ क्लिक करें</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. - + इंस्टॉल की ट्रैकिंग करने से %1 को यह जानने में सहायता मिलती है कि उनके कितने उपयोक्ता हैं, वे किस हार्डवेयर पर %1 को इंस्टॉल करते हैं एवं (नीचे दिए अंतिम दो विकल्पों सहित), पसंदीदा अनुप्रयोगों के बारे में निरंतर जानकारी प्राप्त करते हैं। यह जानने हेतु कि क्या भेजा जाएगा, कृपया प्रत्येक क्षेत्र के साथ में दिए सहायता आइकन पर क्लिक करें। 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. - + इसे चयनित करने पर आपके इंस्टॉल व हार्डवेयर संबंधी जानकारी भेजी जाएँगी। यह जानकारी इंस्टॉल समाप्त हो जाने के उपरांत <b>केवल एक बार ही</b> भेजी जाएगी। By selecting this you will <b>periodically</b> send information about your installation, hardware and applications, to %1. - + इसे चयनित करने पर आपके इंस्टॉल, हार्डवेयर व अनुप्रयोगों संबंधी जानकारी <b>समय-समय पर</b>, %1 को भेजी जाएँगी। By selecting this you will <b>regularly</b> send information about your installation, hardware, applications and usage patterns, to %1. - + इसे चयनित करने पर आपके इंस्टॉल, हार्डवेयर, अनुप्रयोगों व उपयोक्ता प्रतिमानों संबंधी जानकारी <b>समय-समय पर</b>, %1 को भेजी जाएँगी। @@ -2968,7 +3017,7 @@ Output: Feedback - + प्रतिक्रिया @@ -2976,37 +3025,37 @@ Output: <small>If more than one person will use this computer, you can create multiple accounts after setup.</small> - + <small>यदि एक से अधिक व्यक्ति इस कंप्यूटर का उपयोग करेंगे, तो आप सेटअप के उपरांत एकाधिक अकाउंट बना सकते हैं।</small> <small>If more than one person will use this computer, you can create multiple accounts after installation.</small> - + <small>यदि एक से अधिक व्यक्ति इस कंप्यूटर का उपयोग करेंगे, तो आप इंस्टॉल के उपरांत एकाधिक अकाउंट बना सकते हैं।</small> Your username is too long. - आपका उपयोक्ता नाम बहुत लंबा है। + आपका उपयोक्ता नाम काफ़ी लंबा है। Your username contains invalid characters. Only lowercase letters and numbers are allowed. - आपके होस्ट नाम में अमान्य अक्षर हैं । केवल lowercase अक्षरों व संख्याओं की ही अनुमति है । + आपके होस्ट नाम में अमान्य अक्षर हैं । केवल lowercase अक्षरों व संख्याओं की अनुमति है । Your hostname is too short. - आपका होस्ट नाम बहुत छोटा है। + आपका होस्ट नाम काफ़ी छोटा है। Your hostname is too long. - आपका होस्ट नाम बहुत लंबा है। + आपका होस्ट नाम काफ़ी लंबा है। Your hostname contains invalid characters. Only letters, numbers and dashes are allowed. - आपके होस्ट नाम में अमान्य अक्षर हैं । केवल अक्षरों, संख्याओं व dash की ही अनुमति है । + आपके होस्ट नाम में अमान्य अक्षर हैं । केवल अक्षरों, संख्याओं व dash की अनुमति है । @@ -3028,52 +3077,52 @@ Output: Create Volume Group - + वॉल्यूम समूह बनाएँ List of Physical Volumes - + वॉल्यूम समूहों की सूची Volume Group Name: - + वॉल्यूम समूह का नाम : Volume Group Type: - + वॉल्यूम समूह का प्रकार : Physical Extent Size: - + डिस्क ब्लॉक की आकार सीमा : MiB - MiB + MiB Total Size: - + कुल आकार : Used Size: - + प्रयुक्त आकार : Total Sectors: - + कुल सेक्टर : Quantity of LVs: - + तार्किक वॉल्यूम की मात्रा : @@ -3097,7 +3146,7 @@ Output: Select language - + भाषा चुनें @@ -3122,17 +3171,17 @@ Output: <h1>Welcome to the Calamares setup program for %1.</h1> - + <h1>%1 हेतु Calamares सेटअप में आपका स्वागत है।</h1> <h1>Welcome to %1 setup.</h1> - + <h1>%1 सेटअप में आपका स्वागत है।</h1> About %1 setup - + %1 सेटअप के बारे में @@ -3142,7 +3191,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-2019 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-2019 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> - लिब्रेटिंग सॉफ्टवेयर द्वारा प्रायोजित है। @@ -3155,7 +3204,7 @@ Output: Welcome - स्वागतं + स्वागत है \ No newline at end of file diff --git a/lang/calamares_hr.ts b/lang/calamares_hr.ts index 89862d76e..372e94597 100644 --- a/lang/calamares_hr.ts +++ b/lang/calamares_hr.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). Čekam %1 modul(a).Čekam %1 modul(a).Čekam %1 modul(a). - + (%n second(s)) (%n sekunda(e))(%n sekunda(e))(%n sekunda(e)) - + System-requirements checking is complete. Provjera zahtjeva za instalaciju sustava je dovršena. @@ -226,160 +226,156 @@ Calamares::ViewManager - + &Back &Natrag - - + &Next &Sljedeće - - + &Cancel &Odustani - - + Cancel setup without changing the system. Odustanite od instalacije bez promjena na sustavu. - - + Cancel installation without changing the system. Odustanite od instalacije bez promjena na sustavu. - + Setup Failed Instalacija nije uspjela - + Calamares Initialization Failed Inicijalizacija Calamares-a nije uspjela - + %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 se ne može se instalirati. Calamares nije mogao učitati sve konfigurirane module. Ovo je problem s načinom na koji se Calamares koristi u distribuciji. - + <br/>The following modules could not be loaded: <br/>Sljedeći moduli se nisu mogli učitati: - + Continue with installation? Nastaviti sa instalacijom? - + 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> Instalacijski program %1 će izvršiti promjene na vašem disku kako bi postavio %2. <br/><strong>Ne možete poništiti te promjene.</strong> - + &Set up now &Postaviti odmah - + &Set up &Postaviti - + &Install &Instaliraj - + Setup is complete. Close the setup program. Instalacija je završena. Zatvorite instalacijski program. - + Cancel setup? Prekinuti instalaciju? - + Cancel installation? Prekinuti instalaciju? - + Do you really want to cancel the current setup process? The setup program will quit and all changes will be lost. Stvarno želite prekinuti instalacijski proces? Instalacijski program će izaći i sve promjene će biti izgubljene. - + Do you really want to cancel the current install process? The installer will quit and all changes will be lost. Stvarno želite prekinuti instalacijski proces? Instalacijski program će izaći i sve promjene će biti izgubljene. - + &Yes &Da - + &No &Ne - + &Close &Zatvori - + Continue with setup? Nastaviti s postavljanjem? - + 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> %1 instalacijski program će napraviti promjene na disku kako bi instalirao %2.<br/><strong>Nećete moći vratiti te promjene.</strong> - + &Install now &Instaliraj sada - + Go &back Idi &natrag - + &Done &Gotovo - + The installation is complete. Close the installer. Instalacija je završena. Zatvorite instalacijski program. - + Error Greška - + Installation Failed Instalacija nije uspjela @@ -1290,6 +1286,22 @@ Instalacijski program će izaći i sve promjene će biti izgubljene.Nije moguće pisati u datoteku <code>%1</code>. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + Stvaranje initramfs s mkinitcpio. + + + + InitramfsJob + + + Creating initramfs. + Stvaranje initramfs. + + InteractiveTerminalPage @@ -1513,6 +1525,42 @@ Instalacijski program će izaći i sve promjene će biti izgubljene.Lokacija + + LuksBootKeyFileJob + + + Configuring LUKS key file. + Konfiguriranje LUKS ključne datoteke. + + + + + No partitions are defined. + Nema definiranih particija. + + + + + + Encrypted rootfs setup error + Pogreška postavljanja šifriranog rootfs-a + + + + Root partition %1 is LUKS but no passphrase has been set. + Root particija %1 je LUKS, ali nije postavljena zaporka. + + + + Could not create LUKS key file for root partition %1. + Nije moguće kreirati LUKS ključnu datoteku za root particiju %1. + + + + Could configure LUKS key file on partition %1. + Moguće je konfigurirati LUKS ključnu datoteku na particiji %1. + + NetInstallPage @@ -2220,14 +2268,14 @@ Instalacijski program će izaći i sve promjene će biti izgubljene. ProcessResult - + There was no output from the command. Nema izlazne informacije od naredbe. - + Output: @@ -2236,52 +2284,52 @@ Izlaz: - + External command crashed. Vanjska naredba je prekinula s radom. - + Command <i>%1</i> crashed. Naredba <i>%1</i> je prekinula s radom. - + External command failed to start. Vanjska naredba nije uspješno pokrenuta. - + Command <i>%1</i> failed to start. Naredba <i>%1</i> nije uspješno pokrenuta. - + Internal error when starting command. Unutrašnja greška pri pokretanju naredbe. - + Bad parameters for process job call. Krivi parametri za proces poziva posla. - + External command failed to finish. Vanjska naredba se nije uspjela izvršiti. - + Command <i>%1</i> failed to finish in %2 seconds. Naredba <i>%1</i> nije uspjela završiti za %2 sekundi. - + External command finished with errors. Vanjska naredba je završila sa pogreškama. - + Command <i>%1</i> finished with exit code %2. Naredba <i>%1</i> je završila sa izlaznim kodom %2. @@ -2330,7 +2378,7 @@ Izlaz: (nema točke montiranja) - + Requirements checking for module <i>%1</i> is complete. Provjera zahtjeva za modul <i>%1</i> je dovršena. diff --git a/lang/calamares_hu.ts b/lang/calamares_hu.ts index cf8e907f7..cdf120890 100644 --- a/lang/calamares_hu.ts +++ b/lang/calamares_hu.ts @@ -99,12 +99,12 @@ Reload Stylesheet - + Stílusok újratöltése Widget Tree - + Modul- fa @@ -159,12 +159,12 @@ Run command '%1' in target system. - + '%1' parancs futtatása a cél rendszeren. Run command '%1'. - + '%1' parancs futtatása. @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). Várakozás a %n modulokra.Várakozás %n modulokra. - + (%n second(s)) (%n másodperc)(%n másodperc) - + System-requirements checking is complete. Rendszerkövetelmények ellenőrzése kész. @@ -226,160 +226,156 @@ Calamares::ViewManager - + &Back &Vissza - - + &Next &Következő - - + &Cancel &Mégse - - + Cancel setup without changing the system. Telepítés megszakítása a rendszer módosítása nélkül. - - + Cancel installation without changing the system. Kilépés a telepítőből a rendszer megváltoztatása nélkül. - + Setup Failed Telepítési hiba - + Calamares Initialization Failed A Calamares előkészítése meghiúsult - + %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. A(z) %1 nem telepíthető. A Calamares nem tudta betölteni a konfigurált modulokat. Ez a probléma abból fakad, ahogy a disztribúció a Calamarest használja. - + <br/>The following modules could not be loaded: <br/>A következő modulok nem tölthetőek be: - + Continue with installation? Folytatja a telepítést? - + 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> A %1 telepítő változtatásokat fog végrehajtani a lemezen a %2 telepítéséhez. <br/><strong>Ezután már nem tudja visszavonni a változtatásokat.</strong> - + &Set up now &Telepítés most - + &Set up &Telepítés - + &Install &Telepítés - + Setup is complete. Close the setup program. Telepítés sikerült. Zárja be a telepítőt. - + Cancel setup? Megszakítja a telepítést? - + Cancel installation? Abbahagyod a telepítést? - + Do you really want to cancel the current setup process? The setup program will quit and all changes will be lost. Valóban megszakítod a telepítési eljárást? A telepítő ki fog lépni és minden változtatás elveszik. - + Do you really want to cancel the current install process? The installer will quit and all changes will be lost. Biztos abba szeretnéd hagyni a telepítést? Minden változtatás elveszik, ha kilépsz a telepítőből. - + &Yes &Igen - + &No &Nem - + &Close &Bezár - + Continue with setup? Folytatod a telepítéssel? - + 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> A %1 telepítő változtatásokat fog elvégezni, hogy telepítse a következőt: %2.<br/><strong>A változtatások visszavonhatatlanok lesznek.</strong> - + &Install now &Telepítés most - + Go &back Menj &vissza - + &Done &Befejez - + The installation is complete. Close the installer. A telepítés befejeződött, Bezárhatod a telepítőt. - + Error Hiba - + Installation Failed Telepítés nem sikerült @@ -1290,6 +1286,22 @@ Minden változtatás elveszik, ha kilépsz a telepítőből. Sikertelen fájl írás <code>%1</code>. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + initramfs létrehozása mkinitcpio utasítással. + + + + InitramfsJob + + + Creating initramfs. + initramfs létrehozása. + + InteractiveTerminalPage @@ -1513,6 +1525,42 @@ Minden változtatás elveszik, ha kilépsz a telepítőből. Hely + + LuksBootKeyFileJob + + + Configuring LUKS key file. + LUKS kulcs fájl konfigurálása. + + + + + No partitions are defined. + Nincsenek partíciók definiálva. + + + + + + Encrypted rootfs setup error + Titkosított rootfs telepítési hiba + + + + Root partition %1 is LUKS but no passphrase has been set. + A %1 root partíció LUKS de beállítva nincs kulcs. + + + + Could not create LUKS key file for root partition %1. + Nem sikerült létrehozni a LUKS kulcs fájlt a %1 root partícióhoz + + + + Could configure LUKS key file on partition %1. + Nem sikerült beállítani a LUKS kulcs fájlt a %1 root partíción. + + NetInstallPage @@ -2220,14 +2268,14 @@ Minden változtatás elveszik, ha kilépsz a telepítőből. ProcessResult - + There was no output from the command. A parancsnak nem volt kimenete. - + Output: @@ -2236,52 +2284,52 @@ Kimenet: - + External command crashed. Külső parancs összeomlott. - + Command <i>%1</i> crashed. Parancs <i>%1</i> összeomlott. - + External command failed to start. A külső parancsot nem sikerült elindítani. - + Command <i>%1</i> failed to start. A(z) <i>%1</i> parancsot nem sikerült elindítani. - + Internal error when starting command. Belső hiba a parancs végrehajtásakor. - + Bad parameters for process job call. Hibás paraméterek a folyamat hívásához. - + External command failed to finish. Külső parancs nem fejeződött be. - + Command <i>%1</i> failed to finish in %2 seconds. A(z) <i>%1</i> parancsot nem sikerült befejezni %2 másodperc alatt. - + External command finished with errors. A külső parancs hibával fejeződött be. - + Command <i>%1</i> finished with exit code %2. A(z) <i>%1</i> parancs hibakóddal lépett ki: %2. @@ -2330,7 +2378,7 @@ Kimenet: (nincs csatolási pont) - + Requirements checking for module <i>%1</i> is complete. Követelmények ellenőrzése a <i>%1</i>modulhoz kész. diff --git a/lang/calamares_id.ts b/lang/calamares_id.ts index 5557114ef..bc3a72586 100644 --- a/lang/calamares_id.ts +++ b/lang/calamares_id.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,159 +226,155 @@ Calamares::ViewManager - + &Back &Kembali - - + &Next &Berikutnya - - + &Cancel &Batal - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. Batalkan instalasi tanpa mengubah sistem yang ada. - + Setup Failed - + Calamares Initialization Failed Inisialisasi Calamares Gagal - + %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 tidak dapat terinstal. Calamares tidak dapat memuat seluruh modul konfigurasi. Terdapat masalah dengan Calamares karena sedang digunakan oleh distribusi. - + <br/>The following modules could not be loaded: <br/>Modul berikut tidak dapat dimuat. - + 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> - + &Set up now - + &Set up - + &Install &Instal - + Setup is complete. Close the setup program. - + Cancel setup? - + Cancel installation? Batalkan instalasi? - + 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. Apakah Anda benar-benar ingin membatalkan proses instalasi ini? Instalasi akan ditutup dan semua perubahan akan hilang. - + &Yes &Ya - + &No &Tidak - + &Close &Tutup - + Continue with setup? Lanjutkan dengan setelan ini? - + 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> Installer %1 akan membuat perubahan ke disk Anda untuk memasang %2.<br/><strong>Anda tidak dapat membatalkan perubahan tersebut.</strong> - + &Install now &Instal sekarang - + Go &back &Kembali - + &Done &Kelar - + The installation is complete. Close the installer. Instalasi sudah lengkap. Tutup installer. - + Error Kesalahan - + Installation Failed Instalasi Gagal @@ -1289,6 +1285,22 @@ Instalasi akan ditutup dan semua perubahan akan hilang. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1512,6 +1524,42 @@ Instalasi akan ditutup dan semua perubahan akan hilang. Lokasi + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2219,14 +2267,14 @@ Instalasi akan ditutup dan semua perubahan akan hilang. ProcessResult - + There was no output from the command. Tidak ada keluaran dari perintah. - + Output: @@ -2235,52 +2283,52 @@ Keluaran: - + External command crashed. Perintah eksternal rusak. - + Command <i>%1</i> crashed. Perintah <i>%1</i> mogok. - + External command failed to start. Perintah eksternal gagal dimulai - + Command <i>%1</i> failed to start. Perintah <i>%1</i> gagal dimulai. - + Internal error when starting command. Terjadi kesalahan internal saat menjalankan perintah. - + Bad parameters for process job call. Parameter buruk untuk memproses panggilan tugas, - + External command failed to finish. Perintah eksternal gagal diselesaikan . - + Command <i>%1</i> failed to finish in %2 seconds. Perintah <i>%1</i> gagal untuk diselesaikan dalam %2 detik. - + External command finished with errors. Perintah eksternal diselesaikan dengan kesalahan . - + Command <i>%1</i> finished with exit code %2. Perintah <i>%1</i> diselesaikan dengan kode keluar %2. @@ -2329,7 +2377,7 @@ Keluaran: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_is.ts b/lang/calamares_is.ts index 921ce91cd..04a4eb0fe 100644 --- a/lang/calamares_is.ts +++ b/lang/calamares_is.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,159 +226,155 @@ Calamares::ViewManager - + &Back &Til baka - - + &Next &Næst - - + &Cancel &Hætta við - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. Hætta við uppsetningu ánþess að breyta kerfinu. - + Setup Failed - + Calamares Initialization Failed Calamares uppsetning mistókst - + %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 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> - + &Set up now - + &Set up - + &Install &Setja upp - + Setup is complete. Close the setup program. - + Cancel setup? - + Cancel installation? Hætta við uppsetningu? - + 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. Viltu virkilega að hætta við núverandi uppsetningarferli? Uppsetningarforritið mun hætta og allar breytingar tapast. - + &Yes &Já - + &No &Nei - + &Close &Loka - + Continue with setup? Halda áfram með uppsetningu? - + 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> %1 uppsetningarforritið er um það bil að gera breytingar á diskinum til að setja upp %2.<br/><strong>Þú munt ekki geta afturkallað þessar breytingar.</strong> - + &Install now Setja &inn núna - + Go &back Fara til &baka - + &Done &Búið - + The installation is complete. Close the installer. Uppsetning er lokið. Lokaðu uppsetningarforritinu. - + Error Villa - + Installation Failed Uppsetning mistókst @@ -1289,6 +1285,22 @@ Uppsetningarforritið mun hætta og allar breytingar tapast. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1512,6 +1524,42 @@ Uppsetningarforritið mun hætta og allar breytingar tapast. Staðsetning + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2219,65 +2267,65 @@ Uppsetningarforritið mun hætta og allar breytingar tapast. 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. @@ -2326,7 +2374,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_it_IT.ts b/lang/calamares_it_IT.ts index 5d075f1ac..e55ebf7dd 100644 --- a/lang/calamares_it_IT.ts +++ b/lang/calamares_it_IT.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. Il controllo dei requisiti di sistema è completo. @@ -226,159 +226,155 @@ Calamares::ViewManager - + &Back &Indietro - - + &Next &Avanti - - + &Cancel &Annulla - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. Annullare l'installazione senza modificare il sistema. - + Setup Failed - + Calamares Initialization Failed Inizializzazione di Calamares Fallita - + %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 non può essere installato. Calamares non è stato in grado di caricare tutti i moduli configurati. Questo è un problema del modo in cui Calamares viene utilizzato dalla distribuzione. - + <br/>The following modules could not be loaded: <br/>Non è stato possibile caricare il seguente modulo: - + 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> - + &Set up now - + &Set up - + &Install &Installa - + Setup is complete. Close the setup program. - + Cancel setup? - + Cancel installation? Annullare l'installazione? - + 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. Si vuole davvero annullare l'installazione in corso? Il programma d'installazione sarà terminato e tutte le modifiche andranno perse. - + &Yes &Si - + &No &No - + &Close &Chiudi - + Continue with setup? Procedere con la configurazione? - + 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> Il programma d'nstallazione %1 sta per eseguire delle modifiche al tuo disco per poter installare %2.<br/><strong> Non sarà possibile annullare tali modifiche.</strong> - + &Install now &Installa adesso - + Go &back &Indietro - + &Done &Fatto - + The installation is complete. Close the installer. L'installazione è terminata. Chiudere il programma d'installazione. - + Error Errore - + Installation Failed Installazione non riuscita @@ -1289,6 +1285,22 @@ Il programma d'installazione sarà terminato e tutte le modifiche andranno + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1512,6 +1524,42 @@ Il programma d'installazione sarà terminato e tutte le modifiche andranno Posizione + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2219,13 +2267,13 @@ Il programma d'installazione sarà terminato e tutte le modifiche andranno ProcessResult - + There was no output from the command. Non c'era output dal comando. - + Output: @@ -2234,53 +2282,53 @@ Output: - + External command crashed. Il comando esterno si è arrestato. - + Command <i>%1</i> crashed. Il comando <i>%1</i> si è arrestato. - + External command failed to start. Il comando esterno non si è avviato. - + Command <i>%1</i> failed to start. Il comando %1 non si è avviato. - + Internal error when starting command. Errore interno all'avvio del comando. - + Bad parameters for process job call. Parametri errati per elaborare la chiamata al job. - + External command failed to finish. Il comando esterno non è stato portato a termine. - + Command <i>%1</i> failed to finish in %2 seconds. Il comando <i>%1</i> non è stato portato a termine in %2 secondi. - + External command finished with errors. Il comando esterno è terminato con errori. - + Command <i>%1</i> finished with exit code %2. Il comando <i>%1</i> è terminato con codice di uscita %2. @@ -2329,7 +2377,7 @@ Output: (nessun mount point) - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_ja.ts b/lang/calamares_ja.ts index 8a631a3a4..65a73d4b7 100644 --- a/lang/calamares_ja.ts +++ b/lang/calamares_ja.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). %n モジュールを待機中。 - + (%n second(s)) (%n 秒(s)) - + System-requirements checking is complete. 要求されるシステムの確認を終了しました。 @@ -226,160 +226,156 @@ Calamares::ViewManager - + &Back 戻る (&B) - - + &Next 次へ (&N) - - + &Cancel 中止 (&C) - - + Cancel setup without changing the system. システムを変更することなくセットアップを中断します。 - - + Cancel installation without changing the system. システムを変更しないでインストールを中止します。 - + Setup Failed セットアップに失敗しました。 - + Calamares Initialization Failed Calamares によるインストールに失敗しました。 - + %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 をインストールできません。Calamares はすべてのモジュールをロードすることをできませんでした。これは、Calamares のこのディストリビューションでの使用法による問題です。 - + <br/>The following modules could not be loaded: <br/>以下のモジュールがロードできませんでした。: - + 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> %1 のセットアッププログラムは %2 のセットアップのためディスクの内容を変更します。<br/><strong>これらの変更は取り消しできません。</strong> - + &Set up now セットアップ中(&S) - + &Set up セットアップ (&S) - + &Install インストール (&I) - + Setup is complete. Close the setup program. セットアップが完了しました。プログラムを閉じます。 - + 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. 本当に現在の作業を中止しますか? すべての変更が取り消されます。 - + &Yes はい (&Y) - + &No いいえ (&N) - + &Close 閉じる (&C) - + Continue with setup? セットアップを続行しますか? - + 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> %1 インストーラーは %2 をインストールするためディスクの内容を変更しようとしています。<br/><strong>これらの変更は取り消せません。</strong> - + &Install now 今すぐインストール (&I) - + Go &back 戻る (&B) - + &Done 実行 (&D) - + The installation is complete. Close the installer. インストールが完了しました。インストーラーを閉じます。 - + Error エラー - + Installation Failed インストールに失敗 @@ -1291,6 +1287,22 @@ The installer will quit and all changes will be lost. ファイル <code>%1</code>に書き込めません。 + + InitcpioJob + + + Creating initramfs with mkinitcpio. + mkinitcpioとinitramfsを作成中 + + + + InitramfsJob + + + Creating initramfs. + initramfsを作成中 + + InteractiveTerminalPage @@ -1514,6 +1526,42 @@ The installer will quit and all changes will be lost. ロケーション + + LuksBootKeyFileJob + + + Configuring LUKS key file. + LUKSキーファイルを設定中 + + + + + No partitions are defined. + パーティションが定義されていません。 + + + + + + Encrypted rootfs setup error + 暗号化したrootfsセットアップエラー + + + + Root partition %1 is LUKS but no passphrase has been set. + ルートパーティション %1 はLUKSですが、パスワードが設定されていません。 + + + + Could not create LUKS key file for root partition %1. + ルートパーティション %1 のLUKSキーファイルを作成できませんでした。 + + + + Could configure LUKS key file on partition %1. + パーティション %1 にLUKSキーファイルを設定できました。 + + NetInstallPage @@ -2221,14 +2269,14 @@ The installer will quit and all changes will be lost. ProcessResult - + There was no output from the command. コマンドから出力するものがありませんでした。 - + Output: @@ -2237,52 +2285,52 @@ Output: - + External command crashed. 外部コマンドがクラッシュしました。 - + Command <i>%1</i> crashed. コマンド <i>%1</i> がクラッシュしました。 - + External command failed to start. 外部コマンドの起動に失敗しました。 - + Command <i>%1</i> failed to start. コマンド <i>%1</i> の起動に失敗しました。 - + 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. コマンド<i>%1</i> %2 秒以内に終了することに失敗しました。 - + External command finished with errors. 外部のコマンドがエラーで停止しました。 - + Command <i>%1</i> finished with exit code %2. コマンド <i>%1</i> が終了コード %2 で終了しました。. @@ -2331,7 +2379,7 @@ Output: (マウントポイントなし) - + Requirements checking for module <i>%1</i> is complete. モジュール <i>%1</i> に必要なパッケージの確認が完了しました。 diff --git a/lang/calamares_kk.ts b/lang/calamares_kk.ts index 214321ce4..92b22ea2d 100644 --- a/lang/calamares_kk.ts +++ b/lang/calamares_kk.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,158 +226,154 @@ Calamares::ViewManager - + &Back А&ртқа - - + &Next &Алға - - + &Cancel Ба&с тарту - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. - + Setup Failed - + 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 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> - + &Set up now - + &Set up - + &Install - + Setup is complete. Close the setup program. - + 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. - + &Yes - + &No - + &Close - + Continue with setup? - + 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> - + &Install now - + Go &back - + &Done - + The installation is complete. Close the installer. - + Error - + Installation Failed @@ -1288,6 +1284,22 @@ The installer will quit and all changes will be lost. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1511,6 +1523,42 @@ The installer will quit and all changes will be lost. + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2218,65 +2266,65 @@ The installer will quit and all changes will be lost. 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. @@ -2325,7 +2373,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_kn.ts b/lang/calamares_kn.ts index 199db8626..7b8d93e9d 100644 --- a/lang/calamares_kn.ts +++ b/lang/calamares_kn.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,158 +226,154 @@ Calamares::ViewManager - + &Back ಹಿಂದಿನ - - + &Next ಮುಂದಿನ - - + &Cancel ರದ್ದುಗೊಳಿಸು - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. - + Setup Failed - + 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 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> - + &Set up now - + &Set up - + &Install - + Setup is complete. Close the setup program. - + 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. - + &Yes ಹೌದು - + &No ಇಲ್ಲ - + &Close ಮುಚ್ಚಿರಿ - + Continue with setup? - + 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> - + &Install now - + Go &back - + &Done - + The installation is complete. Close the installer. - + Error ದೋಷ - + Installation Failed ಅನುಸ್ಥಾಪನೆ ವಿಫಲವಾಗಿದೆ @@ -1288,6 +1284,22 @@ The installer will quit and all changes will be lost. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1511,6 +1523,42 @@ The installer will quit and all changes will be lost. + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2218,65 +2266,65 @@ The installer will quit and all changes will be lost. 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. @@ -2325,7 +2373,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_ko.ts b/lang/calamares_ko.ts index 235f3070d..944380431 100644 --- a/lang/calamares_ko.ts +++ b/lang/calamares_ko.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). %n 모듈(들)을 기다리는 중. - + (%n second(s)) (%n 초) - + System-requirements checking is complete. 시스템 요구사항 검사가 완료 되었습니다. @@ -226,160 +226,156 @@ Calamares::ViewManager - + &Back 뒤로 (&B) - - + &Next 다음 (&N) - - + &Cancel 취소 (&C) - - + Cancel setup without changing the system. 시스템을 변경 하지 않고 설치를 취소합니다. - - + Cancel installation without changing the system. 시스템 변경 없이 설치를 취소합니다. - + Setup Failed 설치 실패 - + Calamares Initialization Failed Calamares 초기화 실패 - + %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 가 설치될 수 없습니다. Calamares가 모든 구성된 모듈을 불러올 수 없었습니다. 이것은 Calamares가 분포에 의해 사용되는 방식에서 비롯된 문제입니다. - + <br/>The following modules could not be loaded: 다음 모듈 불러오기 실패: - + 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> %1 설치 프로그램이 %2을(를) 설정하기 위해 디스크를 변경하려고 하는 중입니다.<br/><strong>이러한 변경은 취소할 수 없습니다.</strong> - + &Set up now 지금 설치 (&S) - + &Set up 설치 (&S) - + &Install 설치(&I) - + Setup is complete. Close the setup program. 설치가 완료 되었습니다. 설치 프로그램을 닫습니다. - + 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. 정말로 현재 설치 프로세스를 취소하시겠습니까? 설치 관리자가 종료되며 모든 변경은 반영되지 않습니다. - + &Yes 예(&Y) - + &No 아니오(&N) - + &Close 닫기(&C) - + Continue with setup? 설치를 계속하시겠습니까? - + 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> %1 인스톨러가 %2를 설치하기 위해 사용자의 디스크의 내용을 변경하려고 합니다. <br/> <strong>이 변경 작업은 되돌릴 수 없습니다.</strong> - + &Install now 지금 설치 (&I) - + Go &back 뒤로 이동 (&b) - + &Done 완료 (&D) - + The installation is complete. Close the installer. 설치가 완료되었습니다. 설치 관리자를 닫습니다. - + Error 오류 - + Installation Failed 설치 실패 @@ -1290,6 +1286,22 @@ The installer will quit and all changes will be lost. <code>%1</code> 파일에 쓸 수 없습니다. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + mkinitcpio를 사용하여 initramfs 만드는 중. + + + + InitramfsJob + + + Creating initramfs. + initramfs를 만드는 중. + + InteractiveTerminalPage @@ -1513,6 +1525,42 @@ The installer will quit and all changes will be lost. 위치 + + LuksBootKeyFileJob + + + Configuring LUKS key file. + LUKS 키 파일 구성 중. + + + + + No partitions are defined. + 파티션이 정의되지 않았습니다. + + + + + + Encrypted rootfs setup error + 암호화된 rootfs 설정 오류 + + + + Root partition %1 is LUKS but no passphrase has been set. + 루트 파티션 %1이(가) LUKS이지만 암호가 설정되지 않았습니다. + + + + Could not create LUKS key file for root partition %1. + 루트 파티션 %1에 대한 LUKS 키 파일을 생성할 수 없습니다. + + + + Could configure LUKS key file on partition %1. + %1 파티션에서 LUKS 키 파일을 구성할 수 있습니다. + + NetInstallPage @@ -2220,14 +2268,14 @@ The installer will quit and all changes will be lost. ProcessResult - + There was no output from the command. 명령으로부터 아무런 출력이 없습니다. - + Output: @@ -2236,52 +2284,52 @@ Output: - + External command crashed. 외부 명령이 실패했습니다. - + Command <i>%1</i> crashed. <i>%1</i> 명령이 실패했습니다. - + External command failed to start. 외부 명령을 시작하지 못했습니다. - + Command <i>%1</i> failed to start. <i>%1</i> 명령을 시작하지 못했습니다. - + 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. <i>%1</i> 명령을 %2초 안에 완료하지 못했습니다. - + External command finished with errors. 외부 명령이 오류와 함께 완료되었습니다. - + Command <i>%1</i> finished with exit code %2. <i>%1</i> 명령이 종료 코드 %2와 함께 완료되었습니다. @@ -2330,7 +2378,7 @@ Output: (마운트 위치 없음) - + Requirements checking for module <i>%1</i> is complete. <i>%1</i> 모듈에 대한 요구사항 검사가 완료되었습니다. diff --git a/lang/calamares_lo.ts b/lang/calamares_lo.ts index d5a333062..d0a03a73e 100644 --- a/lang/calamares_lo.ts +++ b/lang/calamares_lo.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,158 +226,154 @@ Calamares::ViewManager - + &Back - - + &Next - - + &Cancel - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. - + Setup Failed - + 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 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> - + &Set up now - + &Set up - + &Install - + Setup is complete. Close the setup program. - + 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. - + &Yes - + &No - + &Close - + Continue with setup? - + 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> - + &Install now - + Go &back - + &Done - + The installation is complete. Close the installer. - + Error - + Installation Failed @@ -1288,6 +1284,22 @@ The installer will quit and all changes will be lost. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1511,6 +1523,42 @@ The installer will quit and all changes will be lost. + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2218,65 +2266,65 @@ The installer will quit and all changes will be lost. 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. @@ -2325,7 +2373,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_lt.ts b/lang/calamares_lt.ts index 2bd6a6621..f53552226 100644 --- a/lang/calamares_lt.ts +++ b/lang/calamares_lt.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). Laukiama %n modulio.Laukiama %n modulių.Laukiama %n modulių.Laukiama %n modulio. - + (%n second(s)) (%n sekundė)(%n sekundės)(%n sekundžių)(%n sekundė) - + System-requirements checking is complete. Sistemos reikalavimų tikrinimas yra užbaigtas. @@ -226,160 +226,156 @@ Calamares::ViewManager - + &Back &Atgal - - + &Next &Toliau - - + &Cancel A&tsisakyti - - + Cancel setup without changing the system. Atsisakyti sąrankos, nieko sistemoje nekeičiant. - - + Cancel installation without changing the system. Atsisakyti diegimo, nieko sistemoje nekeičiant. - + Setup Failed Sąranka patyrė nesėkmę - + Calamares Initialization Failed Calamares inicijavimas nepavyko - + %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. Nepavyksta įdiegti %1. Calamares nepavyko įkelti visų sukonfigūruotų modulių. Tai yra problema, susijusi su tuo, kaip distribucija naudoja diegimo programą Calamares. - + <br/>The following modules could not be loaded: <br/>Nepavyko įkelti šių modulių: - + Continue with installation? Tęsti diegimą? - + 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 sąrankos programa, siekdama nustatyti %2, ketina atlikti pakeitimus diske.<br/><strong>Šių pakeitimų nebegalėsite atšaukti.</strong> - + &Set up now Nu&statyti dabar - + &Set up Nu&statyti - + &Install Į&diegti - + Setup is complete. Close the setup program. Sąranka užbaigta. Užverkite sąrankos programą. - + Cancel setup? Atsisakyti sąrankos? - + Cancel installation? Atsisakyti diegimo? - + Do you really want to cancel the current setup process? The setup program will quit and all changes will be lost. Ar tikrai norite atsisakyti dabartinio sąrankos proceso? Sąrankos programa užbaigs darbą ir visi pakeitimai bus prarasti. - + Do you really want to cancel the current install process? The installer will quit and all changes will be lost. Ar tikrai norite atsisakyti dabartinio diegimo proceso? Diegimo programa užbaigs darbą ir visi pakeitimai bus prarasti. - + &Yes &Taip - + &No &Ne - + &Close &Užverti - + Continue with setup? Tęsti sąranką? - + 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> %1 diegimo programa, siekdama įdiegti %2, ketina atlikti pakeitimus diske.<br/><strong>Šių pakeitimų nebegalėsite atšaukti.</strong> - + &Install now Į&diegti dabar - + Go &back &Grįžti - + &Done A&tlikta - + The installation is complete. Close the installer. Diegimas užbaigtas. Užverkite diegimo programą. - + Error Klaida - + Installation Failed Diegimas nepavyko @@ -1290,6 +1286,22 @@ Diegimo programa užbaigs darbą ir visi pakeitimai bus prarasti. Nepavyko rašyti į failą <code>%1</code>. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + Sukuriama initramfs naudojant mkinitcpio. + + + + InitramfsJob + + + Creating initramfs. + Sukuriama initramfs. + + InteractiveTerminalPage @@ -1513,6 +1525,42 @@ Diegimo programa užbaigs darbą ir visi pakeitimai bus prarasti. Vieta + + LuksBootKeyFileJob + + + Configuring LUKS key file. + Konfigūruojamas LUKS raktų failas. + + + + + No partitions are defined. + Nėra jokių apibrėžtų skaidinių. + + + + + + Encrypted rootfs setup error + Šifruoto rootfs sąrankos klaida + + + + Root partition %1 is LUKS but no passphrase has been set. + Šaknies skaidinys %1 yra LUKS, tačiau nebuvo nustatyta jokia slaptafrazė. + + + + Could not create LUKS key file for root partition %1. + Nepavyko šaknies skaidiniui %1 sukurti LUKS rakto failo. + + + + Could configure LUKS key file on partition %1. + Nepavyko konfigūruoti LUKS rakto failo skaidinyje %1. + + NetInstallPage @@ -2220,14 +2268,14 @@ Diegimo programa užbaigs darbą ir visi pakeitimai bus prarasti. ProcessResult - + There was no output from the command. Nebuvo jokios išvesties iš komandos. - + Output: @@ -2236,52 +2284,52 @@ Išvestis: - + External command crashed. Išorinė komanda užstrigo. - + Command <i>%1</i> crashed. Komanda <i>%1</i> užstrigo. - + External command failed to start. Nepavyko paleisti išorinės komandos. - + Command <i>%1</i> failed to start. Nepavyko paleisti komandos <i>%1</i>. - + Internal error when starting command. Paleidžiant komandą, įvyko vidinė klaida. - + Bad parameters for process job call. Blogi parametrai proceso užduoties iškvietai. - + External command failed to finish. Nepavyko pabaigti išorinės komandos. - + Command <i>%1</i> failed to finish in %2 seconds. Nepavyko per %2 sek. pabaigti komandos <i>%1</i>. - + External command finished with errors. Išorinė komanda pabaigta su klaidomis. - + Command <i>%1</i> finished with exit code %2. Komanda <i>%1</i> pabaigta su išėjimo kodu %2. @@ -2330,7 +2378,7 @@ Išvestis: (nėra prijungimo taško) - + Requirements checking for module <i>%1</i> is complete. Reikalavimų tikrinimas <i>%1</i> moduliui yra užbaigtas. diff --git a/lang/calamares_mk.ts b/lang/calamares_mk.ts index f591f3d63..6058b1059 100644 --- a/lang/calamares_mk.ts +++ b/lang/calamares_mk.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,158 +226,154 @@ Calamares::ViewManager - + &Back - - + &Next - - + &Cancel - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. - + Setup Failed - + 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 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> - + &Set up now - + &Set up - + &Install - + Setup is complete. Close the setup program. - + 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. - + &Yes - + &No - + &Close - + Continue with setup? - + 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> - + &Install now - + Go &back - + &Done - + The installation is complete. Close the installer. Инсталацијата е готова. Исклучете го инсталерот. - + Error Грешка - + Installation Failed @@ -1288,6 +1284,22 @@ The installer will quit and all changes will be lost. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1511,6 +1523,42 @@ The installer will quit and all changes will be lost. + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2218,65 +2266,65 @@ The installer will quit and all changes will be lost. 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. @@ -2325,7 +2373,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_mr.ts b/lang/calamares_mr.ts index 887d2b0b5..f4d005f92 100644 --- a/lang/calamares_mr.ts +++ b/lang/calamares_mr.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,158 +226,154 @@ Calamares::ViewManager - + &Back &मागे - - + &Next &पुढे - - + &Cancel &रद्द करा - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. प्रणालीत बदल न करता अधिष्टापना रद्द करा. - + Setup Failed - + 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 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> - + &Set up now - + &Set up - + &Install - + Setup is complete. Close the setup program. - + 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. - + &Yes &होय - + &No &नाही - + &Close &बंद करा - + Continue with setup? - + 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> - + &Install now &आता अधिष्ठापित करा - + Go &back &मागे जा - + &Done &पूर्ण झाली - + The installation is complete. Close the installer. अधिष्ठापना संपूर्ण झाली. अधिष्ठापक बंद करा. - + Error त्रुटी - + Installation Failed अधिष्ठापना अयशस्वी झाली @@ -1288,6 +1284,22 @@ The installer will quit and all changes will be lost. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1511,6 +1523,42 @@ The installer will quit and all changes will be lost. + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2218,65 +2266,65 @@ The installer will quit and all changes will be lost. 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. @@ -2325,7 +2373,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_nb.ts b/lang/calamares_nb.ts index e6c0bb3cf..1ed2dd4aa 100644 --- a/lang/calamares_nb.ts +++ b/lang/calamares_nb.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,159 +226,155 @@ Calamares::ViewManager - + &Back &Tilbake - - + &Next &Neste - - + &Cancel &Avbryt - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. - + Setup Failed - + 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 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> - + &Set up now - + &Set up - + &Install - + Setup is complete. Close the setup program. - + Cancel setup? - + Cancel installation? Avbryte installasjon? - + 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. Vil du virkelig avbryte installasjonen? Installasjonsprogrammet vil avsluttes og alle endringer vil gå tapt. - + &Yes &Ja - + &No &Nei - + &Close &Lukk - + Continue with setup? Fortsette å sette opp? - + 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> %1 vil nå gjøre endringer på harddisken, for å installere %2. <br/><strong>Du vil ikke kunne omgjøre disse endringene.</strong> - + &Install now &Installer nå - + Go &back Gå &tilbake - + &Done &Ferdig - + The installation is complete. Close the installer. Installasjonen er fullført. Lukk installeringsprogrammet. - + Error Feil - + Installation Failed Installasjon feilet @@ -1289,6 +1285,22 @@ Installasjonsprogrammet vil avsluttes og alle endringer vil gå tapt. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1512,6 +1524,42 @@ Installasjonsprogrammet vil avsluttes og alle endringer vil gå tapt.Plassering + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2219,65 +2267,65 @@ Installasjonsprogrammet vil avsluttes og alle endringer vil gå tapt. 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. Ugyldige parametere for prosessens oppgavekall - + 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. @@ -2326,7 +2374,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_ne_NP.ts b/lang/calamares_ne_NP.ts index 069c082a9..53f88b1b2 100644 --- a/lang/calamares_ne_NP.ts +++ b/lang/calamares_ne_NP.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,158 +226,154 @@ Calamares::ViewManager - + &Back - - + &Next - - + &Cancel - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. - + Setup Failed - + 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 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> - + &Set up now - + &Set up - + &Install - + Setup is complete. Close the setup program. - + 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. - + &Yes - + &No - + &Close - + Continue with setup? - + 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> - + &Install now - + Go &back - + &Done - + The installation is complete. Close the installer. - + Error - + Installation Failed @@ -1288,6 +1284,22 @@ The installer will quit and all changes will be lost. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1511,6 +1523,42 @@ The installer will quit and all changes will be lost. + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2218,65 +2266,65 @@ The installer will quit and all changes will be lost. 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. @@ -2325,7 +2373,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_nl.ts b/lang/calamares_nl.ts index ce02fcd02..039ef6f49 100644 --- a/lang/calamares_nl.ts +++ b/lang/calamares_nl.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,159 +226,155 @@ Calamares::ViewManager - + &Back &Terug - - + &Next &Volgende - - + &Cancel &Afbreken - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. Installatie afbreken zonder aanpassingen aan het systeem. - + Setup Failed - + Calamares Initialization Failed Calamares Initialisatie mislukt - + %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 niet worden geïnstalleerd. Calamares kon niet alle geconfigureerde modules laden. Dit is een probleem met hoe Calamares wordt gebruikt door de distributie. - + <br/>The following modules could not be loaded: <br/>The volgende modules konden niet worden geladen: - + 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> - + &Set up now - + &Set up - + &Install &Installeer - + Setup is complete. Close the setup program. - + Cancel setup? - + Cancel installation? Installatie afbreken? - + 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. Wil je het huidige installatieproces echt afbreken? Het installatieprogramma zal afsluiten en alle wijzigingen zullen verloren gaan. - + &Yes &ja - + &No &Nee - + &Close &Sluiten - + Continue with setup? Doorgaan met installatie? - + 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> Het %1 installatieprogramma zal nu aanpassingen maken aan je schijf om %2 te installeren.<br/><strong>Deze veranderingen kunnen niet ongedaan gemaakt worden.</strong> - + &Install now Nu &installeren - + Go &back Ga &terug - + &Done Voltooi&d - + The installation is complete. Close the installer. De installatie is voltooid. Sluit het installatie-programma. - + Error Fout - + Installation Failed Installatie Mislukt @@ -1289,6 +1285,22 @@ Het installatieprogramma zal afsluiten en alle wijzigingen zullen verloren gaan. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1512,6 +1524,42 @@ Het installatieprogramma zal afsluiten en alle wijzigingen zullen verloren gaan. Locatie + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2219,14 +2267,14 @@ Het installatieprogramma zal afsluiten en alle wijzigingen zullen verloren gaan. ProcessResult - + There was no output from the command. Er was geen uitvoer van de opdracht. - + Output: @@ -2235,52 +2283,52 @@ Uitvoer: - + External command crashed. Externe opdracht is vastgelopen. - + Command <i>%1</i> crashed. Opdracht <i>%1</i> is vastgelopen. - + External command failed to start. Externe opdracht kon niet worden gestart. - + Command <i>%1</i> failed to start. Opdracht <i>%1</i> kon niet worden gestart. - + Internal error when starting command. Interne fout bij het starten van de opdracht. - + Bad parameters for process job call. Onjuiste parameters voor procestaak - + External command failed to finish. Externe opdracht is niet correct beëindigd. - + Command <i>%1</i> failed to finish in %2 seconds. Opdracht <i>%1</i> is niet beëindigd in %2 seconden. - + External command finished with errors. Externe opdracht beëindigd met fouten. - + Command <i>%1</i> finished with exit code %2. Opdracht <i>%1</i> beëindigd met foutcode %2. @@ -2329,7 +2377,7 @@ Uitvoer: (geen aankoppelpunt) - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_pl.ts b/lang/calamares_pl.ts index c3beb76f3..68639ced1 100644 --- a/lang/calamares_pl.ts +++ b/lang/calamares_pl.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,159 +226,155 @@ Calamares::ViewManager - + &Back &Wstecz - - + &Next &Dalej - - + &Cancel &Anuluj - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. Anuluj instalację bez dokonywania zmian w systemie. - + Setup Failed - + Calamares Initialization Failed Błąd inicjacji programu Calamares - + %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 nie może zostać zainstalowany. Calamares nie mógł wczytać wszystkich skonfigurowanych modułów. Jest to problem ze sposobem, w jaki Calamares jest używany przez dystrybucję. - + <br/>The following modules could not be loaded: <br/>Następujące moduły nie mogły zostać wczytane: - + 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> - + &Set up now - + &Set up - + &Install Za&instaluj - + Setup is complete. Close the setup program. - + Cancel setup? Anulować ustawianie? - + Cancel installation? Anulować instalację? - + 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. Czy na pewno chcesz anulować obecny proces instalacji? Instalator zostanie zamknięty i wszystkie zmiany zostaną utracone. - + &Yes &Tak - + &No &Nie - + &Close Zam&knij - + Continue with setup? Kontynuować z programem instalacyjnym? - + 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> Instalator %1 zamierza przeprowadzić zmiany na Twoim dysku, aby zainstalować %2.<br/><strong>Nie będziesz mógł cofnąć tych zmian.</strong> - + &Install now &Zainstaluj teraz - + Go &back &Cofnij się - + &Done &Ukończono - + The installation is complete. Close the installer. Instalacja ukończona pomyślnie. Możesz zamknąć instalator. - + Error Błąd - + Installation Failed Wystąpił błąd instalacji @@ -1289,6 +1285,22 @@ Instalator zostanie zamknięty i wszystkie zmiany zostaną utracone. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + Tworzenie initramfs z mkinitcpio. + + + + InitramfsJob + + + Creating initramfs. + Tworzenie initramfs. + + InteractiveTerminalPage @@ -1512,6 +1524,42 @@ Instalator zostanie zamknięty i wszystkie zmiany zostaną utracone.Położenie + + LuksBootKeyFileJob + + + Configuring LUKS key file. + Konfigurowanie pliku klucza LUKS. + + + + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2219,14 +2267,14 @@ Instalator zostanie zamknięty i wszystkie zmiany zostaną utracone. ProcessResult - + There was no output from the command. W wyniku polecenia nie ma żadnego rezultatu. - + Output: @@ -2235,52 +2283,52 @@ Wyjście: - + External command crashed. Zewnętrzne polecenie zakończone niepowodzeniem. - + Command <i>%1</i> crashed. Wykonanie polecenia <i>%1</i> nie powiodło się. - + External command failed to start. Nie udało się uruchomić zewnętrznego polecenia. - + Command <i>%1</i> failed to start. Polecenie <i>%1</i> nie zostało uruchomione. - + Internal error when starting command. Wystąpił wewnętrzny błąd podczas uruchamiania polecenia. - + Bad parameters for process job call. Błędne parametry wywołania zadania. - + External command failed to finish. Nie udało się ukończyć zewnętrznego polecenia. - + Command <i>%1</i> failed to finish in %2 seconds. Nie udało się ukończyć polecenia <i>%1</i> w ciągu %2 sekund. - + External command finished with errors. Ukończono zewnętrzne polecenie z błędami. - + Command <i>%1</i> finished with exit code %2. Polecenie <i>%1</i> zostało ukończone z błędem o kodzie %2. @@ -2329,7 +2377,7 @@ Wyjście: (brak punktu montowania) - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_pt_BR.ts b/lang/calamares_pt_BR.ts index 2e0809b87..533541556 100644 --- a/lang/calamares_pt_BR.ts +++ b/lang/calamares_pt_BR.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). Esperando por %n módulo.Esperando por %n módulos. - + (%n second(s)) (%n segundo)(%n segundos) - + System-requirements checking is complete. Verificação de requerimentos do sistema completa. @@ -226,160 +226,156 @@ Calamares::ViewManager - + &Back &Voltar - - + &Next &Próximo - - + &Cancel &Cancelar - - + Cancel setup without changing the system. Cancelar configuração sem alterar o sistema. - - + Cancel installation without changing the system. Cancelar instalação sem modificar o sistema. - + Setup Failed A Configuração Falhou - + Calamares Initialization Failed Falha na inicialização do Calamares - + %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 não pôde ser instalado. O Calamares não conseguiu carregar todos os módulos configurados. Este é um problema com o modo em que o Calamares está sendo utilizado pela distribuição. - + <br/>The following modules could not be loaded: <br/>Os seguintes módulos não puderam ser carregados: - + Continue with installation? Continuar com a instalação? - + 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> O programa de configuração %1 está prestes a fazer mudanças no seu disco de modo a configurar %2.<br/><strong>Você não será capaz de desfazer estas mudanças.</strong> - + &Set up now &Configurar agora - + &Set up &Configurar - + &Install &Instalar - + Setup is complete. Close the setup program. A configuração está completa. Feche o programa de configuração. - + Cancel setup? Cancelar a configuração? - + Cancel installation? Cancelar a instalação? - + Do you really want to cancel the current setup process? The setup program will quit and all changes will be lost. Você realmente quer cancelar o processo atual de configuração? O programa de configuração será fechado e todas as mudanças serão perdidas. - + Do you really want to cancel the current install process? The installer will quit and all changes will be lost. Você deseja realmente cancelar a instalação atual? O instalador será fechado e todas as alterações serão perdidas. - + &Yes &Sim - + &No &Não - + &Close Fe&char - + Continue with setup? Continuar com configuração? - + 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> O instalador %1 está prestes a fazer alterações no disco a fim de instalar %2.<br/><strong>Você não será capaz de desfazer estas mudanças.</strong> - + &Install now &Instalar agora - + Go &back &Voltar - + &Done Concluí&do - + The installation is complete. Close the installer. A instalação está completa. Feche o instalador. - + Error Erro - + Installation Failed Falha na Instalação @@ -1290,6 +1286,22 @@ O instalador será fechado e todas as alterações serão perdidas.Não foi possível escrever no arquivo <code>%1</code>. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + Criando initramfs com mkinitcpio. + + + + InitramfsJob + + + Creating initramfs. + Criando initramfs. + + InteractiveTerminalPage @@ -1513,6 +1525,42 @@ O instalador será fechado e todas as alterações serão perdidas.Localização + + LuksBootKeyFileJob + + + Configuring LUKS key file. + Configurando o arquivo de chave do LUKS. + + + + + No partitions are defined. + Nenhuma partição está definida. + + + + + + Encrypted rootfs setup error + Erro de configuração de rootfs encriptado + + + + Root partition %1 is LUKS but no passphrase has been set. + A partição raiz %1 é LUKS, mas nenhuma senha foi definida. + + + + Could not create LUKS key file for root partition %1. + Não foi possível criar o arquivo de chave LUKS para a partição raiz %1. + + + + Could configure LUKS key file on partition %1. + Pode configurar o arquivo de chave LUKS na partição% 1. + + NetInstallPage @@ -2220,14 +2268,14 @@ O instalador será fechado e todas as alterações serão perdidas. ProcessResult - + There was no output from the command. Não houve saída do comando. - + Output: @@ -2236,52 +2284,52 @@ Saída: - + External command crashed. O comando externo falhou. - + Command <i>%1</i> crashed. O comando <i>%1</i> falhou. - + External command failed to start. O comando externo falhou ao iniciar. - + Command <i>%1</i> failed to start. O comando <i>%1</i> falhou ao iniciar. - + Internal error when starting command. Erro interno ao iniciar o comando. - + Bad parameters for process job call. Parâmetros ruins para a chamada da tarefa do processo. - + External command failed to finish. O comando externo falhou ao finalizar. - + Command <i>%1</i> failed to finish in %2 seconds. O comando <i>%1</i> falhou ao finalizar em %2 segundos. - + External command finished with errors. O comando externo foi concluído com erros. - + Command <i>%1</i> finished with exit code %2. O comando <i>%1</i> foi concluído com o código %2. @@ -2330,7 +2378,7 @@ Saída: (sem ponto de montagem) - + Requirements checking for module <i>%1</i> is complete. A verificação de requerimentos para o módulo <i>%1</i> está completa. diff --git a/lang/calamares_pt_PT.ts b/lang/calamares_pt_PT.ts index e1d49f242..a727717d2 100644 --- a/lang/calamares_pt_PT.ts +++ b/lang/calamares_pt_PT.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). A aguardar por %n módulo(s).A aguardar por %n módulo(s). - + (%n second(s)) (%n segundo(s))(%n segundo(s)) - + System-requirements checking is complete. A verificação de requisitos de sistema está completa. @@ -226,160 +226,156 @@ Calamares::ViewManager - + &Back &Voltar - - + &Next &Próximo - - + &Cancel &Cancelar - - + Cancel setup without changing the system. Cancelar instalação sem alterar o sistema. - - + Cancel installation without changing the system. Cancelar instalar instalação sem modificar o sistema. - + Setup Failed Falha de Instalação - + Calamares Initialization Failed Falha na Inicialização do Calamares - + %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 não pode ser instalado. O Calamares não foi capaz de carregar todos os módulos configurados. Isto é um problema da maneira como o Calamares é usado pela distribuição. - + <br/>The following modules could not be loaded: <br/>Os módulos seguintes não puderam ser carregados: - + Continue with installation? Continuar com a instalação? - + 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> - + &Set up now &Instalar agora - + &Set up &Instalar - + &Install &Instalar - + Setup is complete. Close the setup program. Instalação completa. Feche o programa de instalação. - + Cancel setup? Cancelar instalação? - + Cancel installation? Cancelar a instalação? - + Do you really want to cancel the current setup process? The setup program will quit and all changes will be lost. Quer mesmo cancelar o processo de instalação atual? O programa de instalação irá fechar todas as alterações serão perdidas. - + Do you really want to cancel the current install process? The installer will quit and all changes will be lost. Tem a certeza que pretende cancelar o atual processo de instalação? O instalador será encerrado e todas as alterações serão perdidas. - + &Yes &Sim - + &No &Não - + &Close &Fechar - + Continue with setup? Continuar com a configuração? - + 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> O %1 instalador está prestes a fazer alterações ao seu disco em ordem para instalar %2.<br/><strong>Não será capaz de desfazer estas alterações.</strong> - + &Install now &Instalar agora - + Go &back Voltar &atrás - + &Done &Feito - + The installation is complete. Close the installer. A instalação está completa. Feche o instalador. - + Error Erro - + Installation Failed Falha na Instalação @@ -1290,6 +1286,22 @@ O instalador será encerrado e todas as alterações serão perdidas.Não foi possível escrever para o ficheiro <code>%1</code>. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1513,6 +1525,42 @@ O instalador será encerrado e todas as alterações serão perdidas.Localização + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2220,14 +2268,14 @@ O instalador será encerrado e todas as alterações serão perdidas. ProcessResult - + There was no output from the command. O comando não produziu saída de dados. - + Output: @@ -2236,52 +2284,52 @@ Saída de Dados: - + External command crashed. O comando externo "crashou". - + Command <i>%1</i> crashed. Comando <i>%1</i> "crashou". - + External command failed to start. Comando externo falhou ao iniciar. - + Command <i>%1</i> failed to start. Comando <i>%1</i> falhou a inicialização. - + Internal error when starting command. Erro interno ao iniciar comando. - + Bad parameters for process job call. Maus parâmetros para chamada de processamento de tarefa. - + External command failed to finish. Comando externo falhou a finalização. - + Command <i>%1</i> failed to finish in %2 seconds. Comando <i>%1</i> falhou ao finalizar em %2 segundos. - + External command finished with errors. Comando externo finalizou com erros. - + Command <i>%1</i> finished with exit code %2. Comando <i>%1</i> finalizou com código de saída %2. @@ -2330,7 +2378,7 @@ Saída de Dados: (sem ponto de montagem) - + Requirements checking for module <i>%1</i> is complete. A verificação de requisitos para módulo <i>%1</i> está completa. diff --git a/lang/calamares_ro.ts b/lang/calamares_ro.ts index fbc795e6a..b979ba4c8 100644 --- a/lang/calamares_ro.ts +++ b/lang/calamares_ro.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,159 +226,155 @@ Calamares::ViewManager - + &Back &Înapoi - - + &Next &Următorul - - + &Cancel &Anulează - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. Anulează instalarea fără schimbarea sistemului. - + Setup Failed - + 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 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> - + &Set up now - + &Set up - + &Install Instalează - + Setup is complete. Close the setup program. - + Cancel setup? - + Cancel installation? Anulez instalarea? - + 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. Doriți să anulați procesul curent de instalare? Programul de instalare va ieși, iar toate modificările vor fi pierdute. - + &Yes &Da - + &No &Nu - + &Close În&chide - + Continue with setup? Continuați configurarea? - + 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> Programul de instalare %1 este pregătit să facă schimbări pe discul dumneavoastră pentru a instala %2.<br/><strong>Nu veți putea anula aceste schimbări.</strong> - + &Install now &Instalează acum - + Go &back Î&napoi - + &Done &Gata - + The installation is complete. Close the installer. Instalarea este completă. Închide instalatorul. - + Error Eroare - + Installation Failed Instalare eșuată @@ -1289,6 +1285,22 @@ Programul de instalare va ieși, iar toate modificările vor fi pierdute. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1512,6 +1524,42 @@ Programul de instalare va ieși, iar toate modificările vor fi pierdute.Locație + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2222,14 +2270,14 @@ Programul de instalare va ieși, iar toate modificările vor fi pierdute. ProcessResult - + There was no output from the command. Nu a existat nici o iesire din comanda - + Output: @@ -2238,52 +2286,52 @@ Output - + External command crashed. Comanda externă a eșuat. - + Command <i>%1</i> crashed. Comanda <i>%1</i> a eșuat. - + External command failed to start. Comanda externă nu a putut fi pornită. - + Command <i>%1</i> failed to start. Comanda <i>%1</i> nu a putut fi pornită. - + Internal error when starting command. Eroare internă la pornirea comenzii. - + Bad parameters for process job call. Parametri proști pentru apelul sarcinii de proces. - + External command failed to finish. Finalizarea comenzii externe a eșuat. - + Command <i>%1</i> failed to finish in %2 seconds. Comanda <i>%1</i> nu a putut fi finalizată în %2 secunde. - + External command finished with errors. Comanda externă finalizată cu erori. - + Command <i>%1</i> finished with exit code %2. Comanda <i>%1</i> finalizată cu codul de ieșire %2. @@ -2332,7 +2380,7 @@ Output - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_ru.ts b/lang/calamares_ru.ts index aaf4c34a5..4de6cc2aa 100644 --- a/lang/calamares_ru.ts +++ b/lang/calamares_ru.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,158 +226,155 @@ Calamares::ViewManager - + &Back &Назад - - + &Next &Далее - - + &Cancel О&тмена - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. Отменить установку без изменения системы. - + Setup Failed - + Сбой установки - + Calamares Initialization Failed Ошибка инициализации Calamares - + %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. Calamares не удалось загрузить все сконфигурированные модули. Эта проблема вызвана тем, как ваш дистрибутив использует Calamares. - + <br/>The following modules could not be loaded: <br/>Не удалось загрузить следующие модули: - + 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> - + Программа установки %1 готова внести изменения на Ваш диск, чтобы установить %2.<br/><strong>Отменить эти изменения будет невозможно.</strong> - + &Set up now - + &Set up - + &Install &Установить - + Setup is complete. Close the setup program. - + Установка завершена. Закройте программу установки. - + 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. Действительно прервать процесс установки? Программа установки сразу прекратит работу, все изменения будут потеряны. - + &Yes &Да - + &No &Нет - + &Close &Закрыть - + Continue with setup? Продолжить установку? - + 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> Программа установки %1 готова внести изменения на Ваш диск, чтобы установить %2.<br/><strong>Отменить эти изменения будет невозможно.</strong> - + &Install now Приступить к &установке - + Go &back &Назад - + &Done &Готово - + The installation is complete. Close the installer. Установка завершена. Закройте установщик. - + Error Ошибка - + Installation Failed Установка завершилась неудачей @@ -410,7 +407,7 @@ The installer will quit and all changes will be lost. %1 Setup Program - + Программа установки %1 @@ -479,7 +476,7 @@ The installer will quit and all changes will be lost. %1 will be shrunk to %2MiB and a new %3MiB partition will be created for %4. - + %1 будет уменьшен до %2MB и новый раздел %3MB будет создан для %4. @@ -522,7 +519,7 @@ The installer will quit and all changes will be lost. No Swap - + Без раздела подкачки @@ -722,12 +719,12 @@ The installer will quit and all changes will be lost. Create new %2MiB partition on %4 (%3) with file system %1. - + Создать новый раздел %2 MB на %4 (%3) с файловой системой %1. Create new <strong>%2MiB</strong> partition on <strong>%4</strong> (%3) with file system <strong>%1</strong>. - + Создать новый раздел <strong>%2 MB</strong> на <strong>%4</strong> (%3) с файловой системой <strong>%1</strong>. @@ -834,7 +831,7 @@ The installer will quit and all changes will be lost. Create Volume Group - + Создать группу томов @@ -1110,7 +1107,7 @@ The installer will quit and all changes will be lost. <Restart checkbox tooltip> - + <Restart checkbox tooltip> @@ -1120,12 +1117,12 @@ The installer will quit and all changes will be lost. <h1>All done.</h1><br/>%1 has been set up on your computer.<br/>You may now start using your new system. - + <h1>Готово.</h1><br/>Система %1 установлена на ваш компьютер.<br/>Можете перезагрузить компьютер и начать использовать вашу новую систему. <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>Если этот флажок установлен, ваша система будет перезагружена сразу после нажатия кнопки <span style="font-style:italic;">Готово</span> или закрытия программы установки.</p></body></html> @@ -1135,12 +1132,12 @@ The installer will quit and all changes will be lost. <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>Если этот флажок установлен, ваша система будет перезагружена сразу после нажатия кнопки <span style=" font-style:italic;">Готово</span> или закрытия программы установки.</p></body></html> <h1>Setup Failed</h1><br/>%1 has not been set up on your computer.<br/>The error message was: %2. - + <h1>Сбой установки</h1><br/>Система %1 не была установлена на ваш компьютер.<br/>Сообщение об ошибке: %2. @@ -1158,7 +1155,7 @@ The installer will quit and all changes will be lost. Setup Complete - + Установка завершена @@ -1168,7 +1165,7 @@ The installer will quit and all changes will be lost. The setup of %1 is complete. - + Установка %1 завершена. @@ -1181,12 +1178,12 @@ The installer will quit and all changes will be lost. Format partition %1 (file system: %2, size: %3 MiB) on %4. - + Форматировать раздел %1 (файловая система: %2, размер: %3 МБ) на %4. Format <strong>%3MiB</strong> partition <strong>%1</strong> with file system <strong>%2</strong>. - + Форматировать раздел <strong>%1</strong> размером <strong>%3MB</strong> с файловой системой <strong>%2</strong>. @@ -1204,22 +1201,22 @@ The installer will quit and all changes will be lost. has at least %1 GiB available drive space - + доступно как минимум %1 ГБ свободного дискового пространства There is not enough drive space. At least %1 GiB is required. - + Недостаточно места на дисках. Необходимо как минимум %1 ГБ. has at least %1 GiB working memory - + доступно как минимум %1 ГБ оперативной памяти The system does not have enough working memory. At least %1 GiB is required. - + Недостаточно оперативной памяти. Необходимо как минимум %1 ГБ. @@ -1244,7 +1241,7 @@ The installer will quit and all changes will be lost. The setup program is not running with administrator rights. - + Программа установки запущена без прав администратора. @@ -1254,7 +1251,7 @@ The installer will quit and all changes will be lost. The screen is too small to display the setup program. - + Экран слишком маленький, чтобы отобразить программу установки. @@ -1275,17 +1272,33 @@ The installer will quit and all changes will be lost. Could not create directories <code>%1</code>. - + Не удалось создать директории <code>%1</code>. Could not open file <code>%1</code>. - + Не удалось открыть файл <code>%1</code>. Could not write to file <code>%1</code>. - + Не удалась запись в файл <code>%1</code>. + + + + InitcpioJob + + + Creating initramfs with mkinitcpio. + Создание initramfs при помощи mkinitcpio. + + + + InitramfsJob + + + Creating initramfs. + Создание initramfs. @@ -1436,32 +1449,32 @@ The installer will quit and all changes will be lost. Shows the complete license text - + Показывает полный текст лицензии Hide license text - + Скрыть текст лицензии Show license agreement - + Показать лицензионное соглашение Hide license agreement - + Скрыть лицензионное соглашение Opens the license agreement in a browser window. - + Открывает лицензионное соглашение в окне браузера. <a href="%1">View license agreement</a> - + <a href="%1">Просмотреть лицензионное соглашение</a> @@ -1511,6 +1524,42 @@ The installer will quit and all changes will be lost. Местоположение + + LuksBootKeyFileJob + + + Configuring LUKS key file. + Конфигурация файла ключа LUKS. + + + + + No partitions are defined. + Разделы не были заданы. + + + + + + Encrypted rootfs setup error + + + + + Root partition %1 is LUKS but no passphrase has been set. + Корневой раздел %1 это LUKS, но ключ шифрования не был задан. + + + + Could not create LUKS key file for root partition %1. + Не удалось создать файл ключа LUKS для корневого раздела %1. + + + + Could configure LUKS key file on partition %1. + + + NetInstallPage @@ -2149,12 +2198,12 @@ The installer will quit and all changes will be lost. has at least one disk device available. - + имеет как минимум одно доступное дисковое устройство. There are no partitons to install on. - + Нет разделов для установки. @@ -2218,14 +2267,14 @@ The installer will quit and all changes will be lost. ProcessResult - + There was no output from the command. Вывода из команды не последовало. - + Output: @@ -2234,52 +2283,52 @@ Output: - + External command crashed. Сбой внешней команды. - + Command <i>%1</i> crashed. Сбой команды <i>%1</i>. - + External command failed to start. Не удалось запустить внешнюю команду. - + Command <i>%1</i> failed to start. Не удалось запустить команду <i>%1</i>. - + 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. Команда <i>%1</i> не завершилась за %2 с. - + External command finished with errors. Внешняя команда завершилась с ошибками - + Command <i>%1</i> finished with exit code %2. Команда <i>%1</i> завершилась с кодом %2. @@ -2325,12 +2374,12 @@ Output: (no mount point) - + (без точки монтирования) - + Requirements checking for module <i>%1</i> is complete. - + Проверка требований для модуля <i>%1</i> завершена. @@ -2485,13 +2534,13 @@ Output: The filesystem %1 cannot be resized. - + Невозможно изменить размер файловой системы %1. The device %1 cannot be resized. - + Невозможно изменить размер устройства %1. @@ -2514,12 +2563,12 @@ Output: Resize <strong>%2MiB</strong> partition <strong>%1</strong> to <strong>%3MiB</strong>. - + Изменить размер <strong>%2MB</strong> раздела <strong>%1</strong> на <strong>%3MB</strong>. Resizing %2MiB partition %1 to %3MiB. - + Изменение размера раздела %1 с %2MB на %3MB. @@ -2541,17 +2590,17 @@ Output: Resize volume group named %1 from %2 to %3. - + Изменить размер группы томов под именем %1 с %2 на %3. Resize volume group named <strong>%1</strong> from <strong>%2</strong> to <strong>%3</strong>. - + Изменить размер группы томов под именем <strong>%1</strong> с <strong>%2</strong> на <strong>%3</strong>. The installer failed to resize a volume group named '%1'. - + Программе установки не удалось изменить размер группы томов под именем '%1'. @@ -2559,7 +2608,7 @@ Output: 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> @@ -2569,7 +2618,7 @@ Output: 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/>Можно продолжить установку, но некоторые возможности могут быть недоступны. @@ -2675,7 +2724,7 @@ Output: Set flags on %1MiB %2 partition. - + Установить флаги %1MiB раздела %2. @@ -2690,22 +2739,22 @@ Output: Clear flags on %1MiB <strong>%2</strong> partition. - + Снять флаги %1MiB раздела <strong>%2</strong>. Flag %1MiB <strong>%2</strong> partition as <strong>%3</strong>. - + Отметить %1MB раздел <strong>%2</strong> флагом как <strong>%3</strong>. Clearing flags on %1MiB <strong>%2</strong> partition. - + Снятие флагов %1MiB раздела <strong>%2</strong>. Setting flags <strong>%3</strong> on %1MiB <strong>%2</strong> partition. - + Установка флагов <strong>%3</strong> %1MiB раздела <strong>%2</strong>. @@ -2851,7 +2900,7 @@ Output: This is an overview of what will happen once you start the setup procedure. - + Это обзор изменений, которые будут применены при запуске процедуры установки. @@ -2949,17 +2998,17 @@ Output: 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. - + Отметив этот пункт, вы поделитесь информацией о установке и своем оборудовании. Эта информация <b>будет отправлена только один раз</b> после завершения установки. By selecting this you will <b>periodically</b> send information about your installation, hardware and applications, to %1. - + Отметив этот пункт, вы будете <b>периодически</b> отправлять %1 информацию о своей установке, оборудовании и приложениях. By selecting this you will <b>regularly</b> send information about your installation, hardware, applications and usage patterns, to %1. - + Отметив этот пункт, вы будете <b>регулярно</b> отправлять %1 информацию о своей установке, оборудовании, приложениях и паттернах их использования. @@ -2975,12 +3024,12 @@ Output: <small>If more than one person will use this computer, you can create multiple accounts after setup.</small> - + <small>Если этот компьютер будет использоваться несколькими людьми, вы сможете создать учетные записи для них после установки.</small> <small>If more than one person will use this computer, you can create multiple accounts after installation.</small> - + <small>Если этот компьютер используется несколькими людьми, Вы сможете создать соответствующие учетные записи сразу после установки.</small> @@ -3027,7 +3076,7 @@ Output: Create Volume Group - + Создать группу томов @@ -3037,12 +3086,12 @@ Output: Volume Group Name: - + Имя группы томов: Volume Group Type: - + Тип группы томов: @@ -3057,17 +3106,17 @@ Output: Total Size: - + Общий объём: Used Size: - + Использованный объём: Total Sectors: - + Всего секторов: @@ -3096,7 +3145,7 @@ Output: Select language - + Выберите язык @@ -3121,17 +3170,17 @@ Output: <h1>Welcome to the Calamares setup program for %1.</h1> - + <h1>Добро пожаловать в программу установки Calamares для %1 .</h1> <h1>Welcome to %1 setup.</h1> - + <h1>Добро пожаловать в программу установки %1 .</h1> About %1 setup - + О установке %1 diff --git a/lang/calamares_sk.ts b/lang/calamares_sk.ts index 00a03251c..04f9e4fd9 100644 --- a/lang/calamares_sk.ts +++ b/lang/calamares_sk.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). Čaká sa na %n modul.Čaká sa na %n moduly.Čaká sa na %n modulov.Čaká sa na %n modulov. - + (%n second(s)) (%n sekunda)(%n sekundy)(%n sekúnd)(%n sekúnd) - + System-requirements checking is complete. Kontrola systémových požiadaviek je dokončená. @@ -226,160 +226,156 @@ Calamares::ViewManager - + &Back &Späť - - + &Next Ď&alej - - + &Cancel &Zrušiť - - + Cancel setup without changing the system. Zrušenie inštalácie bez zmien v systéme. - - + Cancel installation without changing the system. Zruší inštaláciu bez zmeny systému. - + Setup Failed Inštalácia zlyhala - + Calamares Initialization Failed Zlyhala inicializácia inštalátora Calamares - + %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. Nie je možné nainštalovať %1. Calamares nemohol načítať všetky konfigurované moduly. Je problém s tým, ako sa Calamares používa pri distribúcii. - + <br/>The following modules could not be loaded: <br/>Nebolo možné načítať nasledujúce moduly - + Continue with installation? Pokračovať v inštalácii? - + 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> - + &Set up now - + &Set up - + &Install _Inštalovať - + Setup is complete. Close the setup program. - + Cancel setup? Zrušiť inštaláciu? - + Cancel installation? Zrušiť inštaláciu? - + Do you really want to cancel the current setup process? The setup program will quit and all changes will be lost. Naozaj chcete zrušiť aktuálny priebeh inštalácie? Inštalačný program bude ukončený a zmeny budú stratené. - + Do you really want to cancel the current install process? The installer will quit and all changes will be lost. Skutočne chcete zrušiť aktuálny priebeh inštalácie? Inštalátor sa ukončí a všetky zmeny budú stratené. - + &Yes _Áno - + &No _Nie - + &Close _Zavrieť - + Continue with setup? Pokračovať v inštalácii? - + 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> Inštalátor distribúcie %1 sa chystá vykonať zmeny na vašom disku, aby nainštaloval distribúciu %2. <br/><strong>Tieto zmeny nebudete môcť vrátiť späť.</strong> - + &Install now &Inštalovať teraz - + Go &back Prejsť s&päť - + &Done _Dokončiť - + The installation is complete. Close the installer. Inštalácia je dokončená. Zatvorí inštalátor. - + Error Chyba - + Installation Failed Inštalácia zlyhala @@ -1290,6 +1286,22 @@ Inštalátor sa ukončí a všetky zmeny budú stratené. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1513,6 +1525,42 @@ Inštalátor sa ukončí a všetky zmeny budú stratené. Umiestnenie + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2220,14 +2268,14 @@ Inštalátor sa ukončí a všetky zmeny budú stratené. ProcessResult - + There was no output from the command. Žiadny výstup z príkazu. - + Output: @@ -2236,52 +2284,52 @@ Výstup: - + External command crashed. Externý príkaz nečakane skončil. - + Command <i>%1</i> crashed. Príkaz <i>%1</i> nečakane skončil. - + External command failed to start. Zlyhalo spustenie externého príkazu. - + Command <i>%1</i> failed to start. Zlyhalo spustenie príkazu <i>%1</i> . - + Internal error when starting command. Počas spúšťania príkazu sa vyskytla interná chyba. - + Bad parameters for process job call. Nesprávne parametre pre volanie úlohy procesu. - + External command failed to finish. Zlyhalo dokončenie externého príkazu. - + Command <i>%1</i> failed to finish in %2 seconds. Zlyhalo dokončenie príkazu <i>%1</i> počas doby %2 sekúnd. - + External command finished with errors. Externý príkaz bol dokončený s chybami. - + Command <i>%1</i> finished with exit code %2. Príkaz <i>%1</i> skončil s ukončovacím kódom %2. @@ -2330,7 +2378,7 @@ Výstup: (žiadny bod pripojenia) - + Requirements checking for module <i>%1</i> is complete. Kontrola požiadaviek modulu <i>%1</i> je dokončená. diff --git a/lang/calamares_sl.ts b/lang/calamares_sl.ts index ce6069495..35ebd55f6 100644 --- a/lang/calamares_sl.ts +++ b/lang/calamares_sl.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,159 +226,155 @@ Calamares::ViewManager - + &Back &Nazaj - - + &Next &Naprej - - + &Cancel - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. - + Setup Failed - + 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 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> - + &Set up now - + &Set up - + &Install - + Setup is complete. Close the setup program. - + Cancel setup? - + Cancel installation? Preklic namestitve? - + 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. Ali res želite preklicati trenutni namestitveni proces? Namestilni program se bo končal in vse spremembe bodo izgubljene. - + &Yes - + &No - + &Close - + Continue with setup? - + 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> - + &Install now - + Go &back - + &Done - + The installation is complete. Close the installer. - + Error Napaka - + Installation Failed Namestitev je spodletela @@ -1289,6 +1285,22 @@ Namestilni program se bo končal in vse spremembe bodo izgubljene. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1512,6 +1524,42 @@ Namestilni program se bo končal in vse spremembe bodo izgubljene. Položaj + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2219,65 +2267,65 @@ Namestilni program se bo končal in vse spremembe bodo izgubljene. 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. Nepravilni parametri za klic procesa opravila. - + 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. @@ -2326,7 +2374,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_sq.ts b/lang/calamares_sq.ts index e41229a34..e843247c7 100644 --- a/lang/calamares_sq.ts +++ b/lang/calamares_sq.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). Po pritet për %n modul(e).Po pritet për %n modul(e). - + (%n second(s)) (%n sekondë(a))(%n sekondë(a)) - + System-requirements checking is complete. Kontrolli i domosdoshmërive të sistemit u plotësua. @@ -226,160 +226,156 @@ Calamares::ViewManager - + &Back &Mbrapsht - - + &Next &Pasuesi - - + &Cancel &Anuloje - - + Cancel setup without changing the system. Anuloje rregullimin pa ndryshuar sistemin. - - + Cancel installation without changing the system. Anuloje instalimin pa ndryshuar sistemin. - + Setup Failed Rregullimi Dështoi - + Calamares Initialization Failed Gatitja e Calamares-it Dështoi - + %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 s’mund të instalohet. Calamares s’qe në gjendje të ngarkonte krejt modulet e konfiguruar. Ky është një problem që lidhet me mënyrën se si përdoret Calamares nga shpërndarja. - + <br/>The following modules could not be loaded: <br/>S’u ngarkuan dot modulet vijues: - + Continue with installation? Të vazhdohet me instalimin? - + 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> Programi i rregullimit %1 është një hap larg nga bërja e ndryshimeve në diskun tuaj, që të mund të rregullojë %2.<br/><strong>S’do të jeni në gjendje t’i zhbëni këto ndryshime.</strong> - + &Set up now &Rregulloje tani - + &Set up &Rregulloje - + &Install &Instaloje - + Setup is complete. Close the setup program. Rregullimi është i plotë. Mbylleni programin e rregullimit. - + Cancel setup? Të anulohet rregullimi? - + Cancel installation? Të anulohet instalimi? - + Do you really want to cancel the current setup process? The setup program will quit and all changes will be lost. Doni vërtet të anulohet procesi i tanishëm i rregullimit? Programi i rregullimit do të mbyllet dhe krejt ndryshimet do të humbin. - + Do you really want to cancel the current install process? The installer will quit and all changes will be lost. Doni vërtet të anulohet procesi i tanishëm i instalimit? Instaluesi do të mbyllet dhe krejt ndryshimet do të hidhen tej. - + &Yes &Po - + &No &Jo - + &Close &Mbylle - + Continue with setup? Të vazhdohet me rregullimin? - + 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> Instaluesi %1 është një hap larg nga bërja e ndryshimeve në diskun tuaj, që të mund të instalojë %2.<br/><strong>S’do të jeni në gjendje t’i zhbëni këto ndryshime.</strong> - + &Install now &Instaloje tani - + Go &back Kthehu &mbrapsht - + &Done &U bë - + The installation is complete. Close the installer. Instalimi u plotësua. Mbylle instaluesin. - + Error Gabim - + Installation Failed Instalimi Dështoi @@ -1290,6 +1286,22 @@ Instaluesi do të mbyllet dhe krejt ndryshimet do të hidhen tej. S’u shkrua dot te kartelë <code>%1</code>. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + Po krijohet initramfs me mkinitcpio. + + + + InitramfsJob + + + Creating initramfs. + Po krijohet initramfs. + + InteractiveTerminalPage @@ -1513,6 +1525,42 @@ Instaluesi do të mbyllet dhe krejt ndryshimet do të hidhen tej. Vendndodhje + + LuksBootKeyFileJob + + + Configuring LUKS key file. + Po formësohet kartelë kyçesh LUKS. + + + + + No partitions are defined. + S’ka pjesë të përkufizuara. + + + + + + Encrypted rootfs setup error + Gabim ujdisjeje rootfs të fshehtëzuar + + + + Root partition %1 is LUKS but no passphrase has been set. + Pjesa rrënjë %1 është LUKS, por s’është caktuar frazëkalim. + + + + Could not create LUKS key file for root partition %1. + S’u krijua dot kartelë kyçi LUKS për ndarjen rrënjë %1. + + + + Could configure LUKS key file on partition %1. + Mund të formësohej kartelë kyçesh LUKS në pjesën %1. + + NetInstallPage @@ -2220,14 +2268,14 @@ Instaluesi do të mbyllet dhe krejt ndryshimet do të hidhen tej. ProcessResult - + There was no output from the command. S’pati përfundim nga urdhri. - + Output: @@ -2236,52 +2284,52 @@ Përfundim: - + External command crashed. Urdhri i jashtëm u vithis. - + Command <i>%1</i> crashed. Urdhri <i>%1</i> u vithis. - + External command failed to start. Dështoi nisja e urdhrit të jashtëm. - + Command <i>%1</i> failed to start. Dështoi nisja e urdhrit <i>%1</i>. - + Internal error when starting command. Gabim i brendshëm kur niset urdhri. - + Bad parameters for process job call. Parametra të gabuar për thirrje akti procesi. - + External command failed to finish. S’u arrit të përfundohej urdhër i jashtëm. - + Command <i>%1</i> failed to finish in %2 seconds. Urdhri <i>%1</i> s’arriti të përfundohej në %2 sekonda. - + External command finished with errors. Urdhri i jashtë përfundoi me gabime. - + Command <i>%1</i> finished with exit code %2. Urdhri <i>%1</i> përfundoi me kod daljeje %2. @@ -2330,7 +2378,7 @@ Përfundim: (s’ka pikë montimi) - + Requirements checking for module <i>%1</i> is complete. Kontrolli i domosdoshmërive për modulin <i>%1</i> u plotësua. diff --git a/lang/calamares_sr.ts b/lang/calamares_sr.ts index d9265925b..d92da1ad1 100644 --- a/lang/calamares_sr.ts +++ b/lang/calamares_sr.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,159 +226,155 @@ Calamares::ViewManager - + &Back &Назад - - + &Next &Следеће - - + &Cancel &Откажи - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. - + Setup Failed - + 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 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> - + &Set up now - + &Set up - + &Install - + Setup is complete. Close the setup program. - + 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. Да ли стварно желите да прекинете текући процес инсталације? Инсталер ће бити затворен и све промене ће бити изгубљене. - + &Yes - + &No - + &Close - + Continue with setup? Наставити са подешавањем? - + 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> - + &Install now &Инсталирај сада - + Go &back Иди &назад - + &Done - + The installation is complete. Close the installer. - + Error Грешка - + Installation Failed Инсталација није успела @@ -1289,6 +1285,22 @@ The installer will quit and all changes will be lost. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1512,6 +1524,42 @@ The installer will quit and all changes will be lost. Локација + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2219,65 +2267,65 @@ The installer will quit and all changes will be lost. 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. @@ -2326,7 +2374,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_sr@latin.ts b/lang/calamares_sr@latin.ts index 1d383195f..0ef4a34af 100644 --- a/lang/calamares_sr@latin.ts +++ b/lang/calamares_sr@latin.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,159 +226,155 @@ Calamares::ViewManager - + &Back &Nazad - - + &Next &Dalje - - + &Cancel &Prekini - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. - + Setup Failed - + 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 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> - + &Set up now - + &Set up - + &Install - + Setup is complete. Close the setup program. - + Cancel setup? - + Cancel installation? Prekini instalaciju? - + 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. Da li stvarno želite prekinuti trenutni proces instalacije? Instaler će se zatvoriti i sve promjene će biti izgubljene. - + &Yes - + &No - + &Close - + Continue with setup? - + 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> - + &Install now - + Go &back - + &Done - + The installation is complete. Close the installer. - + Error Greška - + Installation Failed Neuspješna instalacija @@ -1289,6 +1285,22 @@ Instaler će se zatvoriti i sve promjene će biti izgubljene. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1512,6 +1524,42 @@ Instaler će se zatvoriti i sve promjene će biti izgubljene. Lokacija + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2219,65 +2267,65 @@ Instaler će se zatvoriti i sve promjene će biti izgubljene. 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. Pogrešni parametri kod poziva funkcije u procesu. - + 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. @@ -2326,7 +2374,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_sv.ts b/lang/calamares_sv.ts index 610ac5cda..85045517b 100644 --- a/lang/calamares_sv.ts +++ b/lang/calamares_sv.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,159 +226,155 @@ Calamares::ViewManager - + &Back &Bakåt - - + &Next &Nästa - - + &Cancel Avbryt - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. - + Setup Failed - + 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 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> - + &Set up now - + &Set up - + &Install - + Setup is complete. Close the setup program. - + Cancel setup? - + Cancel installation? Avbryt 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. Är du säker på att du vill avsluta installationen i förtid? Alla ändringar kommer att gå förlorade. - + &Yes - + &No - + &Close - + Continue with setup? Fortsätt med installation? - + 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> %1-installeraren är på väg att göra ändringar för att installera %2.<br/><strong>Du kommer inte att kunna ångra dessa ändringar!strong> - + &Install now &Installera nu - + Go &back Gå &bakåt - + &Done - + The installation is complete. Close the installer. - + Error Fel - + Installation Failed Installationen misslyckades @@ -1289,6 +1285,22 @@ Alla ändringar kommer att gå förlorade. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1512,6 +1524,42 @@ Alla ändringar kommer att gå förlorade. Plats + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2219,65 +2267,65 @@ Alla ändringar kommer att gå förlorade. 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. Ogiltiga parametrar för processens uppgiftsanrop. - + 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. @@ -2326,7 +2374,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_th.ts b/lang/calamares_th.ts index 52b50460d..927770c31 100644 --- a/lang/calamares_th.ts +++ b/lang/calamares_th.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,159 +226,155 @@ Calamares::ViewManager - + &Back &B ย้อนกลับ - - + &Next &N ถัดไป - - + &Cancel &C ยกเลิก - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. - + Setup Failed - + 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 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> - + &Set up now - + &Set up - + &Install - + Setup is complete. Close the setup program. - + 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. คุณต้องการยกเลิกกระบวนการติดตั้งที่กำลังดำเนินการอยู่หรือไม่? ตัวติดตั้งจะสิ้นสุดการทำงานและไม่บันทึกการเปลี่ยนแปลงที่ได้ดำเนินการก่อนหน้านี้ - + &Yes - + &No - + &Close - + Continue with setup? ดำเนินการติดตั้งต่อหรือไม่? - + 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> ตัวติดตั้ง %1 กำลังพยายามที่จะทำการเปลี่ยนแปลงในดิสก์ของคุณเพื่อติดตั้ง %2<br/><strong>คุณจะไม่สามารถยกเลิกการเปลี่ยนแปลงเหล่านี้ได้</strong> - + &Install now &ติดตั้งตอนนี้ - + Go &back กลั&บไป - + &Done - + The installation is complete. Close the installer. - + Error ข้อผิดพลาด - + Installation Failed การติดตั้งล้มเหลว @@ -1289,6 +1285,22 @@ The installer will quit and all changes will be lost. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1512,6 +1524,42 @@ The installer will quit and all changes will be lost. ตำแหน่ง + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2219,65 +2267,65 @@ The installer will quit and all changes will be lost. 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. @@ -2326,7 +2374,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_tr_TR.ts b/lang/calamares_tr_TR.ts index 15a17eefd..730bb881a 100644 --- a/lang/calamares_tr_TR.ts +++ b/lang/calamares_tr_TR.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). %n modülü bekleniyor.%n modül(leri) bekleniyor. - + (%n second(s)) (%n saniye(ler))(%n saniye) - + System-requirements checking is complete. Sistem gereksinimleri kontrolü tamamlandı. @@ -226,160 +226,156 @@ Calamares::ViewManager - + &Back &Geri - - + &Next &Sonraki - - + &Cancel &Vazgeç - - + Cancel setup without changing the system. Sistemi değiştirmeden kurulumu iptal edin. - - + Cancel installation without changing the system. Sistemi değiştirmeden kurulumu iptal edin. - + Setup Failed Kurulum Başarısız - + Calamares Initialization Failed Calamares Başlatılamadı - + %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 yüklenemedi. Calamares yapılandırılmış modüllerin bazılarını yükleyemedi. Bu, Calamares'in kullandığınız dağıtıma uyarlamasından kaynaklanan bir sorundur. - + <br/>The following modules could not be loaded: <br/>Aşağıdaki modüller yüklenemedi: - + Continue with installation? Kuruluma devam edilsin mi? - + 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 sistem kurulum uygulaması,%2 ayarlamak için diskinizde değişiklik yapmak üzere. <br/><strong>Bu değişiklikleri geri alamayacaksınız.</strong> - + &Set up now &Şimdi kur - + &Set up &Kur - + &Install &Yükle - + Setup is complete. Close the setup program. Kurulum tamamlandı. Kurulum programını kapatın. - + Cancel setup? Kurulum iptal edilsin mi? - + Cancel installation? Yüklemeyi iptal et? - + Do you really want to cancel the current setup process? The setup program will quit and all changes will be lost. Mevcut kurulum işlemini gerçekten iptal etmek istiyor musunuz? Kurulum uygulaması sonlandırılacak ve tüm değişiklikler kaybedilecek. - + Do you really want to cancel the current install process? The installer will quit and all changes will be lost. Yükleme işlemini gerçekten iptal etmek istiyor musunuz? Yükleyiciden çıkınca tüm değişiklikler kaybedilecek. - + &Yes &Evet - + &No &Hayır - + &Close &Kapat - + Continue with setup? Kuruluma devam et? - + 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> %1 sistem yükleyici %2 yüklemek için diskinizde değişiklik yapacak.<br/><strong>Bu değişiklikleri geri almak mümkün olmayacak.</strong> - + &Install now &Şimdi yükle - + Go &back Geri &git - + &Done &Tamam - + The installation is complete. Close the installer. Yükleme işi tamamlandı. Sistem yükleyiciyi kapatın. - + Error Hata - + Installation Failed Kurulum Başarısız @@ -1292,6 +1288,22 @@ Sistem güç kaynağına bağlı değil. <code>%1</code> dosyasına yazılamadı. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + Mkinitcpio ile initramfs oluşturuluyor. + + + + InitramfsJob + + + Creating initramfs. + Initramfs oluşturuluyor. + + InteractiveTerminalPage @@ -1515,6 +1527,42 @@ Sistem güç kaynağına bağlı değil. Sistem Yereli + + LuksBootKeyFileJob + + + Configuring LUKS key file. + LUKS anahtar dosyası yapılandırılıyor. + + + + + No partitions are defined. + Hiçbir disk bölümü tanımlanmadı. + + + + + + Encrypted rootfs setup error + Şifrelenmiş rootfs kurulum hatası + + + + Root partition %1 is LUKS but no passphrase has been set. + %1 kök disk bölümü LUKS olacak fakat bunun için parola belirlenmedi. + + + + Could not create LUKS key file for root partition %1. + %1 kök disk bölümü için LUKS anahtar dosyası oluşturulamadı. + + + + Could configure LUKS key file on partition %1. + %1 disk bölümü LUKS anahtar dosyası yapılandırılabilir. + + NetInstallPage @@ -2223,14 +2271,14 @@ Sistem güç kaynağına bağlı değil. ProcessResult - + There was no output from the command. Komut çıktısı yok. - + Output: @@ -2239,52 +2287,52 @@ Output: - + External command crashed. Harici komut çöktü. - + Command <i>%1</i> crashed. Komut <i>%1</i> çöktü. - + External command failed to start. Harici komut başlatılamadı. - + Command <i>%1</i> failed to start. Komut <i>%1</i> başlatılamadı. - + Internal error when starting command. Komut başlatılırken dahili hata. - + Bad parameters for process job call. Çalışma adımları başarısız oldu. - + External command failed to finish. Harici komut başarısız oldu. - + Command <i>%1</i> failed to finish in %2 seconds. Komut <i>%1</i> %2 saniyede başarısız oldu. - + External command finished with errors. Harici komut hatalarla bitti. - + Command <i>%1</i> finished with exit code %2. Komut <i>%1</i> %2 çıkış kodu ile tamamlandı @@ -2333,7 +2381,7 @@ Output: (bağlama noktası yok) - + Requirements checking for module <i>%1</i> is complete. <i>%1</i> modülü için gerekenler tamamlandı. diff --git a/lang/calamares_uk.ts b/lang/calamares_uk.ts index 0c97745d8..b21f16d51 100644 --- a/lang/calamares_uk.ts +++ b/lang/calamares_uk.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). Очікування %n модулю.Очікування %n модулів.Очікування %n модулів.Очікування %n модулів. - + (%n second(s)) (%n секунда)(%n секунди)(%n секунд(и))(%n секунд(и)) - + System-requirements checking is complete. Перевірка системних вимог завершена. @@ -226,159 +226,155 @@ Calamares::ViewManager - + &Back &Назад - - + &Next &Вперед - - + &Cancel &Скасувати - - + Cancel setup without changing the system. Скасувати налаштування без зміни системи. - - + Cancel installation without changing the system. Скасувати встановлення без зміни системи. - + Setup Failed Помилка встановлення - + Calamares Initialization Failed Помилка ініціалізації Calamares - + %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 неможливо встановити. Calamares не зміг завантажити всі налаштовані модулі. Ця проблема зв'язана з тим, як Calamares використовується дистрибутивом. - + <br/>The following modules could not be loaded: <br/>Не вдалося завантажити наступні модулі: - + 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> Програма налаштування %1 збирається внести зміни до вашого диска, щоб налаштувати %2. <br/><strong> Ви не зможете скасувати ці зміни.</strong> - + &Set up now &Налаштувати зараз - + &Set up &Налаштувати - + &Install &Встановити - + Setup is complete. Close the setup program. Встановлення виконано. Закрити програму встановлення. - + 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. Чи ви насправді бажаєте скасувати процес встановлення? Установник закриється і всі зміни буде втрачено. - + &Yes &Так - + &No &Ні - + &Close &Закрити - + Continue with setup? Продовжити встановлення? - + 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> Установник %1 збирається зробити зміни на вашому диску, щоб встановити %2.<br/><strong>Ці зміни неможливо буде повернути.</strong> - + &Install now &Встановити зараз - + Go &back Перейти &назад - + &Done &Закінчити - + The installation is complete. Close the installer. Встановлення виконано. Закрити установник. - + Error Помилка - + Installation Failed Втановлення завершилося невдачею @@ -1289,6 +1285,22 @@ The installer will quit and all changes will be lost. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1512,6 +1524,42 @@ The installer will quit and all changes will be lost. Місцезнаходження + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2220,65 +2268,65 @@ The installer will quit and all changes will be lost. 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. @@ -2327,7 +2375,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_ur.ts b/lang/calamares_ur.ts index 3d6e51b22..cb4d80715 100644 --- a/lang/calamares_ur.ts +++ b/lang/calamares_ur.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,158 +226,154 @@ Calamares::ViewManager - + &Back - - + &Next - - + &Cancel - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. - + Setup Failed - + 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 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> - + &Set up now - + &Set up - + &Install - + Setup is complete. Close the setup program. - + 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. - + &Yes - + &No - + &Close - + Continue with setup? - + 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> - + &Install now - + Go &back - + &Done - + The installation is complete. Close the installer. - + Error - + Installation Failed @@ -1288,6 +1284,22 @@ The installer will quit and all changes will be lost. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1511,6 +1523,42 @@ The installer will quit and all changes will be lost. + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2218,65 +2266,65 @@ The installer will quit and all changes will be lost. 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. @@ -2325,7 +2373,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_uz.ts b/lang/calamares_uz.ts index b7b12e55a..7cd148c37 100644 --- a/lang/calamares_uz.ts +++ b/lang/calamares_uz.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -226,158 +226,154 @@ Calamares::ViewManager - + &Back - - + &Next - - + &Cancel - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. - + Setup Failed - + 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 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> - + &Set up now - + &Set up - + &Install - + Setup is complete. Close the setup program. - + 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. - + &Yes - + &No - + &Close - + Continue with setup? - + 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> - + &Install now - + Go &back - + &Done - + The installation is complete. Close the installer. - + Error - + Installation Failed @@ -1288,6 +1284,22 @@ The installer will quit and all changes will be lost. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1511,6 +1523,42 @@ The installer will quit and all changes will be lost. + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2218,65 +2266,65 @@ The installer will quit and all changes will be lost. 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. @@ -2325,7 +2373,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_zh_CN.ts b/lang/calamares_zh_CN.ts index 192c8c380..9cd30f582 100644 --- a/lang/calamares_zh_CN.ts +++ b/lang/calamares_zh_CN.ts @@ -209,17 +209,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). - + (%n second(s)) - + System-requirements checking is complete. @@ -227,159 +227,155 @@ Calamares::ViewManager - + &Back 后退(&B) - - + &Next 下一步(&N) - - + &Cancel 取消(&C) - - + Cancel setup without changing the system. - - + Cancel installation without changing the system. 取消安装,并不做任何更改。 - + Setup Failed - + Calamares Initialization Failed Calamares安装失败 - + %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无法安装。 Calamares无法加载所有已配置的模块。这是分配使用Calamares的方式的问题。 - + <br/>The following modules could not be loaded: <br/>无法加载以下模块: - + 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> - + &Set up now - + &Set up - + &Install 安装(&I) - + Setup is complete. Close the setup program. - + 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. 确定要取消当前的安装吗? 安装程序将退出,所有修改都会丢失。 - + &Yes &是 - + &No &否 - + &Close &关闭 - + Continue with setup? 要继续安装吗? - + 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> %1 安装程序将在您的磁盘上做出变更以安装 %2。<br/><strong>您将无法复原这些变更。</strong> - + &Install now 现在安装 (&I) - + Go &back 返回 (&B) - + &Done &完成 - + The installation is complete. Close the installer. 安装已完成。请关闭安装程序。 - + Error 错误 - + Installation Failed 安装失败 @@ -1291,6 +1287,22 @@ The installer will quit and all changes will be lost. + + InitcpioJob + + + Creating initramfs with mkinitcpio. + + + + + InitramfsJob + + + Creating initramfs. + + + InteractiveTerminalPage @@ -1514,6 +1526,42 @@ The installer will quit and all changes will be lost. 位置 + + 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 configure LUKS key file on partition %1. + + + NetInstallPage @@ -2221,14 +2269,14 @@ The installer will quit and all changes will be lost. ProcessResult - + There was no output from the command. 命令没有输出。 - + Output: @@ -2237,52 +2285,52 @@ Output: - + External command crashed. 外部命令已崩溃。 - + Command <i>%1</i> crashed. 命令 <i>%1</i> 已崩溃。 - + External command failed to start. 无法启动外部命令。 - + Command <i>%1</i> failed to start. 无法启动命令 <i>%1</i>。 - + 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. 命令 <i>%1</i> 未能在 %2 秒内完成。 - + External command finished with errors. 外部命令已完成,但出现了错误。 - + Command <i>%1</i> finished with exit code %2. 命令 <i>%1</i> 以退出代码 %2 完成。 @@ -2331,7 +2379,7 @@ Output: - + Requirements checking for module <i>%1</i> is complete. diff --git a/lang/calamares_zh_TW.ts b/lang/calamares_zh_TW.ts index d69d780d9..efdea35b3 100644 --- a/lang/calamares_zh_TW.ts +++ b/lang/calamares_zh_TW.ts @@ -208,17 +208,17 @@ Calamares::RequirementsChecker - + Waiting for %n module(s). 正在等待 %n 個模組。 - + (%n second(s)) (%n 秒) - + System-requirements checking is complete. 系統需求檢查完成。 @@ -226,160 +226,156 @@ Calamares::ViewManager - + &Back 返回 (&B) - - + &Next 下一步 (&N) - - + &Cancel 取消(&C) - - + Cancel setup without changing the system. 取消安裝,不更改系統。 - - + Cancel installation without changing the system. 不變更系統並取消安裝。 - + Setup Failed 設定失敗 - + Calamares Initialization Failed Calamares 初始化失敗 - + %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 無法安裝。Calamares 無法載入所有已設定的模組。散佈版使用 Calamares 的方式有問題。 - + <br/>The following modules could not be loaded: <br/>以下的模組無法載入: - + 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> %1 設定程式將在您的磁碟上做出變更以設定 %2。<br/><strong>您將無法復原這些變更。</strong> - + &Set up now 現在進行設定 (&S) - + &Set up 設定 (&S) - + &Install 安裝(&I) - + Setup is complete. Close the setup program. 設定完成。關閉設定程式。 - + 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. 您真的想要取消目前的安裝程序嗎? 安裝程式將會退出且所有變動將會遺失。 - + &Yes 是(&Y) - + &No 否(&N) - + &Close 關閉(&C) - + Continue with setup? 繼續安裝? - + 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> %1 安裝程式將在您的磁碟上做出變更以安裝 %2。<br/><strong>您將無法復原這些變更。</strong> - + &Install now 現在安裝 (&I) - + Go &back 上一步 (&B) - + &Done 完成(&D) - + The installation is complete. Close the installer. 安裝完成。關閉安裝程式。 - + Error 錯誤 - + Installation Failed 安裝失敗 @@ -1290,6 +1286,22 @@ The installer will quit and all changes will be lost. 無法寫入至檔案 <code>%1</code>。 + + InitcpioJob + + + Creating initramfs with mkinitcpio. + 正在使用 mkinitcpio 建立 initramfs。 + + + + InitramfsJob + + + Creating initramfs. + 正在建立 initramfs。 + + InteractiveTerminalPage @@ -1513,6 +1525,42 @@ The installer will quit and all changes will be lost. 位置 + + LuksBootKeyFileJob + + + Configuring LUKS key file. + 正在設定 LUKS 金鑰檔案。 + + + + + No partitions are defined. + 沒有已定義的分割區。 + + + + + + Encrypted rootfs setup error + 已加密的 rootfs 設定錯誤 + + + + Root partition %1 is LUKS but no passphrase has been set. + 根分割區 %1 為 LUKS 但沒有設定密碼。 + + + + Could not create LUKS key file for root partition %1. + 無法為根分割區 %1 建立 LUKS 金鑰檔。 + + + + Could configure LUKS key file on partition %1. + 無法在分割區 %1 設定 LUKS 金鑰檔。 + + NetInstallPage @@ -2220,14 +2268,14 @@ The installer will quit and all changes will be lost. ProcessResult - + There was no output from the command. 指令沒有輸出。 - + Output: @@ -2236,52 +2284,52 @@ Output: - + External command crashed. 外部指令當機。 - + Command <i>%1</i> crashed. 指令 <i>%1</i> 已當機。 - + External command failed to start. 外部指令啟動失敗。 - + Command <i>%1</i> failed to start. 指令 <i>%1</i> 啟動失敗。 - + 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. 指令 <i>%1</i> 在結束 %2 秒內失敗。 - + External command finished with errors. 外部指令結束時發生錯誤。 - + Command <i>%1</i> finished with exit code %2. 指令 <i>%1</i> 結束時有錯誤碼 %2。 @@ -2330,7 +2378,7 @@ Output: (沒有掛載點) - + Requirements checking for module <i>%1</i> is complete. 模組 <i>%1</i> 需求檢查完成。 From 08ac97b1eae05911e3e5e6725d1eefe32565836e Mon Sep 17 00:00:00 2001 From: Calamares CI Date: Mon, 29 Jul 2019 13:29:03 +0200 Subject: [PATCH 013/302] i18n: [dummypythonqt] Automatic merge of Transifex translations --- .../lang/et/LC_MESSAGES/dummypythonqt.mo | Bin 872 -> 880 bytes .../lang/et/LC_MESSAGES/dummypythonqt.po | 6 +++--- .../lang/zh_TW/LC_MESSAGES/dummypythonqt.mo | Bin 925 -> 924 bytes .../lang/zh_TW/LC_MESSAGES/dummypythonqt.po | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/modules/dummypythonqt/lang/et/LC_MESSAGES/dummypythonqt.mo b/src/modules/dummypythonqt/lang/et/LC_MESSAGES/dummypythonqt.mo index 23c6048966fbfd8f920c86cdc361017dda6cd96e..cdb2466fa84ca8e127a9762d324b14318cb28f02 100644 GIT binary patch delta 78 zcmaFC_JM6eh-n5R149B3b2Bh7oMd8PPzTaifiy3W{tKiffHXHV1A{1#RsqtcK-y|! VX8, YEAR. # # Translators: -# Madis, 2018 +# Madis Otenurm, 2018 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Madis, 2018\n" +"Last-Translator: Madis Otenurm, 2018\n" "Language-Team: Estonian (https://www.transifex.com/calamares/teams/20061/et/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" diff --git a/src/modules/dummypythonqt/lang/zh_TW/LC_MESSAGES/dummypythonqt.mo b/src/modules/dummypythonqt/lang/zh_TW/LC_MESSAGES/dummypythonqt.mo index 43817982da70956f0ccdd3e86cea3162c51bda87..f13ff2d5fd45d65ec6884e3352102ece429c9782 100644 GIT binary patch delta 79 zcmbQsK8Jlmh-m{O149B3i!m@TJY-^E&;ZgufHV(~R%B*ikO9(qKpG_P4WuoBbkfF7 WZ${3SyPKcQ?|-p+*XDbS`xycJRuMx0 delta 80 zcmbQkK9_w$h-o7u149B3i!m@TJYr&C&;Zgufiw@0R$^vgkO9*AKpG_P1Eej1bn?bd XZ$>V!)U-4OkJ7}v^v!n}_cH, YEAR. # # Translators: -# Jeff Huang , 2017 +# 黃柏諺 , 2017 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Jeff Huang , 2017\n" +"Last-Translator: 黃柏諺 , 2017\n" "Language-Team: Chinese (Taiwan) (https://www.transifex.com/calamares/teams/20061/zh_TW/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" From 2bac96425f6c96eb809cfbccd6b408890fb1c9aa Mon Sep 17 00:00:00 2001 From: Calamares CI Date: Mon, 29 Jul 2019 13:29:04 +0200 Subject: [PATCH 014/302] i18n: [python] Automatic merge of Transifex translations --- lang/python.pot | 51 +---- lang/python/ar/LC_MESSAGES/python.mo | Bin 3255 -> 3192 bytes lang/python/ar/LC_MESSAGES/python.po | 49 +---- lang/python/ast/LC_MESSAGES/python.mo | Bin 5387 -> 5255 bytes lang/python/ast/LC_MESSAGES/python.po | 49 +---- lang/python/be/LC_MESSAGES/python.po | 49 +---- lang/python/bg/LC_MESSAGES/python.po | 49 +---- lang/python/ca/LC_MESSAGES/python.mo | Bin 9227 -> 8352 bytes lang/python/ca/LC_MESSAGES/python.po | 52 +---- lang/python/ca@valencia/LC_MESSAGES/python.po | 49 +---- lang/python/cs_CZ/LC_MESSAGES/python.mo | Bin 9380 -> 8485 bytes lang/python/cs_CZ/LC_MESSAGES/python.po | 51 +---- lang/python/da/LC_MESSAGES/python.mo | Bin 8622 -> 7771 bytes lang/python/da/LC_MESSAGES/python.po | 52 +---- lang/python/de/LC_MESSAGES/python.mo | Bin 8948 -> 8079 bytes lang/python/de/LC_MESSAGES/python.po | 51 +---- lang/python/el/LC_MESSAGES/python.po | 49 +---- lang/python/en_GB/LC_MESSAGES/python.po | 49 +---- lang/python/eo/LC_MESSAGES/python.po | 49 +---- lang/python/es/LC_MESSAGES/python.po | 49 +---- lang/python/es_MX/LC_MESSAGES/python.po | 49 +---- lang/python/es_PR/LC_MESSAGES/python.po | 49 +---- lang/python/et/LC_MESSAGES/python.mo | Bin 1981 -> 1989 bytes lang/python/et/LC_MESSAGES/python.po | 53 +----- lang/python/eu/LC_MESSAGES/python.po | 49 +---- lang/python/fa/LC_MESSAGES/python.po | 49 +---- lang/python/fi_FI/LC_MESSAGES/python.mo | Bin 8463 -> 7648 bytes lang/python/fi_FI/LC_MESSAGES/python.po | 51 +---- lang/python/fr/LC_MESSAGES/python.mo | Bin 9201 -> 8295 bytes lang/python/fr/LC_MESSAGES/python.po | 53 +----- lang/python/fr_CH/LC_MESSAGES/python.po | 49 +---- lang/python/gl/LC_MESSAGES/python.po | 49 +---- lang/python/gu/LC_MESSAGES/python.po | 49 +---- lang/python/he/LC_MESSAGES/python.mo | Bin 10061 -> 9147 bytes lang/python/he/LC_MESSAGES/python.po | 51 +---- lang/python/hi/LC_MESSAGES/python.mo | Bin 1596 -> 11347 bytes lang/python/hi/LC_MESSAGES/python.po | 178 ++++++++---------- lang/python/hr/LC_MESSAGES/python.mo | Bin 8896 -> 8030 bytes lang/python/hr/LC_MESSAGES/python.po | 51 +---- lang/python/hu/LC_MESSAGES/python.mo | Bin 9035 -> 8184 bytes lang/python/hu/LC_MESSAGES/python.po | 51 +---- lang/python/id/LC_MESSAGES/python.po | 49 +---- lang/python/is/LC_MESSAGES/python.po | 49 +---- lang/python/it_IT/LC_MESSAGES/python.po | 49 +---- lang/python/ja/LC_MESSAGES/python.mo | Bin 8186 -> 8919 bytes lang/python/ja/LC_MESSAGES/python.po | 70 ++----- lang/python/kk/LC_MESSAGES/python.po | 49 +---- lang/python/kn/LC_MESSAGES/python.po | 49 +---- lang/python/ko/LC_MESSAGES/python.mo | Bin 9298 -> 8396 bytes lang/python/ko/LC_MESSAGES/python.po | 51 +---- lang/python/lo/LC_MESSAGES/python.po | 49 +---- lang/python/lt/LC_MESSAGES/python.mo | Bin 9191 -> 8318 bytes lang/python/lt/LC_MESSAGES/python.po | 51 +---- lang/python/mk/LC_MESSAGES/python.po | 49 +---- lang/python/mr/LC_MESSAGES/python.po | 49 +---- lang/python/nb/LC_MESSAGES/python.po | 49 +---- lang/python/ne_NP/LC_MESSAGES/python.po | 49 +---- lang/python/nl/LC_MESSAGES/python.po | 49 +---- lang/python/pl/LC_MESSAGES/python.mo | Bin 5690 -> 5408 bytes lang/python/pl/LC_MESSAGES/python.po | 49 +---- lang/python/pt_BR/LC_MESSAGES/python.mo | Bin 9199 -> 8342 bytes lang/python/pt_BR/LC_MESSAGES/python.po | 51 +---- lang/python/pt_PT/LC_MESSAGES/python.mo | Bin 7323 -> 7452 bytes lang/python/pt_PT/LC_MESSAGES/python.po | 57 ++---- lang/python/ro/LC_MESSAGES/python.po | 49 +---- lang/python/ru/LC_MESSAGES/python.po | 49 +---- lang/python/sk/LC_MESSAGES/python.po | 49 +---- lang/python/sl/LC_MESSAGES/python.po | 49 +---- lang/python/sq/LC_MESSAGES/python.mo | Bin 8864 -> 8019 bytes lang/python/sq/LC_MESSAGES/python.po | 51 +---- lang/python/sr/LC_MESSAGES/python.po | 49 +---- lang/python/sr@latin/LC_MESSAGES/python.po | 49 +---- lang/python/sv/LC_MESSAGES/python.po | 49 +---- lang/python/th/LC_MESSAGES/python.po | 49 +---- lang/python/tr_TR/LC_MESSAGES/python.mo | Bin 8938 -> 8082 bytes lang/python/tr_TR/LC_MESSAGES/python.po | 51 +---- lang/python/uk/LC_MESSAGES/python.po | 49 +---- lang/python/ur/LC_MESSAGES/python.po | 49 +---- lang/python/uz/LC_MESSAGES/python.po | 49 +---- lang/python/zh_CN/LC_MESSAGES/python.po | 49 +---- lang/python/zh_TW/LC_MESSAGES/python.mo | Bin 8320 -> 7483 bytes lang/python/zh_TW/LC_MESSAGES/python.po | 53 +----- 82 files changed, 509 insertions(+), 2631 deletions(-) diff --git a/lang/python.pot b/lang/python.pot index f159d4752..b31490417 100644 --- a/lang/python.pot +++ b/lang/python.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -32,8 +32,7 @@ msgstr "Mounting partitions." #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -42,7 +41,7 @@ msgstr "Configuration Error" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "No partitions are defined for
{!s}
to use." @@ -211,22 +210,6 @@ msgstr "Configuring mkinitcpio." msgid "No root mount point is given for
{!s}
to use." msgstr "No root mount point is given for
{!s}
to use." -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "Creating initramfs with mkinitcpio." - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "Process Failed" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "Configuring encrypted swap." @@ -324,18 +307,6 @@ msgstr "Install bootloader." msgid "Remove live user from target system" msgstr "Remove live user from target system" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "Creating initramfs." - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "Failed to run update-initramfs on the target" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "The exit code was {}" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "Setting hardware clock." @@ -348,6 +319,10 @@ msgstr "Creating initramfs with dracut." 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/initramfscfg/main.py:41 msgid "Configuring initramfs." msgstr "Configuring initramfs." @@ -356,18 +331,6 @@ msgstr "Configuring initramfs." msgid "Configuring OpenRC dmcrypt service." msgstr "Configuring OpenRC dmcrypt service." -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "Configuring LUKS key file." - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "Encrypted rootfs setup error" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "Rootfs partition {!s} is LUKS but no passphrase found." - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "Writing fstab." diff --git a/lang/python/ar/LC_MESSAGES/python.mo b/lang/python/ar/LC_MESSAGES/python.mo index d44bd3613bed68a8dfc1f9fad955dfcbbab6b5c5..75d05ea24b6adc09b4b3a4db0dbd869e01d96881 100644 GIT binary patch delta 710 zcmX}qJ1j#{9LMp$K4_^&t7xfe+A39#L`)`02OP#S2oHBH9?KGnB_6#;XygU7@lGu zK41plFpEB~*%;T`*R1vKIg+6YT`U*a0Rotg<7bL z`oT30V+{-Vg_@u6JM$M%?>CTzY!8!IamOz(%KG+1Lnr&h6nb0DE{Q@GHU8FSHi|!( z!$iQ@ND(LKZ@T>h?5BT&TKEyC@f%Z^4w_A25f$NWOtHRIXr%E9wcsm`V;%FDY9V!IOxE9U3qb+;#Q%(AB{ndK=UCTe~AUO>H delta 765 zcmXxi%PWLY7{~Ev#xU-8<2INWmvP-#D+yueKTsr-lD}Y5lq5eJO z`1w`Y6kL7wgsPfC$rbuenrRg@ot%9bhc^nC4Sf&VFoia9Tcz2wmC?~@b?5(~@1QL= z2w`=uFLc-J%NjKxxPGHxmKQ(wPJ8{KiMgfah57im?>;|p;;g4GoegK**-D*;oV8Sf L2WRm_@tx-nNMK9F diff --git a/lang/python/ar/LC_MESSAGES/python.po b/lang/python/ar/LC_MESSAGES/python.po index e226bf074..11dc09b36 100644 --- a/lang/python/ar/LC_MESSAGES/python.po +++ b/lang/python/ar/LC_MESSAGES/python.po @@ -12,7 +12,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: aboodilankaboot, 2019\n" "Language-Team: Arabic (https://www.transifex.com/calamares/teams/20061/ar/)\n" @@ -36,8 +36,7 @@ msgstr "جاري تركيب الأقسام" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -46,7 +45,7 @@ msgstr "خطأ في الضبط" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -208,20 +207,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "العملية فشلت" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -320,18 +305,6 @@ msgstr "تثبيت محمل الإقلاع" msgid "Remove live user from target system" msgstr "إزالة المستخدم المباشر من النظام الهدف" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "كود الخروج كان {}" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "جاري إعداد ساعة الهاردوير" @@ -344,6 +317,10 @@ msgstr "" 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 "" @@ -352,18 +329,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/ast/LC_MESSAGES/python.mo b/lang/python/ast/LC_MESSAGES/python.mo index 6cacaf7af9f624b2104cbaf7dddf65b6b38f0190..a349964df7e7a88dbee912248d96bd46f910e1c2 100644 GIT binary patch delta 1043 zcmY+@%}bO~6vy%7_~fKElP}|IO^svbOKN6nrbaL*5kW*77usT|RS~%v5ELe`2+}}? zik1m3%8kLKe}EeaK?GMKNCa*|(pD{W(f4;B6})i$+&j-a-gD16GuiZ}F}+pdeK1BV z^E`7Z$Ltm!1o*?)%QcJRU#!N6XLcR0VkJJtG91Tl%wR39;3eF}dW@X%_kF16Njztk zw%05od@zF*xQNZTip98p_&k(n_K(e_#=AVh8S^4y+0K0Sur5 zdWuobw+xG3KKO<;dI7Is__SFY_MmR^3>DxsUcfIH#bxZnZ5+mUz8_E;TiCzHMqEN= zY6trpNzYq8#XajV-00Ojpk{?puASjRO*ffiEGBKait{6#7o^X3BCe|f?DY)jFW_a9WsSG@oL delta 1120 zcmZY8Pe@cz6vy$C^E9VS(oq)r55kL z(faA_^m`l3PGdueA6lDdwg+Rl1BdW1X0Z+Da63N6GaSIL zsFXw-gZWw10dAmPg!;k)(u8XjeyY$pE7VV-}V!rM5Ai>S~ywwN8mG-@Fqm6|80`|sE1t9X)m z>o&6-o<|-0H7XLHFopHxLp3mn<9H!L{1y7AT-b}tNaS6CDYt5g09Q<`pOs)_ienRw}PK36Oxr)Q>% ce(uuLmHFAacsN!l7bZ)^od5sryG^U!KW%+y-v9sr diff --git a/lang/python/ast/LC_MESSAGES/python.po b/lang/python/ast/LC_MESSAGES/python.po index d5c40ef55..ad2ec77e2 100644 --- a/lang/python/ast/LC_MESSAGES/python.po +++ b/lang/python/ast/LC_MESSAGES/python.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: enolp , 2019\n" "Language-Team: Asturian (https://www.transifex.com/calamares/teams/20061/ast/)\n" @@ -35,8 +35,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -45,7 +44,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -212,20 +211,6 @@ msgstr "Configurando mkinitcpio." msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "Configurando l'intercambéu cifráu." @@ -317,18 +302,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "Fallu al executar update-initramfs nel destín" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "El códigu de salida foi {}" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "Configurando'l reló de hardware." @@ -341,6 +314,10 @@ msgstr "" msgid "Failed to run dracut on the target" msgstr "Fallu al executar dracut nel destín" +#: src/modules/dracut/main.py:59 +msgid "The exit code was {}" +msgstr "El códigu de salida foi {}" + #: src/modules/initramfscfg/main.py:41 msgid "Configuring initramfs." msgstr "" @@ -349,18 +326,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "Configurando'l serviciu dmcrypt d'OpenRC." -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/be/LC_MESSAGES/python.po b/lang/python/be/LC_MESSAGES/python.po index c44a1f531..ccb6d0192 100644 --- a/lang/python/be/LC_MESSAGES/python.po +++ b/lang/python/be/LC_MESSAGES/python.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Language-Team: Belarusian (https://www.transifex.com/calamares/teams/20061/be/)\n" "MIME-Version: 1.0\n" @@ -31,8 +31,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -41,7 +40,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -203,20 +202,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -311,18 +296,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -335,6 +308,10 @@ msgstr "" 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 "" @@ -343,18 +320,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/bg/LC_MESSAGES/python.po b/lang/python/bg/LC_MESSAGES/python.po index 23cc5301c..7742ffbd5 100644 --- a/lang/python/bg/LC_MESSAGES/python.po +++ b/lang/python/bg/LC_MESSAGES/python.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Georgi Georgiev , 2018\n" "Language-Team: Bulgarian (https://www.transifex.com/calamares/teams/20061/bg/)\n" @@ -35,8 +35,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -45,7 +44,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -207,20 +206,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -311,18 +296,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -335,6 +308,10 @@ msgstr "" 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 "" @@ -343,18 +320,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/ca/LC_MESSAGES/python.mo b/lang/python/ca/LC_MESSAGES/python.mo index 52cfde3edd139b61f1578f79e803d4359e568e18..d235d0590842f5a5c1c7c5e11e19280082848872 100644 GIT binary patch delta 1627 zcmYk+Sx8h-9LMp0)1-}-+n717qqb*@TZ>wbHMUU*DlHaL^iU7hOB8J|K`%vt#BHT0 z2_o#lz`?g5OF{^O9(;))GN_0iqM}H8>H9l#g$|tiIp@sWv;5CF_tKXB*2KHK;58#{ zCYO-A0%iyBa*zipC(Udd=KAi#O6m`>2w!3ye#AnIq?^@at?wb!?{{zozQ#FdGtJhR zC9Hr#74>$UhsSUs-t_Au7^eOavvCq57z(8ZtU^ts8P(4&EXFfffHyE72XQWrVmZFW zYR0#}6mn@;l#%*lBX&@4N3HZes>2tk4kl0?PNF83m6>|K5_726qax6Tn$T&~!tSCL zHi~-xE0!|8*(|drD8mZu#s)l#gvf?)DSkzDICr+$N^C-P+>51n1vSCPScYSM`zLIs z9?UY^hpngy+{MH)3P}p>IDtE`hBzZg4r@cFf{MAlj950|2@Cu_CBAmyk znJq!R-=CLq5?4|0AZ(iW#W3+#2ZJ<3@h5J=e5Tiedr`mN#u&awt*nAsY{nR>!waZL zJ;g@+!ob3o(Ye6?^>p2~-Dtr~wC2 zhwn4$PzHEOAud5}*(ubXKfnrnh1$YzetS55wc9f?gFoGN>`+zas{~r{z$92(Es7@kh#{y)v zE47d{TgGx}BTub1n5x=3)M}&TwdC1k#&!2R9d%fzl2#uhYdbW)OWGr)s?; z=40oQLdN&PT{CW(3q4zDe0AM{1$QoHs6f&d=zQolO(kvbbn+51=iFUooh5g|IXCWW z#+9}8YD^BN?VRo{$hhhK&gk+EWu8ms&#DS|_p?qXJF{ICcd8C?`i6(}kbKR*o`e8vPA883TL}4`2hH!B#vU zJAQQe{z{z3^#QyK-@^sQ6wPTG)46aRXW*17V-nbb>i6QEcmT)aF`R_QQ4@ZHTF5W4 z|Dwj5T+LY6j&-;NYw;PZ$9*`J`OQ%p`oU?`L_gzP{1YeO^fBch&PPS43pe5pR3uKJ zp1**auzGBHf|;lZ+fn0oqsH5Tci8N;7>iGOqOFlzjB*n(H_A#5a^MNQaELlX?3Li0M_gCE7$zr{BC zS8*%OV)@$H^Vp1U;0F8(*I@(OybpWuaeM{0;T6=`cTFrWaN9)Uzmf|%E@)>b(Bkh{ z7)H2=n+AA++2keE$`>+<7Ve{de+Vs}$5r?bF2&^>yzcMC4m^k2*l2e72qx-@zXr^4 zK_Pq>7vYa_e{w@PdAgA`nWs?$?2bKxmj36c1^s~c;xIB){RDE!q)@rz#{IphaSj)0 zL`j57k_)&1uc5MfHvedvPSjaGg*t-$asOAGPrsJTQ_gf@69%X=KNw#>iR{T-LLJ>- zsErqESXL{Im8c7Ys0DnCn)nK~U zo!N9S=!b5`2Dx0w-MkwXeCq~5E-0<9ey%nsWNpFEIHB8oV~C+otJ{Xx*)~6L+xvIw za@zNDZS&MGjhis3wJE$ zWA`rFSYCwh1fdstxvbUm*2~*yYugK<&E~A{t zVO4F97Y?|A%`khPQ;2?3wyn+{wzdownr59|HPPWE0}UspFF zj)+T$JU?{8WNAvn!Ab6bn=XV-aC=lK$7ORX#lrtb!4KT$XdV>ZFE!XUSuWu+aTHDyVbyqg_#hL$v@EB^z=YHDl% diff --git a/lang/python/ca/LC_MESSAGES/python.po b/lang/python/ca/LC_MESSAGES/python.po index b9fd96871..d8ff64f9f 100644 --- a/lang/python/ca/LC_MESSAGES/python.po +++ b/lang/python/ca/LC_MESSAGES/python.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Davidmp , 2019\n" "Language-Team: Catalan (https://www.transifex.com/calamares/teams/20061/ca/)\n" @@ -35,8 +35,7 @@ msgstr "Es munten les particions." #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -45,7 +44,7 @@ msgstr "Error de configuració" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "No s'han definit particions perquè les usi
{!s}
." @@ -217,22 +216,6 @@ msgid "No root mount point is given for
{!s}
to use." msgstr "" "No s'ha proporcionat el punt de muntatge perquè l'usi
{!s}
." -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "Es creen initramfs amb mkinitcpio." - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "Ha fallat el procés." - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" -"El procés
mkinitcpio
ha fallat amb el codi d'error {!s}. L'ordre " -"era
{!s}
." - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "Es configura l'intercanvi encriptat." @@ -331,18 +314,6 @@ msgstr "S'instal·la el carregador d'arrencada." msgid "Remove live user from target system" msgstr "Suprimeix l'usuari de la sessió autònoma del sistema de destinació" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "Es creen initramfs." - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "Ha fallat executar update-initramfs a la destinació." - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "El codi de sortida ha estat {}" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "S'estableix el rellotge del maquinari." @@ -355,6 +326,10 @@ msgstr "Es creen initramfs amb dracut." msgid "Failed to run dracut on the target" msgstr "Ha fallat executar dracut a la destinació." +#: src/modules/dracut/main.py:59 +msgid "The exit code was {}" +msgstr "El codi de sortida ha estat {}" + #: src/modules/initramfscfg/main.py:41 msgid "Configuring initramfs." msgstr "Es configuren initramfs." @@ -363,19 +338,6 @@ msgstr "Es configuren initramfs." msgid "Configuring OpenRC dmcrypt service." msgstr "Es configura el sevei OpenRC dmcrypt." -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "Es configura el fitxer de clau LUKS." - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "Error de configuració de rootfs encriptat." - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" -"La partició de rootfs {!s} és LUKS però no se n'ha trobat cap contrasenya." - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "S'escriu fstab." diff --git a/lang/python/ca@valencia/LC_MESSAGES/python.po b/lang/python/ca@valencia/LC_MESSAGES/python.po index 41bb10c11..5c242bf1b 100644 --- a/lang/python/ca@valencia/LC_MESSAGES/python.po +++ b/lang/python/ca@valencia/LC_MESSAGES/python.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Language-Team: Catalan (Valencian) (https://www.transifex.com/calamares/teams/20061/ca@valencia/)\n" "MIME-Version: 1.0\n" @@ -31,8 +31,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -41,7 +40,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -203,20 +202,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -307,18 +292,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -331,6 +304,10 @@ msgstr "" 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 "" @@ -339,18 +316,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/cs_CZ/LC_MESSAGES/python.mo b/lang/python/cs_CZ/LC_MESSAGES/python.mo index 5088700635a4bb263490c655df4c90bfd9088416..0ec2c6aef2df2adcadc33ad60f16c2e19188403e 100644 GIT binary patch delta 1627 zcmXxkOGs2v9LMp$Hff`#j^&t>*7(RuE%VV!r&2SehfHKt#6(FCgQ6hYWWnSvq84=t zT}X>4szuKsS_BbDL{ZdEC=eu+z}mD3Op?C8JJ$neKIfdd_dNdRoO^fsz1H|>p6`~C zI><%jy{Ts1c+JNTDL2h*2L?Q2SW5jqhVTQ{<2WwD!gR9+tn=(a{Xc{?_yzOP=9z6U zi(8OF8TBZZV=pepL9hM>7f>I^9Gt>J^!t+omZ2sRLG`mA7vn_?;s7qh$5?>FxD>x( zHRIbfg#ZmJGLjEA;vVWz)JpH5I(&=jU<}pa6l!AGnaTG{F_(G+DgxV36Y4`P>^5p) z!>IQsv6%7Avdo%b36|hNT#J{G5ZQCA!bwzz1@q0;U=yn2(^!l*P!oKDOYoi7K7kSH zzHGA?wxA|(8{?}eBq&623_G!wIIqMw9>9lq1XEd__U2Pl4-Af zIS=a)wqQ5LumWFuj-&d|qLVPzp(fN7r@*A`94e$&@EQ)FLRC($t8ou%Mg2%$mhkEy zaU1m+)N^fwM-k}7Mtp!;z;|4SLBiaRov7#IpDAc2GpN&E%t_L~&B!};1{LC~coJVB zi?(uJQpXYO!L!(fBdF)AxML?UhR1Oj8NybEleeZFIU8|1NMSdBJV1qX3R95pkbAhm zwvaV@#&*+Ie%F$H$*OHaZCjYUkvyNwJluPpj*9GTT2G;wT;evw-Cy@!s-%$2rWLaV ztRZXFd@8J!93gA6N(#S{_BW5rEp?Nkqb<;O)w?apYsY89O*()r-uQ0FH_)JKr~OmX zcJQ%t6F1N@$xURPXq^RZ4_{sP8vyPBovQ+=nyhVTSH(*@kaNhDWX`*L?l@-2ec}AL zU$X#iR%7Bt+P*nXMaH1>Cu6VElX*F@Fsm%pxs%(mib|J$@7ZRMbr|{6)P3RiphLY-kYLSJHB7AWU5jNsdr%wI=Bjlu^P`| zBYsF_+t zKrR%#hSFY58Es)J&ci)82Oq{Nd;;s}UmfQ{UKm5^=x1DxS8x_CD)(Ppjgp~u+=&Ay znfL(Z`R`FWEUWN4Sc1}FD@waPDD4g4OiW`V{i~M$1kuEi`ZFGZ$c)e!YCO@Baf(;P*VC9@=;&$wFWQaVqDA)y$3r`es}Q> zJcE4Hk9=ty&v0=o7d32QX}Aq#%^pB`@JZyOPVlt~$I!q(aS85XIx>MnDD^Wa1Nag( zj-w2`hV+mmwGLT+)rChf^B@x@I|Ul0BgxikVq%faKC#r(zn5k?PVEHC>Xl7=^Z(<`RE`pV zj$SD#C~L@OR$BdOhWdFl;y-SLY7mC?Dz_zm6$|G$;jGBk+r;DB(1XfCYHOY z+(pQ7aYblZ=_5f3{? z!qokC$_fQkPvd8$9}k;@I_}th1Nm&E-?8`SvQ};+ z;7+c(QrnwOQq3PTxicY0aeL4Xy63AFyW>^CRhz=;K0{kZB5CaR9xSwDSh+XCwvO8J zKFvzS4ux_fv6Q>F`f2xUb=}N=aedey6$b4m`ytcMl@T+w rWzvbvJZ27=mZ9@wxopVFWp&t0#H3B#@8q&W?6rGq7K~o3Z7KO1^gof* diff --git a/lang/python/cs_CZ/LC_MESSAGES/python.po b/lang/python/cs_CZ/LC_MESSAGES/python.po index 752a7c60d..9215054e0 100644 --- a/lang/python/cs_CZ/LC_MESSAGES/python.po +++ b/lang/python/cs_CZ/LC_MESSAGES/python.po @@ -12,7 +12,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Pavel Borecki , 2019\n" "Language-Team: Czech (Czech Republic) (https://www.transifex.com/calamares/teams/20061/cs_CZ/)\n" @@ -36,8 +36,7 @@ msgstr "Připojování oddílů." #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -46,7 +45,7 @@ msgstr "Chyba nastavení" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "Pro
{!s}
nejsou zadány žádné oddíly." @@ -215,22 +214,6 @@ msgstr "Nastavování mkinitcpio." msgid "No root mount point is given for
{!s}
to use." msgstr "Pro
{!s}
není zadán žádný přípojný bod." -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "Vytváření initramfs pomocí mkinitcpio." - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "Proces zhavaroval" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" -"Proces
mkinitcpio
zhavaroval kódem chyby {!s}. Příkaz byl " -"
{!s}
." - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "Nastavování šifrovaného prostoru pro odkládání stránek paměti." @@ -334,18 +317,6 @@ msgstr "Instalace zavaděče systému." msgid "Remove live user from target system" msgstr "Odebrat uživatele živé relace z cílového systému" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "Vytváření initramfs." - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "Na cíli se nepodařilo spustit update-initramfs" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "Návratový kód byl {}" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "Nastavování hardwarových hodin." @@ -358,6 +329,10 @@ msgstr "Vytváření initramfs s dracut." msgid "Failed to run dracut on the target" msgstr "Na cíli se nepodařilo spustit dracut" +#: src/modules/dracut/main.py:59 +msgid "The exit code was {}" +msgstr "Návratový kód byl {}" + #: src/modules/initramfscfg/main.py:41 msgid "Configuring initramfs." msgstr "Nastavování initramfs." @@ -366,18 +341,6 @@ msgstr "Nastavování initramfs." msgid "Configuring OpenRC dmcrypt service." msgstr "Nastavování služby OpenRC dmcrypt." -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "Nastavování souboru s klíčem pro LUKS šifrování." - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "Chyba nastavení šifrovaného kořenového oddílu" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "Kořenový oddíl {!s} je LUKS ale nebyla nalezena žádná heslová fráze." - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "Zapisování fstab." diff --git a/lang/python/da/LC_MESSAGES/python.mo b/lang/python/da/LC_MESSAGES/python.mo index 60e2bdda844d93314ab6976075153b56c8793987..81024c8f77d9da069859b08b8dfa362f29528e56 100644 GIT binary patch delta 1623 zcmXxkOGs2v9LMp$qvazT-#J?2Bg?cbt+eqmS!yNNL&&g*7CkH>qD4}a6%)~-CeE7Py-*sAoigGyoUw&!n^(r z!}JsUX8W)S6~G`yR?>*lXveR(9apo@;DT2080+u@)?*rBhOo`^BI>Niuvz!vQVbAP zDK?@eIPCSWqjKO85}Qq+j`A}qS%2rS|H}F-?$SV2sD3AED|=AMb`|x&EmY)Bu?jz- za>vij#9~Fb18Y#Za|v~%BgmZg3R#&_`8n zsBECFqjHN|TKKJ@Cd9h79yNIpwT?={yNfEsM5-p7Et+d1RY7Wgw`eO=w57A9Y_@@w zRIQp%g`0R`)GMi??N(9#=qPzh-J)Hqr*cB>7f=_KBYZa8qQy3O^P677TB@?QnyR7% z;$!C)-azAf;l5_du(fQ7{~ELDTS7no489$rBjfLN-s#cm9>Iglu|*d5-Gl5=+17}ZD-b*Ezo$` z2$2^=f@ahhh!|dYOOyml6b+Xk8cmG;0TNA66ED0mnn3gg`2Edn2#MjOXFhYz%$&nAx;9V*~oQ7!TqMJdYjt zec8zq;_GX%js87&JHCg@jVYP4oXnx)D&C1RtBskDt5EF$ybTZHWITrTcmg%yH>idD zQuaD(yoMUa!Y)i;A5O=oF^T)JiTTY@PV~T8)I>kwLcD@gan8i}!6m2&b>kMyq9XAb z>i!>46V}wm6U;+R*o7Lm7d2iMr{D;7Fuys#i574Uwd0>r5tvXH573Tx&|Zftu^*f9 zEnI@iNig31U3Fw*p8QRDK-+$k|ylsL=)^mh30jfg~!YN-(rgP zWqcABuzc<8MQp*txEa63hj9kmybCk<1ip+r@ORX^@17PfaK|*_zm^V<4(;qDTKFes z#t<&zwvqN8W|Lo_2A;wwT3{#Y`E95T9K{uQ8awd{F2hA6fXtzCyHQDd2>CPbbI=Ap zFL9zIx`axSO73dM8A!Cu22`lGqjI8voA3?PbHCz3tYKTqiDk&9%{J6{9%=*okf55w zsBu5Ud$Dwm6Ycab)CBcx?`~X;8fXw(aWD4Z3Do`9a2?KNo9fTw4m^c=uAcXyaoSJ| z>npdPMZL;*k@-sIZ%!17nH;pzPE`9*4s6a8P%AxvX*`1p>FlO>=bfnJ%i@Fh32MUY zXk)V#KerFHu-}jmz+A(%`u^*yU5TfWT!JCVc_2$yd{82*a9d}cC3sG6ak>8(ar%FhE9HUZMRy$C%)>8>c^qoVL zq>FVzQC=*dE>eS{u-8(%sAH)rrKPdaZ+7`K3b#Ukb6HK}eyYB2C6eClII7A9YG-s7 zhj=;Xyw#{wmsL{hlT%SXkv?X;x)l0{s47aNP1Gu?vRj#|WFt`wKW@=KkP2KyT|w24 z&&1KXs;y%u^*p|@*UCF1Rwg&-w1!)&-%hUa9lMxwvsTW{6@7as6Ii=*#ewj<>Zb6Y z>aC6I+ER;u7T zT|;?w_ZM1($xBn=HR(j>#+gH>i33*Y&UJ~wuAWgXSfvK*lHf}y?!SMto1g_ zO^1Kf?(N(XFQQ=k#auDxxt8v?a)A|XZRc>&ay_eH2SH)Lw*$w@c*AbG)%5mk2#-yi zJ^D)B2NNdi))x1|sqCOb99qM+#PRTKA{l;^m=#`3^vz%IJT++TV#i(~xbRNVRdno( zm5<`!JH>J&!j9zg;h|*Jl>hDiNb+DsQ+e@@dy6onW;L#i!mu$8fybRY2c2EF33w8KJTQRAe`SY(j7;m{!s} to use." msgstr "Der er ikke angivet nogle partitioner som
{!s}
skal bruge." @@ -217,22 +216,6 @@ msgid "No root mount point is given for
{!s}
to use." msgstr "" "Der er ikke angivet noget rodmonteringspunkt som
{!s}
skal bruge." -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "Opretter initramfs med mkinitcpio." - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "Processen mislykkedes" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" -"Processen
mkinitcpio
mislykkedes med fejlkoden {!s}. Kommandoen " -"blev
{!s}
." - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "Konfigurerer krypteret swap." @@ -329,18 +312,6 @@ msgstr "Installér bootloader." msgid "Remove live user from target system" msgstr "Fjern livebruger fra målsystemet" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "Opretter initramfs." - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "Kunne ikke køre update-initramfs på målet" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "Afslutningskoden var {}" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "Indstiller hardwareur." @@ -353,6 +324,10 @@ msgstr "Opretter initramfs med dracut." msgid "Failed to run dracut on the target" msgstr "Kunne ikke køre dracut på målet" +#: src/modules/dracut/main.py:59 +msgid "The exit code was {}" +msgstr "Afslutningskoden var {}" + #: src/modules/initramfscfg/main.py:41 msgid "Configuring initramfs." msgstr "Konfigurerer initramfs." @@ -361,19 +336,6 @@ msgstr "Konfigurerer initramfs." msgid "Configuring OpenRC dmcrypt service." msgstr "Konfigurerer OpenRC dmcrypt-tjeneste." -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "Konfigurerer LUKS-nøglefil." - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "Fejl ved opsætning af krypteret rootfs" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" -"Rootfs-partitionen {!s} er LUKS men der blev ikke fundet nogen adgangskode." - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "Skriver fstab." diff --git a/lang/python/de/LC_MESSAGES/python.mo b/lang/python/de/LC_MESSAGES/python.mo index d0f2e4e58d3eb75a61f5a577d580e8048ba2bb81..7196846bc2bd6c224bc756ae394fecfecb47d2e6 100644 GIT binary patch delta 1623 zcmXxkOGs2v9LMqhjHZq6SCgYT`6x3p)6()WR#s*dA>`mAToghsN)T$36;pxWB8nO^ zg=pcT2zo$+s}=?JfFdwx*8`La!mv$L)~4_8-tpj>&pF3?&pqdV{`dZDyRswlDJSu| zQQE1is9~?!QM{DM4<#$fY(Hkl?ZZ;~cd!6o;THUY`4~txtHaH42T=dNiJNc+SD-C7 zYcPwLpGFz|4qSsLaUG7w`%f{K{uj)|MGTH=B~IgN ze2-N;-~Q3aW}qU)y|4)n(eFU*bP_e;bJPU0s0kNQ3(H7#?=QtH`gN!Xw4oL>jM~^O z)W)V!_s?Sy&o@gmYla|};9;!Cvq*^S5pKYF)PyV3&1$e2HSq~7!mFqSKExotjE{fC z5dFjqvp#G^E#MYLHqwaE=)hS#h_%FdJw~tx@8S{kvOS$$KXR#^#yvQS+Q1tuMjzq4 z;4!PjF#UTut{%cwO}`6u-AFF+-$mm#16BA9+tAPQWFPLv$$0-ODuh+6q7}nfhhtce zuTc^6aPaCkA-C8NGPRAMj&dUIl%M!3>)$d^i3_L@2Z&=nwxB}Wg-W_psL)=sO$ekXlR95%&rx##ae7cMdUc@h{mx7U!bo4 zjXL`@Qhz(vVg(N2KAgY-f^x8@w`K{MEke^C($6E^m0kCAk;cgPV(>@$rJ1C_j#3e^CTJH~g& znHX#bRS#n>rzj_MzKL$vTCkm3Ol_p5Q<>Iz&y!Kfx>UB&*hwvM1~`8eJy=C&wp0|( zrJ}RedHJYHSS?s#R8gX;tfi9ZdYhfHncpU=cD=!f2f-X~oqTJE3?NujU$}xeeL?_RkL?n&ebJtlb z0eNMegtFLFQddH>JY_ukDS O8|@69kL9kOP52Lq8j+X) delta 2365 zcmZwITWnNC7{KwNr9fNCrA1mU(kURK(xpm^T$YwnickK5zSHYZg?=7*ci3OfFUR$MiYf-)CV>C06w6E=!22)VD$f;a{{PLnEqyF_slo* z&75U_*B`y*pXx_Ht0Wtij?$RJziR*&6q~X z#D^%~{}Cl%&G;a|Jd}W)DD%cp=1b!w+=cDLSC7+>1$>0EV8=l3*IFodiC18w(1lWm^n&)s9z8#LA zz$pE*cn{8J`LeS|uoYj#P52q!icM_uI!xi6_!Mr#Ur^4zuRd7dwtDivnt=iXva|P5 zSxhlB5-{}{^n36#t>u*+^--bnu2 zY3yd81K&eQ<(aVG!VM#)x&!45vnXf$aOle@cj6FAioeC{@j}?2%T1-J)}mxMj&ga+ z{E-a5APu=hhfo6ifD7?AB%7+4tIb+e8_H3w#T4dHGVu*A!Ae#oJBy+ON+L;6LnzNb zkFt?>P~v=oH)8oa8j`wNwjpP^1lur$^1uOE<4*rPwR)|2i5`2KJ+*@CzJ;E2!5{rAP*d>!(io%c=6r zEmS#oDKe?N1)3@wkqakx>hdBBy}Yy#-(QvNsE;Z;meNDz_s2gw*$qFAei%$vI1rW8$a9KgLQKpp+K}`fowlR5#J!{{5?T)9a$j`_0?w z-|{MyvW~jUZv~f5E~Ffxlz|xwu?AHCEoL9I-Vt|#uRp{`!51T{ z-!3GKU=>L6RWWc`%bjg7M| ztv;f9ZO1j)thtmb@2$qIa|ev=T%61`whq?V8k0n|t}&UcvAwFM1I^tfCw2TthWYga zto(mT8)_P^D6eJ$_Whvj`-=Hvv#!oru1=bq4rWgjk|sz*ifCyg%ZaDihL+h@85t$R z_7yYiN4of2mH(jEI%7{~xQ+h*rrPy$y+FseGx?yg@<#VxN_g6&$hgUm49_@S`46qt BcB%jX diff --git a/lang/python/de/LC_MESSAGES/python.po b/lang/python/de/LC_MESSAGES/python.po index e315fb242..43cb42650 100644 --- a/lang/python/de/LC_MESSAGES/python.po +++ b/lang/python/de/LC_MESSAGES/python.po @@ -13,7 +13,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Andreas Eitel , 2019\n" "Language-Team: German (https://www.transifex.com/calamares/teams/20061/de/)\n" @@ -37,8 +37,7 @@ msgstr "Partitionen mounten." #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -47,7 +46,7 @@ msgstr "Konfigurationsfehler" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" "Es sind keine Partitionen für
{!s}
zur Verwendung definiert." @@ -219,22 +218,6 @@ msgid "No root mount point is given for
{!s}
to use." msgstr "" "Es ist kein Root-Mount-Punkt für
{!s}
zur Verwendung angegeben." -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "Erstelle initramfs mit mkinitcpio." - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "Prozess fehlgeschlagen" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" -"Der Prozess
mkinitcpio
ist mit dem Fehlercode {!s} " -"fehlgeschlagen. Der Befehl war
{!s}
." - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "Konfiguriere verschlüsseltes swap." @@ -331,18 +314,6 @@ msgstr "Installiere Bootloader." msgid "Remove live user from target system" msgstr "Entferne Live-Benutzer aus dem Zielsystem" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "Erstelle initramfs." - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "Ausführen von update-initramfs auf dem Ziel schlug fehl" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "Der Exit-Code war {}" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "Einstellen der Hardware-Uhr." @@ -355,6 +326,10 @@ msgstr "Erstelle initramfs mit dracut." msgid "Failed to run dracut on the target" msgstr "Ausführen von dracut auf dem Ziel schlug fehl" +#: src/modules/dracut/main.py:59 +msgid "The exit code was {}" +msgstr "Der Exit-Code war {}" + #: src/modules/initramfscfg/main.py:41 msgid "Configuring initramfs." msgstr "initramfs konfigurieren." @@ -363,18 +338,6 @@ msgstr "initramfs konfigurieren." msgid "Configuring OpenRC dmcrypt service." msgstr "Konfiguration des OpenRC dmcrypt-Dienstes." -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "LUKS-Schlüsseldatei konfigurieren." - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "Verschlüsselter Rootfs-Setup-Fehler" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "Rootfs-Partition {!s} ist LUKS, aber keine Passphrase gefunden." - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "Schreibe fstab." diff --git a/lang/python/el/LC_MESSAGES/python.po b/lang/python/el/LC_MESSAGES/python.po index fb9bd2e00..c4af77ef6 100644 --- a/lang/python/el/LC_MESSAGES/python.po +++ b/lang/python/el/LC_MESSAGES/python.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Efstathios Iosifidis , 2017\n" "Language-Team: Greek (https://www.transifex.com/calamares/teams/20061/el/)\n" @@ -35,8 +35,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -45,7 +44,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -207,20 +206,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -311,18 +296,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -335,6 +308,10 @@ msgstr "" 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 "" @@ -343,18 +320,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/en_GB/LC_MESSAGES/python.po b/lang/python/en_GB/LC_MESSAGES/python.po index eb43ab0e1..5eef9a059 100644 --- a/lang/python/en_GB/LC_MESSAGES/python.po +++ b/lang/python/en_GB/LC_MESSAGES/python.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Jason Collins , 2018\n" "Language-Team: English (United Kingdom) (https://www.transifex.com/calamares/teams/20061/en_GB/)\n" @@ -35,8 +35,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -45,7 +44,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -207,20 +206,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -311,18 +296,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -335,6 +308,10 @@ msgstr "" 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 "" @@ -343,18 +320,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/eo/LC_MESSAGES/python.po b/lang/python/eo/LC_MESSAGES/python.po index d03d672fa..f6e2ef898 100644 --- a/lang/python/eo/LC_MESSAGES/python.po +++ b/lang/python/eo/LC_MESSAGES/python.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Kurt Ankh Phoenix , 2018\n" "Language-Team: Esperanto (https://www.transifex.com/calamares/teams/20061/eo/)\n" @@ -35,8 +35,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -45,7 +44,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -207,20 +206,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -311,18 +296,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -335,6 +308,10 @@ msgstr "" 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 "" @@ -343,18 +320,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/es/LC_MESSAGES/python.po b/lang/python/es/LC_MESSAGES/python.po index 271bdaeb5..583b3adf0 100644 --- a/lang/python/es/LC_MESSAGES/python.po +++ b/lang/python/es/LC_MESSAGES/python.po @@ -14,7 +14,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Fito JB, 2019\n" "Language-Team: Spanish (https://www.transifex.com/calamares/teams/20061/es/)\n" @@ -38,8 +38,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -48,7 +47,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -214,20 +213,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -318,18 +303,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -342,6 +315,10 @@ msgstr "" 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 "" @@ -350,18 +327,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/es_MX/LC_MESSAGES/python.po b/lang/python/es_MX/LC_MESSAGES/python.po index 34103cda5..bc02a0f42 100644 --- a/lang/python/es_MX/LC_MESSAGES/python.po +++ b/lang/python/es_MX/LC_MESSAGES/python.po @@ -12,7 +12,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Logan 8192 , 2018\n" "Language-Team: Spanish (Mexico) (https://www.transifex.com/calamares/teams/20061/es_MX/)\n" @@ -36,8 +36,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -46,7 +45,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -208,20 +207,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -312,18 +297,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -336,6 +309,10 @@ msgstr "" 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 "" @@ -344,18 +321,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/es_PR/LC_MESSAGES/python.po b/lang/python/es_PR/LC_MESSAGES/python.po index 644265373..54151ce05 100644 --- a/lang/python/es_PR/LC_MESSAGES/python.po +++ b/lang/python/es_PR/LC_MESSAGES/python.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Language-Team: Spanish (Puerto Rico) (https://www.transifex.com/calamares/teams/20061/es_PR/)\n" "MIME-Version: 1.0\n" @@ -31,8 +31,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -41,7 +40,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -203,20 +202,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -307,18 +292,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -331,6 +304,10 @@ msgstr "" 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 "" @@ -339,18 +316,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/et/LC_MESSAGES/python.mo b/lang/python/et/LC_MESSAGES/python.mo index ba6dcdd148deeb9c8338a98cb9f94aebd9852f5e..8f796c2df3fb38472079d1f8b1fa77e0dc891efe 100644 GIT binary patch delta 168 zcmdnXf0Td1n)(bz28K7x3=E143=E;H3=CR8x*SMr1L;LTS`SE{gYy3ZX)z#QlZ}Bv z97sC=X%QeD0i*?ibS{uK1k&|DS_MdN1k$QN`Wled0MdVev<{F~WoKZ}2hu_8418b( eO+Wz|pumdFmW(>g918v=sd=SExtmj2BA5Xnrxq>% delta 159 zcmX@gzn6c)n)(Dr28K7x3=E143=F=k3=CR8Iv+@D1L;{nS`SDcgYv%uX)z#Qk&S^t z97tOLX%QeD0Hg(hbSjWG1k&X|S_Me21k$QN`W%qf0McK8v<{G#WoKZ}2hv{b418b( VRX_n5pumF7mW(>gn{!zrm;pHl5|jV{ diff --git a/lang/python/et/LC_MESSAGES/python.po b/lang/python/et/LC_MESSAGES/python.po index e36f9c39d..03705c5fb 100644 --- a/lang/python/et/LC_MESSAGES/python.po +++ b/lang/python/et/LC_MESSAGES/python.po @@ -4,16 +4,16 @@ # FIRST AUTHOR , YEAR. # # Translators: -# Madis, 2019 +# Madis Otenurm, 2019 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" -"Last-Translator: Madis, 2019\n" +"Last-Translator: Madis Otenurm, 2019\n" "Language-Team: Estonian (https://www.transifex.com/calamares/teams/20061/et/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -35,8 +35,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -45,7 +44,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -207,20 +206,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -311,18 +296,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -335,6 +308,10 @@ msgstr "" 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 "" @@ -343,18 +320,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/eu/LC_MESSAGES/python.po b/lang/python/eu/LC_MESSAGES/python.po index c015db10b..5ced4ff83 100644 --- a/lang/python/eu/LC_MESSAGES/python.po +++ b/lang/python/eu/LC_MESSAGES/python.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Ander Elortondo, 2019\n" "Language-Team: Basque (https://www.transifex.com/calamares/teams/20061/eu/)\n" @@ -35,8 +35,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -45,7 +44,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -210,20 +209,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -314,18 +299,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -338,6 +311,10 @@ msgstr "" 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 "" @@ -346,18 +323,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/fa/LC_MESSAGES/python.po b/lang/python/fa/LC_MESSAGES/python.po index 2e3707b34..85cab6ca6 100644 --- a/lang/python/fa/LC_MESSAGES/python.po +++ b/lang/python/fa/LC_MESSAGES/python.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Language-Team: Persian (https://www.transifex.com/calamares/teams/20061/fa/)\n" "MIME-Version: 1.0\n" @@ -31,8 +31,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -41,7 +40,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -203,20 +202,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -307,18 +292,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -331,6 +304,10 @@ msgstr "" 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 "" @@ -339,18 +316,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/fi_FI/LC_MESSAGES/python.mo b/lang/python/fi_FI/LC_MESSAGES/python.mo index b46237dde675512ca782769121253c28727ed5ce..07df789023245ada0695fdb56bba9e1ed4179c27 100644 GIT binary patch delta 1617 zcmXxk+e;K-7{~FaUA0xy%tIbp%QQQim6nIy(o8Y4kPeh(fl*fxbyr<%ZRf5kXi}nX zvJ+7d)!u0mh6eos6%vI=6m=m*5ZFcZ{mqOozVmtCnc4U7ypMCOX)F@|oSoETloo23 z+8i)DfJc(JP<|$xZN^`|(G;^%`j@c?A7d4cU;$2IHD*uuY(+hfVI@ApJRHMXv$*}C zQO1qRkl6yi+v!)Lc6tsq-~-eEL#P2qQ45fg_NT<)P~y7QPl5x zu^69Vg!%0)jro{7!)y&MLPBHvaT)fa27HYg@GEM7^bBu7OK>jz4XFFw7{$}L4+l^a z7i5}MUJ0hsbIU5OwNy^RR=an+kf!-E>_1cI>wMczkAkv2CR;%%vBB$Y2$0^ zh7H_2;4ADFC7X_|+3UL3gCf+Xo)&aFOA9X~#tUl$&XsVN O`$k{UvP66FaPU9f-<8h* delta 2317 zcmZwHZ%kEX9Ki7>gcK1nL=Xje{1<_6F+)Hg75^oHt3+6-Y#q1Y^xX5W?N;gt){tNP`zlY_5Gc5MOQuB?|h!;+;g5k zzvnskO52Ie>2Hg3PbQ`QLmBW4 z%0$j*{S2kQtGEP<<|?+TRunsGjM;tIxBd#K3DpF~;tYbY;X!b-e?ZTL4X z!`4Ej*5N)Rh3XXU#YV(A}jt2=}Q$dY6n)M3}B(0g<~jt{xQm#D6fe2b_Av4V<-!`fQ|Sw z%0QJIC^>{(ScMKsCQcx`m{#YgG;m`IM{pY1Hg$lfWRIT0jrb<+z-uTOXr#BjIE-=p z5aszA9lgIB@eg=pxz)Da<@v zg$%$SqUt7Q6MUiJYS&{mA>|$-k08NeA%WpP>Ly&k_+h$WrpSSkBD0pv$U(ccY^Na^ zkZsB#3W!`nvLjp3MBFG_smMXzNN7UJYC^WQlSoUd`GX6~Hmd^D|L7&1BNBdBX6bF65`^<(PWNbp}n()7!&dGN`Ggn4wpL+_}X@K%J96@uxogx9&!RZ9#cKtotf@}<&y=46LVI{qxHs! zVcEWA#vRY6o8;8^)VOQ;{?vHVvQ0add2ivnEuAxYN(4@LU*BA!t&Nc&kuYMaJ8, 2019\n" "Language-Team: Finnish (Finland) (https://www.transifex.com/calamares/teams/20061/fi_FI/)\n" @@ -35,8 +35,7 @@ msgstr "Yhdistä osiot." #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -45,7 +44,7 @@ msgstr "Määritysvirhe" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "Ei ole määritetty käyttämään osioita
{!s}
." @@ -214,22 +213,6 @@ msgid "No root mount point is given for
{!s}
to use." msgstr "" "Root-juuri kiinnityspistettä
{!s}
ei ole annettu käytettäväksi." -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "Initramfs luominen mkinitcpion avulla." - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "Prosessi epäonnistui" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" -"Prosessi
mkinitcpio
epäonnistui virhekoodilla {!s}. Komento oli " -"
{!s}
." - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "Salatun swapin määrittäminen." @@ -324,18 +307,6 @@ msgstr "Asenna bootloader." msgid "Remove live user from target system" msgstr "Poista Live-käyttäjä kohdejärjestelmästä" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "Luodaan initramfs." - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "Kohteen update-initramfs suorittaminen epäonnistui" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "Poistumiskoodi oli {}" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "Laitteiston kellon asettaminen." @@ -348,6 +319,10 @@ msgstr "Initramfs luominen dracut:lla." msgid "Failed to run dracut on the target" msgstr "Dracut-ohjelman suorittaminen ei onnistunut" +#: src/modules/dracut/main.py:59 +msgid "The exit code was {}" +msgstr "Poistumiskoodi oli {}" + #: src/modules/initramfscfg/main.py:41 msgid "Configuring initramfs." msgstr "Määritetään initramfs." @@ -356,18 +331,6 @@ msgstr "Määritetään initramfs." msgid "Configuring OpenRC dmcrypt service." msgstr "OpenRC dmcrypt-palvelun määrittäminen." -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "LUKS-avaintiedoston määrittäminen." - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "Salattu rootfs asennusvirhe" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "Rootfs-osio {!s} on LUKS, mutta salasanaa ei löydy." - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "Fstab kirjoittaminen." diff --git a/lang/python/fr/LC_MESSAGES/python.mo b/lang/python/fr/LC_MESSAGES/python.mo index 9919ffc5343189787162aae63888c2a3c661969c..9595cd8011a721907e3d6492291a30e5434e18e9 100644 GIT binary patch delta 1627 zcmXxkUuex?9LMqR&dxSxV}F_bbDaG#!~7W=b9S&{hSD-)(k?dAE{Nh{89Ky;#A^Lw zOLDPY;KGzcYNnPYwIUa8P_i`C6iP}`-k;z3?Wt$4=lSjYor#W>*g$1sQf6lUNb%*Q|=K4B?pAraI#ZCHq>F&F!BE)L^-9LI(D z9xIvO{?f?eK}Bl(hhc1?-;CPnAZozpr~xKX1O7oREIlp$ehFsMuSP|n5w)Nm)W&Y1 zHa3oWe;OAszu9cFItXGh9>5wrgM`Q);4+*>4LE;}*($6<4SW|CM_c4esyyu@W zLf@Zm){YIR1>C~uavCuj%{Ym>u!=Y@!6@#>yV!v~wx_c@g#6S_;a0qa+Q3T;VSsR6 zNHAN9dVe^ZyuuX1RfX-SBk0W`{`EA5c@VHa zip*g_R;7W~q9)vrt8fH&;54>j4YRDktDd7+tN-I_jFz#jMKszx&!R#!gbL9!+=3tR zD3ySHR`Om%PTB4txf8Wf8X71eM8aSM6VOLh za;a>huB9@ETeKiW!yoV325h2+sOzaDyt@g8wiK$8b*8MNQBPI$G{0MPrYZ{6OwqZ` zl$A6Tc0LuhnHr($d{r9bxKSk0b(`Iy@M>cmwfhCsL-N=7Y`8_yXz=ED&sgW8Yp0A> zDWUSQa|<`n_+GfTfLrEXBOL=@UH2ORZvG^xK~e7L7`Cb7m2ym^D$2?^B`)a{&usF= zJr}O5d-W{#D0yF^Q=U5D{7!9ky3)?Y=FTqlIfLmvu{{~x0q0lVW9M7`ap!zNZ>+KK Tx6gSR9B?8~D5=b}rw{ zoc`Wj@clY$=6OHP#Iv|UsX=v~!h9ZF$2+mEOsPifM7dAlbUcRDcm`+VTPPiVfijTG zk^iBzH>aGoumfk|E}Vf+VGTZqbLn5bMnOI}kJ8aExETM%sW^X1_~BBN2yMb`*ozX0 z4^Zm=h|*zsMcBbYlny&k+U-GUuNQB_0c@pzb%cTp;A4~-UqXq%> zJNH-caa_dkWoFM}6TXUD@pF6-YnkRNi}4gEE}O6xvYMGKJFMNtBs?iPF$zl#WZ8b_=F(Bc8%X@Dir6jqu2B zAHo=Z6nPa_a9>Bb9>eXpMEXBRL1y-I9ataSbFXFg`%>SBT7xR0e7Lw(t zRFa#?MdVKMN^%o<%5Y`r&f=>0j?F!KpBd0er_aO+JImgv>2i(bIhkJVWE{`6(#gC& z;CQLR*JX1HH_CR_cV}#OAm^EccC%TJw|V3FIc;1w>lU_@ADZF%8SUp1mS>vAnizh! zyuE0aZqK=!!VJLMQR_&!$ncGkttE_Y;zkkB@-`x?h4rLFzO z*5lKODSN!8KOVorshZq^Zr3%ws}sJa`DD^HX_N8fHVj`F%fjT^ml{WFHk$sCA=@AA z_?D19UpujQUfk$h7!*H>*Z6p%@UGGG+k^1NnPeDUqeq53%kgfF@W=~xib*l9v1SWL z>rU;mh~a32UCVYdCJeO6GYO-;ft(2=p0, 2019\n" "Language-Team: French (https://www.transifex.com/calamares/teams/20061/fr/)\n" @@ -43,8 +43,7 @@ msgstr "Montage des partitions." #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -53,7 +52,7 @@ msgstr "Erreur de configuration" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" "Aucune partition n'est définie pour être utilisée par
{!s}
." @@ -228,22 +227,6 @@ msgstr "" "Aucun point de montage racine n'a été donné pour être utilisé par " "
{!s}
." -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "Création de l'initramfs avec mkinitcpio." - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "Échec du processus" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" -"Le processus
mkinitcpio
a échoué avec le code d'erreur {!s}. La " -"commande était
{!s}
." - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "Configuration du swap chiffrée." @@ -342,18 +325,6 @@ msgstr "Installation du bootloader." msgid "Remove live user from target system" msgstr "Supprimer l'utilisateur live du système cible" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "création du initramfs" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "Erreur d'exécution de update-initramfs sur la cible." - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "Le code de sortie était {}" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "Configuration de l'horloge matériel." @@ -366,6 +337,10 @@ msgstr "Configuration du initramfs avec dracut." msgid "Failed to run dracut on the target" msgstr "Erreur d'exécution de dracut sur la cible." +#: src/modules/dracut/main.py:59 +msgid "The exit code was {}" +msgstr "Le code de sortie était {}" + #: src/modules/initramfscfg/main.py:41 msgid "Configuring initramfs." msgstr "Configuration du initramfs." @@ -374,20 +349,6 @@ msgstr "Configuration du initramfs." msgid "Configuring OpenRC dmcrypt service." msgstr "Configuration du service OpenRC dmcrypt." -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "Configuration de la clé de fichier LUKS." - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "Erreur du chiffrement du setup rootfs" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" -"La partition racine {!s} est de type LUKS mais aucune phrase de passe n'a " -"été trouvée." - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "Écriture du fstab." diff --git a/lang/python/fr_CH/LC_MESSAGES/python.po b/lang/python/fr_CH/LC_MESSAGES/python.po index 47ed6f847..fbda54e3c 100644 --- a/lang/python/fr_CH/LC_MESSAGES/python.po +++ b/lang/python/fr_CH/LC_MESSAGES/python.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Language-Team: French (Switzerland) (https://www.transifex.com/calamares/teams/20061/fr_CH/)\n" "MIME-Version: 1.0\n" @@ -31,8 +31,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -41,7 +40,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -203,20 +202,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -307,18 +292,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -331,6 +304,10 @@ msgstr "" 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 "" @@ -339,18 +316,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/gl/LC_MESSAGES/python.po b/lang/python/gl/LC_MESSAGES/python.po index 817d036e4..089d3dd63 100644 --- a/lang/python/gl/LC_MESSAGES/python.po +++ b/lang/python/gl/LC_MESSAGES/python.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Xosé, 2018\n" "Language-Team: Galician (https://www.transifex.com/calamares/teams/20061/gl/)\n" @@ -35,8 +35,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -45,7 +44,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -210,20 +209,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -314,18 +299,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -338,6 +311,10 @@ msgstr "" 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 "" @@ -346,18 +323,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/gu/LC_MESSAGES/python.po b/lang/python/gu/LC_MESSAGES/python.po index d591c8d01..84a31ec50 100644 --- a/lang/python/gu/LC_MESSAGES/python.po +++ b/lang/python/gu/LC_MESSAGES/python.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Language-Team: Gujarati (https://www.transifex.com/calamares/teams/20061/gu/)\n" "MIME-Version: 1.0\n" @@ -31,8 +31,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -41,7 +40,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -203,20 +202,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -307,18 +292,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -331,6 +304,10 @@ msgstr "" 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 "" @@ -339,18 +316,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/he/LC_MESSAGES/python.mo b/lang/python/he/LC_MESSAGES/python.mo index 6028c79209721d82fbd9774c2934b612bd38981d..423f053a942a181cf1c6eb9b8d2b3f89c1b01e42 100644 GIT binary patch delta 1636 zcmXxkOGs346vy%7IB7GJqv<$SrcPrI^U*`cUZa+k2|?LIEP7E$2oePqL1s)*REsj| z7P$x`TZ9`G2in*okO;yas|bq7g|&!UMHFuO{;uPJGoSx|=Fb0h&%JMUjy5O0cGAz}n2zIVtjCY21%^YMzb2? z)WGj>6J~J?YjG#)M6U6{+N=*X@eo$x+XBvC#W2Me+Hv7L>HwQiJ3WaiuB*t{_6T+T zGpxoBr~!Rcq@JEKJd91Kah{-V-8gFezgUA&2Guxi2^x%H=THOP#vUBRby!d3t=I3U zoerZW`iUCIPiHeW;3~X~jW~k4@i*$aZ4}4~?7|l~fNL<($*d}>$Ef0aiMsGRF2OL% z+=X>`8E+x~wd@GH#40?2XHd85D{jOXgWbckcm;htN*ebTQcm_9kLdXyr_s(A6|6!> zbsN*rL#ntG8c?g%#ELCsE$LNc1 zBW{)FA&;yzkZw3rp_1gsjGA<3slV6x<8O630+*7ZIi((_KiHMrn?3Az$`_0}MTMuF avBK-giwnEclUE|qH0M`Qelj;2pYfA(CMb$SM7COmxw5I*TD3L(qqUx`Rez}el*_f&bZxcz{+{P%G}e)GKj%EpdCtr4 zoagbQ4Oi>JKV&8LC{jH+j~tCxY6nhE;)nD>vQjnpVa&uyN)=GA$C+s0Qap$`cm+%F z+n7^Q?E96tnCrXoejLH&N`=)W3WZ#_i*s>Ss!|VN1xmdgr{O`If`gcg@1hL&CCWr@ z#{3JVznN+Dh2@xy&){@?0cYT==wN&`KtUe3gfh@|T!?pYDi)^O50;`ts0KG<8%iWD zptS!UWx%w__5ejF1D2!o>q6__SUb1cSNxD4|MXIKVwQIG+4qlD%N&cU~1*RNt3 z^;`HH&S(0vvi-OS`>-Crz{fF%WiG&0d%QjFQZKGPm}@j*kFlRCvL&xD3SOTU0BDek+Njg4{75E!If~A}^+Nus@acV!xz(;T)zK;&Pjzt*HNtBf@!1?GxS@9m^Pj&Od zoYY$=&wU!EAbWEY<&dPzQtDyMLm8+Z<3220iQy&+%PIVfk4gjXmf=?9S#=zxqYJneZ(}hoq1QFI4WGav4B{P> z6>rz}b9>QA{TzObH?R?h@~s7h)gKfj0!w+9D5^%32fA<`j^HM|hWpS#W9F&`u?jEa zPE6t?yU@VZ_!&kqnND88ew2P4>=Wl$)nSvo|4kH{xo{CBg!!DLI9x@R2}q(ZD~!{u zntfO$N*lUSy_zLBG#<%u`18#k0IR;i*$1mR>>+s2b@^Q3M zV$4jGgS4K^j#v{1>yXNJNs&VGuw%ht# zvMbiR&Bx994_4JH&hQ}T9`r5SD z=M5R|j@F>w;*8A9xmbFV>aaO7E;i;V^SJ(ZNls->XcPH5$0$8ZH%HAw<|v&r#u=JX958#i zIxNMrbUk98m1{D_kTi%?=DwB_<+8Mx5YzW^dlMX^ba#wC`u-=l(Zadwtl-jah+%tJ zOjPD@lz%)tG04{Z{^^ui^fR?%V^y<@;u^Q8KT>cKFjUX%#Q0P gxid_ip$8cFn5=l1mP6(Vr;5Cjojta9&dQ{}0ai!LH2?qr diff --git a/lang/python/he/LC_MESSAGES/python.po b/lang/python/he/LC_MESSAGES/python.po index 61b5fdf83..d5b473aa4 100644 --- a/lang/python/he/LC_MESSAGES/python.po +++ b/lang/python/he/LC_MESSAGES/python.po @@ -12,7 +12,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Yaron Shahrabani , 2019\n" "Language-Team: Hebrew (https://www.transifex.com/calamares/teams/20061/he/)\n" @@ -36,8 +36,7 @@ msgstr "מחיצות מעוגנות." #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -46,7 +45,7 @@ msgstr "שגיאת הגדרות" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "לא הוגדרו מחיצות לשימוש של
{!s}
." @@ -213,22 +212,6 @@ msgstr "mkinitcpio מותקן." msgid "No root mount point is given for
{!s}
to use." msgstr "לא סופקה נקודת עגינת שורש לשימוש של
{!s}
." -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "נוצר initramfs עם mkinitcpio." - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "התהליך נכשל" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" -"התהליך
mkinitcpio
נכשל עם קוד השגיאה {!s}. הפקודה הייתה " -"
{!s}
." - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "מוגדר שטח החלפה מוצפן." @@ -328,18 +311,6 @@ msgstr "התקנת מנהל אתחול." msgid "Remove live user from target system" msgstr "הסרת משתמש חי ממערכת היעד" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "נוצר initramfs." - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "הרצת update-initramfs על היעד נכשלה" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "קוד היציאה היה {}" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "שעון החומרה מוגדר." @@ -352,6 +323,10 @@ msgstr "נוצר initramfs עם dracut." msgid "Failed to run dracut on the target" msgstr "הרצת dracut על היעד נכשלה" +#: src/modules/dracut/main.py:59 +msgid "The exit code was {}" +msgstr "קוד היציאה היה {}" + #: src/modules/initramfscfg/main.py:41 msgid "Configuring initramfs." msgstr "initramfs מוגדר." @@ -360,18 +335,6 @@ msgstr "initramfs מוגדר." msgid "Configuring OpenRC dmcrypt service." msgstr "שירות dmcrypt ל־OpenRC מוגדר." -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "קובץ מפתח ה־LUKS מוגדר." - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "שגיאת התקנת מחיצת שורש מוצפנת" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "מחיצת השורש {!s} היא מסוג LUKS אך לא נמצאה מילת צופן." - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "fstab נכתב." diff --git a/lang/python/hi/LC_MESSAGES/python.mo b/lang/python/hi/LC_MESSAGES/python.mo index 91f4c093205c87e6829d6a196d6bfe606b6d349b..3d3912fe542f18121f765a38567bc04107d61c8d 100644 GIT binary patch literal 11347 zcmcJUeT*Ds9mfZ#yc~#t@+OE61@sEtyK5;>t}Q}eDYUe<V~nInEMraf+j$v_An3f`0%{2c6>`XDM(7cmcQxybz4RFM^My*S`Wk z&GmcWr@#-uv%wQiu=8C2iXO{Bk#jS64mb&(0qzAq1HJ^F3BCz_9{ek~5d0r_D%js= z`wfFzxZVVcolk)x?{}b#e-{*aAAq9Q$tT+J^TAWNUIL2!Ye3QGPEhRH2Z~*9f-?Sn z@N=MZlH)7`&I8W}Zv`&{?*hd?2f$0f_d$_&<|iFz2wVn=+%hO~z5|MWFN5cSZ>9JD z4ld_<-pP)08+Z*U^X~%-;7`F#;Je^Pa1l;k0Dc|31^fwkJ9sq4N!*GcU7ZPVHTWPX z`o9Aj@C2NB=TVMxF}R)U#%Y#M$K$M(l%gI9xp2CoNC zheRdN1&6`kgV%ybonx=B1D9}pA1L$w927ZcoNMRX4DRFlMQ|OsfuL*vzXuM2?}9S_ zsRU;^_+{`i@Y~>G@VDS|;D5nQ;8T!vGx#5HE4a$oetSXD^KI}|a1hdrg8u;T1vf$3 z{otR#?O+Yk_~2ha@$bqDt=zXjk#p8XR;{Ml`Wr}505e)Y zi5s+XPT*L{A#syjl;0W)4(@WGxTLZEB$mP-=%;m0ZbE6NPfqwwF?T$AwxO#Gl!ZusO$Y;BKvlr>70j zRO=>bsP*rv^uDva7?!-NqGF*|ExCzjCf#WC{CM~BLA`H^Znm10u~1f6#+p|$34ZbtW8IfYPrWvf4f2BAm`s_T2F+=riW~1}sa6a8 z*%YgUC4Xch^G>F2dx__)u2m`% zraF;~g@L&v+|KaMJEVBkOzw8pxA=B)DO0~!{6JgDaxeyCC8k?{q zaUluAa%`$@aR=Hkb(~OYyi$iq@-$W6po9#zxzN$27Ki}jS477A$=&mvwSKuQPN-Ft zeKt~fZJif*lm`#JierA@75vhGv);~Xwo}{6pPFoly-KgVrEjRQ7QCdBelxg<;RKBksXKWl*^9p{WePd6s21=6D@8Cv%+RZ zBacW&ZP#lnb*_^oG5jri#e^VB4VECJJu(_mN@`_K$Ieo*nY*ouabZTugEpz?<<-c$ zN}RHMP|k!?wb;tl%HJv6kIksR(+gCmZUZ+*VbP0Y>j7n1Z2B+iFN#};%%HibKM5h- zg3-WRgvzXu(UO;zUdtidN2KLqt|R5{^oVzqr|wbO>h6@$ftQSj(T;pl4mexA zL_;{{Mx}A_SdlWYW5C&FS06IOE@V@9ls0FDd}^x%(TfqR%cbTGEa=FvbSW|TSr<}b z9zlXInsByFV?b=ma98?zm1;6!ph+#rB8%AVVKO#a4!67I7zvW7E~O&Rq5&yJn1ygM zA;Ar7ETkk+W8|hRBsL5ha>;blKe>BBreR#GR>KIEYVWE`+0!jU=AYI=F9Xu$S9&Sk zbf>e>jF0(6s%0)Ctx7F_ibN_`gBMn?Qy9c?nT?l&@*44}D9RWUFn z5{2hxwg^J>5$ZgvNuCfb+o3_?!Wq}hm!#Jcwpn(7^UV%#VjMKR7FHk+?mb^SH#)|i{tY}vYg(+z!F zJYij7V?64Y3M*@)aba6HZ2C5DDs1s~`ZA`lnl)$GEFM~PMPX=ZVdzS;XlVG-C6^5G z>)YVQNnu;$265RXHIVNHWci|@rNr5dtG*jt!RExhdbEO`v6*q2MTUgreCsU1hQDF`H zhZ2DqHcPkrNlVFLGv@bgF0(r?7uJSRB_1|GRWIWei}xuUxIu^S)#le6o$lEJ4%2qjJJ5a>QWdP< zGXZpXqx}eF9ZI(+tY4e;Ur0N4sabm@Vrr+{drf*{8a_{-sJJNs0jyhEI-@L+tJ9DZ z#Bj71n`ps%ZK-uG92>F{ZJ3D*aU^Eqt|zl%nLheukF>4nnFYbG>a1v_tkJ1@(?CpX zD`7pZ4x8~Y580{p>Y0ye)?Q8jIOl%3*?^hWnX~%blG{f5(cb->BV?y1(covw#%DCB zy^`o-N{H7p5~gg;@i<3aO$d1;n3e@ln9ObLQ!+ziscE)2D5s|-M`I5ia%3?<~GpGSbTb#ddeG%P7}~!wqo73K`Nn6Y)g7)O=S_IzCNjic|Ss}7Y{ZY z53<1ZJW2ZvM~~_m^s`epG{0=sLQzSg-VANOdg*zneIsLsJpfRR$@&J*VCkD5?!AyQ ztHm!iFk0HI`qrPaeACxnz(od82q}S5T3Lfw-dd}xtt<8Wq+JTO)D(J&9~_mB>J)X>V9O}MTvbR<`^#S$gVU$J=lUQ?@v9t2)gQ038+a>D(f-!_4}K3%-?ULgRyou4JRy*gb-8n{RO3y z>{Own?6Z;2#mtVIIv94%!QE3wF$E@Kk1%*{6H$pJDds#MUb7_6)>fj-@-7of@TJsc zZ+v=_`Un!zY4ecClZ<{E$?zUodo071rTR`WOA;GJF$_}V zxi)u!b6@=DEHl#&ZlakaIkrrF5Sq#Ysn^i8^+Hn#2xs@&!iNOQ`>b#&$GJN*VWxS` zu4WVu+(jdVkP-s*IGb}3Cauwke4-B7jk07Vfk6rT@F%rK&FEQnPGg*fURrFlET<2^ zOmf)7L7v%EoWXhC@iA zj|l2Y>YEi$B{`^a@Rux@k2M?A@jWU<#dAjFNrv`#;x;wNw!Py;&RiCSE_9J;F<)X& z;hJS(=^~?D9-l;tm4w)P>}Q6obf(*HHL;`o;T-XXy2Tob5H7_lxm45YGyThgk`oK= znd$pNhb}$WS|U!MAGey=`egN!%9IkGt##Mpm2p4YQDM{FmO(8S>^JhYqy1?kzf3gt z35lc_ciGlKJ?fXG7T$%KGZsxJV^jxY+FwWVbBZ~Q>@8aUa|v3DNwVRVw}5Iy{SYuK zZ|t&aGf26XeL1iqF)&>hkJRMprWy^%as0&!g{Nlq@2rM7*0Tl4i!_mXd#j2=+tx!S z9E*lF?h?zk&zOVC03B?&U(RBb`z&M~oqs#m&DYarYroKBBD*fa|NYrS(?1f)Qqtuk zkt#9=|B6AZMa(0c4Y5`!k-pc>ilBZ#qCrv(AQx>~$QX3(D3|$fOiE2#i1Oc!=IcO7 zM`lhd@U&VZL?_|t^h3^a%}h$Nbu4;XgjoJ%txWTrF^At=q@?_iIrZVRi}VxNVJp() WZfmzh!tP2MoE=n)pI4&So&N)sUOmMC delta 336 zcmX}mJ4?f06o>IsZ8Y`*jkF@t)S(463RO_5lNVeZgyQ5Nc&np>gCH(m!9`H~-NsW1dE}h*)6W(2BsXdQ{2V{{6y|B zm)aK05rs#b*$?c_J1GDF diff --git a/lang/python/hi/LC_MESSAGES/python.po b/lang/python/hi/LC_MESSAGES/python.po index c826795f3..55e9bebe8 100644 --- a/lang/python/hi/LC_MESSAGES/python.po +++ b/lang/python/hi/LC_MESSAGES/python.po @@ -4,16 +4,16 @@ # FIRST AUTHOR , YEAR. # # Translators: -# Panwar108 , 2018 +# Panwar108 , 2019 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" -"Last-Translator: Panwar108 , 2018\n" +"Last-Translator: Panwar108 , 2019\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" @@ -23,11 +23,11 @@ msgstr "" #: src/modules/grubcfg/main.py:37 msgid "Configure GRUB." -msgstr "" +msgstr "GRUB विन्यस्त करना।" #: src/modules/mount/main.py:38 msgid "Mounting partitions." -msgstr "" +msgstr "विभाजन माउंट करना।" #: src/modules/mount/main.py:150 src/modules/initcpiocfg/main.py:187 #: src/modules/initcpiocfg/main.py:191 @@ -35,169 +35,173 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" -msgstr "" +msgstr "विन्यास त्रुटि" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." -msgstr "" +msgstr "
{!s}
के उपयोग हेतु कोई विभाजन परिभाषित नहीं हैं।" #: src/modules/services-systemd/main.py:35 msgid "Configure systemd services" -msgstr "" +msgstr "systemd सेवाएँ विन्यस्त करना" #: src/modules/services-systemd/main.py:68 #: src/modules/services-openrc/main.py:102 msgid "Cannot modify service" -msgstr "" +msgstr "सेवा को संशोधित नहीं किया जा सकता" #: src/modules/services-systemd/main.py:69 msgid "" "systemctl {arg!s} call in chroot returned error code {num!s}." -msgstr "" +msgstr "chroot में systemctl {arg!s} कॉल त्रुटि कोड {num!s}।" #: src/modules/services-systemd/main.py:72 #: src/modules/services-systemd/main.py:76 msgid "Cannot enable systemd service {name!s}." -msgstr "" +msgstr "systemd सेवा {name!s} को सक्रिय नहीं किया जा सकता।" #: src/modules/services-systemd/main.py:74 msgid "Cannot enable systemd target {name!s}." -msgstr "" +msgstr "systemd टारगेट {name!s} को सक्रिय नहीं किया जा सकता।" #: src/modules/services-systemd/main.py:78 msgid "Cannot disable systemd target {name!s}." -msgstr "" +msgstr "systemd टारगेट {name!s} को निष्क्रिय नहीं किया जा सकता।" #: src/modules/services-systemd/main.py:80 msgid "Cannot mask systemd unit {name!s}." -msgstr "" +msgstr "systemd यूनिट {name!s} को मास्क नहीं किया जा सकता।" #: src/modules/services-systemd/main.py:82 msgid "" "Unknown systemd commands {command!s} and " "{suffix!s} for unit {name!s}." msgstr "" +"यूनिट {name!s} हेतु अज्ञात systemd कमांड {command!s} व " +"{suffix!s}।" #: src/modules/umount/main.py:40 msgid "Unmount file systems." -msgstr "फ़ाइल सिस्टम माउंट से हटाएँ।" +msgstr "फ़ाइल सिस्टम माउंट से हटाना।" #: src/modules/unpackfs/main.py:41 msgid "Filling up filesystems." -msgstr "" +msgstr "फाइल सिस्टम भरना।" #: src/modules/unpackfs/main.py:159 msgid "rsync failed with error code {}." -msgstr "" +msgstr "rsync त्रुटि कोड {} के साथ विफल।" #: src/modules/unpackfs/main.py:220 src/modules/unpackfs/main.py:238 msgid "Failed to unpack image \"{}\"" -msgstr "" +msgstr "इमेज फ़ाइल \"{}\" को खोलने में विफल" #: src/modules/unpackfs/main.py:221 msgid "" "Failed to find unsquashfs, make sure you have the squashfs-tools package " "installed" msgstr "" +"unsqaushfs खोजने में विफल, सुनिश्चित करें कि squashfs-tools पैकेज इंस्टॉल है" #: src/modules/unpackfs/main.py:320 msgid "No mount point for root partition" -msgstr "" +msgstr "रुट विभाजन हेतु कोई माउंट पॉइंट नहीं है" #: src/modules/unpackfs/main.py:321 msgid "globalstorage does not contain a \"rootMountPoint\" key, doing nothing" -msgstr "" +msgstr "globalstorage में \"rootMountPoint\" कुंजी नहीं है, कुछ नहीं किया जाएगा" #: src/modules/unpackfs/main.py:326 msgid "Bad mount point for root partition" -msgstr "" +msgstr "रुट विभाजन हेतु ख़राब माउंट पॉइंट" #: src/modules/unpackfs/main.py:327 msgid "rootMountPoint is \"{}\", which does not exist, doing nothing" -msgstr "" +msgstr "रुट माउंट पॉइंट \"{}\" है, जो कि मौजूद नहीं है, कुछ नहीं किया जाएगा" #: src/modules/unpackfs/main.py:340 src/modules/unpackfs/main.py:347 #: src/modules/unpackfs/main.py:352 msgid "Bad unsquash configuration" -msgstr "" +msgstr "ख़राब unsquash विन्यास सेटिंग्स" #: src/modules/unpackfs/main.py:341 msgid "The filesystem for \"{}\" ({}) is not supported" -msgstr "" +msgstr "\"{}\" ({}) हेतु फ़ाइल सिस्टम समर्थित नहीं है" #: src/modules/unpackfs/main.py:348 msgid "The source filesystem \"{}\" does not exist" -msgstr "" +msgstr "\"{}\" स्रोत फ़ाइल सिस्टम मौजूद नहीं है" #: src/modules/unpackfs/main.py:353 msgid "The destination \"{}\" in the target system is not a directory" -msgstr "" +msgstr "लक्षित सिस्टम में \"{}\" स्थान कोई डायरेक्टरी नहीं है" #: src/modules/displaymanager/main.py:381 msgid "Cannot write KDM configuration file" -msgstr "" +msgstr "KDM विन्यास फ़ाइल राइट नहीं की जा सकती" #: src/modules/displaymanager/main.py:382 msgid "KDM config file {!s} does not exist" -msgstr "" +msgstr "KDM विन्यास फ़ाइल {!s} मौजूद नहीं है" #: src/modules/displaymanager/main.py:443 msgid "Cannot write LXDM configuration file" -msgstr "" +msgstr "LXDM विन्यास फ़ाइल राइट नहीं की जा सकती" #: src/modules/displaymanager/main.py:444 msgid "LXDM config file {!s} does not exist" -msgstr "" +msgstr "LXDM विन्यास फ़ाइल {!s} मौजूद नहीं है" #: src/modules/displaymanager/main.py:527 msgid "Cannot write LightDM configuration file" -msgstr "" +msgstr "LightDM विन्यास फ़ाइल राइट नहीं की जा सकती" #: src/modules/displaymanager/main.py:528 msgid "LightDM config file {!s} does not exist" -msgstr "" +msgstr "LightDM विन्यास फ़ाइल {!s} मौजूद नहीं है" #: src/modules/displaymanager/main.py:602 msgid "Cannot configure LightDM" -msgstr "" +msgstr "LightDM को विन्यस्त नहीं किया जा सकता" #: src/modules/displaymanager/main.py:603 msgid "No LightDM greeter installed." -msgstr "" +msgstr "कोई LightDM लॉगिन स्क्रीन इंस्टॉल नहीं है।" #: src/modules/displaymanager/main.py:634 msgid "Cannot write SLIM configuration file" -msgstr "" +msgstr "SLIM विन्यास फ़ाइल राइट नहीं की जा सकती" #: src/modules/displaymanager/main.py:635 msgid "SLIM config file {!s} does not exist" -msgstr "" +msgstr "SLIM विन्यास फ़ाइल {!s} मौजूद नहीं है" #: src/modules/displaymanager/main.py:750 msgid "No display managers selected for the displaymanager module." -msgstr "" +msgstr "चयनित डिस्प्ले प्रबंधक मॉड्यूल हेतु कोई डिस्प्ले प्रबंधक नहीं मिला।" #: src/modules/displaymanager/main.py:751 msgid "" "The displaymanagers list is empty or undefined in bothglobalstorage and " "displaymanager.conf." msgstr "" +"bothglobalstorage एवं displaymanager.conf में डिस्प्ले प्रबंधक सूची रिक्त या" +" अपरिभाषित है।" #: src/modules/displaymanager/main.py:831 msgid "Display manager configuration was incomplete" -msgstr "" +msgstr "डिस्प्ले प्रबंधक विन्यास अधूरा था" #: src/modules/initcpiocfg/main.py:36 msgid "Configuring mkinitcpio." -msgstr "" +msgstr "mkinitcpio को विन्यस्त करना।" #: src/modules/initcpiocfg/main.py:192 #: src/modules/luksopenswaphookcfg/main.py:100 @@ -206,79 +210,69 @@ msgstr "" #: 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/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" +"
{!s}
के उपयोग हेतु कोई रुट माउंट पॉइंट प्रदान नहीं किया गया।" #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." -msgstr "" +msgstr "एन्क्रिप्टेड स्वैप को विन्यस्त करना।" #: src/modules/rawfs/main.py:35 msgid "Installing data." -msgstr "" +msgstr "डाटा इंस्टॉल करना।" #: src/modules/services-openrc/main.py:38 msgid "Configure OpenRC services" -msgstr "" +msgstr "OpenRC सेवाएँ विन्यस्त करना" #: src/modules/services-openrc/main.py:66 msgid "Cannot add service {name!s} to run-level {level!s}." -msgstr "" +msgstr "रन-लेवल {level!s} में सेवा {name!s} को जोड़ा नहीं जा सका।" #: src/modules/services-openrc/main.py:68 msgid "Cannot remove service {name!s} from run-level {level!s}." -msgstr "" +msgstr "रन-लेवल {level!s} में सेवा {name!s} को हटाया नहीं जा सका।" #: src/modules/services-openrc/main.py:70 msgid "" "Unknown service-action {arg!s} for service {name!s} in run-" "level {level!s}." msgstr "" +"रन-लेवल {level!s} में सेवा {name!s} हेतु अज्ञात सेवा-कार्य " +"{arg!s}।" #: src/modules/services-openrc/main.py:103 msgid "" "rc-update {arg!s} call in chroot returned error code {num!s}." -msgstr "" +msgstr "chroot में rc-update {arg!s} कॉल त्रुटि कोड {num!s}।" #: src/modules/services-openrc/main.py:110 msgid "Target runlevel does not exist" -msgstr "" +msgstr "लक्षित रनलेवल मौजूद नहीं है" #: src/modules/services-openrc/main.py:111 msgid "" "The path for runlevel {level!s} is {path!s}, which does not " "exist." msgstr "" +"रनलेवल {level!s} हेतु पथ {path!s} है, जो कि मौजूद नहीं है।" #: src/modules/services-openrc/main.py:119 msgid "Target service does not exist" -msgstr "" +msgstr "लक्षित सेवा मौजूद नहीं है" #: src/modules/services-openrc/main.py:120 msgid "" "The path for service {name!s} is {path!s}, which does not " "exist." -msgstr "" +msgstr "सेवा {name!s} हेतु पथ {path!s} है, जो कि मौजूद नहीं है।" #: src/modules/plymouthcfg/main.py:36 msgid "Configure Plymouth theme" -msgstr "" +msgstr "Plymouth थीम विन्यस्त करना " #: src/modules/machineid/main.py:36 msgid "Generate machine-id." -msgstr "मशीन-आईडी उत्पन्न करें।" +msgstr "मशीन-आईडी उत्पन्न करना।" #: src/modules/packages/main.py:62 #, python-format @@ -287,7 +281,7 @@ msgstr "पैकेज (%(count)d / %(total)d) संसाधित किए #: src/modules/packages/main.py:64 src/modules/packages/main.py:74 msgid "Install packages." -msgstr "पैकेज इंस्टॉल करें।" +msgstr "पैकेज इंस्टॉल करना।" #: src/modules/packages/main.py:67 #, python-format @@ -305,59 +299,39 @@ msgstr[1] "%(num)d पैकेज हटाए जा रहे हैं।" #: src/modules/bootloader/main.py:51 msgid "Install bootloader." -msgstr "" +msgstr "बूट लोडर इंस्टॉल करना।" #: src/modules/removeuser/main.py:34 msgid "Remove live user from target system" -msgstr "" - -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" +msgstr "लक्षित सिस्टम से लाइव उपयोक्ता को हटाना" #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." -msgstr "" +msgstr "हार्डवेयर घड़ी सेट करना।" #: src/modules/dracut/main.py:36 msgid "Creating initramfs with dracut." -msgstr "" +msgstr "dracut के साथ initramfs बनाना।" #: src/modules/dracut/main.py:58 msgid "Failed to run dracut on the target" -msgstr "" +msgstr "टारगेट पर dracut चलाने में विफल" + +#: src/modules/dracut/main.py:59 +msgid "The exit code was {}" +msgstr "त्रुटि कोड {}" #: src/modules/initramfscfg/main.py:41 msgid "Configuring initramfs." -msgstr "" +msgstr "initramfs को विन्यस्त करना। " #: src/modules/openrcdmcryptcfg/main.py:34 msgid "Configuring OpenRC dmcrypt service." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" +msgstr "OpenRC dmcrypt सेवा को विन्यस्त करना।" #: src/modules/fstab/main.py:38 msgid "Writing fstab." -msgstr "" +msgstr "fstab पर राइट करना।" #: src/modules/dummypython/main.py:44 msgid "Dummy python job." @@ -369,8 +343,8 @@ msgstr "डमी पाइथन प्रक्रिया की चरण #: src/modules/localecfg/main.py:39 msgid "Configuring locales." -msgstr "" +msgstr "स्थानिकी को विन्यस्त करना।" #: src/modules/networkcfg/main.py:37 msgid "Saving network configuration." -msgstr "" +msgstr "नेटवर्क विन्यास सेटिंग्स संचित करना।" diff --git a/lang/python/hr/LC_MESSAGES/python.mo b/lang/python/hr/LC_MESSAGES/python.mo index ad429694e17936fbf185b8176961ae0129ad61f8..7bbf2f3f2d8a6a962907404f33e7afb4eef2e1b9 100644 GIT binary patch delta 1637 zcmXxkTS!zv9LMp$yW3^eENk;t>Z)m}UCeu{X;vncWt3gfD0>K^w+PCD^(lG?p$=V; z@}Y+;q3gaxL3bY?|0b@%_qZ5su35cV z+%hN>QSZQIcnX)}4Zl8ui>OcHeEf^q7!G?cEJ6*W5!KIrT!QB?1FvHQA7CcF#C-gU zD|x^DqmWL+ie&GPG2BhP12xmzs19GFI+#Fp_!l*>v=s08LR>(-8Wn+7)PQ?P{?Da_^lW~pWkkcS0$2y5^>5+Zwo+)B7sQy)N0baWB%*G#8q&zfh4#XLKvD9aTS#JMj@}DW|avO9@{KcB1-?U!xGE@CvnQCXxSIh-qtt`KXZA z<6%638o(%OfZtGSoJv^Qu^aWmVcdrwu?NfPT>bZRVVl@}+@SOSf)J(1=)0dkzajhYTysE87MJ-BRN1jKfJNKN=L2cHVq<3u~7q|`X`SZ@D>e@sz zN#UGHYba>l_*B?NawAzsQmNI$icw3+DRomN*BDt*)Lv22Ug5LhCM{o!|9*EZ>S<8u zs@>b($A^!dn>c~S_rg793ZIsQl`_7%?l%D34LeH(l9opMWs53)Qgnl4?E~#KEhDSv zU9{$$LibD9q(+i69*HJC&#nqOCCN9O-^rcM@sz$qB(*5u+)nFF?3v#kcE+-Xou}DH doXt7?iO7<{fK!}zJ-DZR>y@SDiIV(*;D393l!yQT delta 2349 zcmZ|QTWl0n7{KvEL10VE9kxKF2at-klqxOPT3Vr8%B2m}2E=Gjx6^jI?aVqe%Qa?G zqdpL-l2wD4P#a_7lTm935Cus}BvCZs(L_wt7sUjgL|?%FH#5Qdz)8>k&Y7J#m+ySD zy;1*lQ|`v>N$)613$>K`c7al9EP99!%DKr(HRJi%NmGQQV!>G$Fs9Ksnmf(!67lnK8@S;%j( z_fW=LSjbpdkMr?4oQp4E5?{wM=2vHE$O9KqCi(>{@h_Z(%ceyS)}lnH8TVojN+d3z z-2W5GgoQ=X1m!3b)}xHuhB96c&cq{F!~E(v4Oze?lpX(y5`n43(E!!>F#RUnh$&ox z!&r-#kx;5TcmS)XE5)BW!AAwYk23x@SdBMv4VDtloJ`n8Lnb(k5}J2$F@6$XzlL@6 zZ{qW~g5}H3Uc;4m8e8xx?#2?f`51QNK70#1@OPB6Z=M}3uwypy-@*l#3$n8>P~&a9 zHi2*vw^sT;Gn-h=(^WW#5`j;#7O$ghU@8YKktmOS5oM>Ra6SHjazqJsxdE3aiNEZi zg9|e78~6l%758r;W2?nvn(Vj+WuhG@xzH2)Dwfk9iM@)lz*{KEI*SjvzXBy$x1)@c z%F&P;2T>;Y5Le^5xc?`zXf=VSb$LEe8&V=Wg9${D_g6YweOa;g*wE%S!&vGipJbyNwV zL`MoQNB9YB-zK8CCnf0QqI1aDm$05nab}^c!shYejLLxDVA3_Jjbml zyOP|HB0H13kRrz_Mjwiq)N%Hi41?Up6^*RYtn zidsNzpsuG%!cH44p4>ih`mSepw&}EWM0eZ$R#m<|@lkTKXPLludbI7>foBG~eSOFd zdh_2W%JTmt+Dn_9ly@W(SY6t4-GFa>E68TF<$11`-%~g^*ULIOo9QxvwetQDqh|~2 z3g+v&jAzvkq~&rdW4m>$q@SNYYeCHt|K%$EOs}O=?!bU?y7VFAN4Fp2tLVlm)#|w^ z%lGwG!*aXwe-yp4VQ;jEjPU|Huw6&X{o3|*xV6q~pdD9djPGZ9J>y%t+s!&%RjO^* zj{L~9rK2Z{*Cmos6#DzJV?&OmS-BfnX~J=S{)KsM!9n90r_UM}4?n*>sq>4Hh52L2 zeHE>4k7r#ONgJJU{lFaT@8fo(uZ-B;p3S3fPaLV0CVxHoW@D?H_N*Wr(pMyG5U#U0RoR))-K$7TgtKhtORyQ3W?!v&>LEFKWjy0WshVMzBF&+6(lnx{MM ze)FJ^-XGs~^LH1X+B80@DVyDdQDqPbRi!rlcJxHXa~(5w(qhR+O~&=oCJOED1r?)X Ii%w7c7a)mi`Tzg` diff --git a/lang/python/hr/LC_MESSAGES/python.po b/lang/python/hr/LC_MESSAGES/python.po index 43b67a4b1..94461e40e 100644 --- a/lang/python/hr/LC_MESSAGES/python.po +++ b/lang/python/hr/LC_MESSAGES/python.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Lovro Kudelić , 2019\n" "Language-Team: Croatian (https://www.transifex.com/calamares/teams/20061/hr/)\n" @@ -35,8 +35,7 @@ msgstr "Montiranje particija." #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -45,7 +44,7 @@ msgstr "Greška konfiguracije" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "Nema definiranih particija za
{!s}
korištenje." @@ -216,22 +215,6 @@ msgid "No root mount point is given for
{!s}
to use." msgstr "" "Nijedna root točka montiranja nije definirana za
{!s}
korištenje." -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "Stvaranje initramfs s mkinitcpio." - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "Proces nije uspio" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" -"Proces
mkinitcpio
nije uspio s kodom pogreške {!s}. Naredba je " -"bila
{!s}
." - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "Konfiguriranje šifriranog swapa." @@ -331,18 +314,6 @@ msgstr "Instalirajte bootloader." msgid "Remove live user from target system" msgstr "Uklonite live korisnika iz ciljnog sustava" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "Stvaranje initramfs." - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "Pokretanje ažuriranja-initramfs na ciljanom sustavu nije uspjelo" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "Izlazni kod bio je {}" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "Postavljanje hardverskog sata." @@ -355,6 +326,10 @@ msgstr "Stvaranje initramfs s dracut." msgid "Failed to run dracut on the target" msgstr "Nije uspjelo pokretanje dracuta na ciljanom sustavu" +#: src/modules/dracut/main.py:59 +msgid "The exit code was {}" +msgstr "Izlazni kod bio je {}" + #: src/modules/initramfscfg/main.py:41 msgid "Configuring initramfs." msgstr "Konfiguriranje initramfs." @@ -363,18 +338,6 @@ msgstr "Konfiguriranje initramfs." msgid "Configuring OpenRC dmcrypt service." msgstr "Konfiguriranje servisa OpenRC dmcrypt." -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "Konfiguriranje LUKS ključne datoteke." - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "Pogreška postavljanja šifriranog rootfs-a" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "Rootfs particija {!s} je LUKS, ali nije pronađena zaporka." - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "Zapisujem fstab." diff --git a/lang/python/hu/LC_MESSAGES/python.mo b/lang/python/hu/LC_MESSAGES/python.mo index c56dc4aecfd8c82aff865f4ba8931669a102fed6..a77df9a5aba74765bc24707a9afcbd6c0cfb3b1f 100644 GIT binary patch delta 1643 zcmXxkOGs2v9LMp0 zAF6un@oC zdgix(G*e^TW4#h6OJ9uFkanU$wK?hF4J=_=rLD5zf&S zW|g>){)4p0_`h*I{SLyW1)oYM{<~@1iawad?ev#W3u$1PyYLb!5>r@?TE$+dK=n^! zC61#ec!%1+5^ASG5`m^QU@7iJCHu)N;$KGNIuADDBKF270hXy9*P$YD2pjPX zp2X+Km{!ICwqPsjwp>7+^$cp~C1l_+?7~5OirR4=AAW4aPTl`b8rs2a)Iw&E+%XST z$)(al-9%+>v?xl)CwOrgp zi*~9|VfRsYQk$r{k}3+biV}+i*KKx7EuY({oUHo>)I%LHuMM|ov#rtjP1kS>RiV>4 zt0?@u?A*c)G~O5PQE@XD#``rk8)wTC=p|*x+%&zB`&8K`Ouki z>)bb?jzh({o)HYs#?{3*Wr<_XQeuxYkaRwrkzC?&Cj7(UgDHD_&dco2&X=4%r$6^% eI5Th3(f>EI2t-eM_IKuXF5mfP z`bX=Pw%qlxrLQQ;7HTc^Scy_etQf`*<%8i$wd47sr6ZJ@#_<-MgbpsmBUpo%unE5@ zI(lSyeJ#%8{C*sdr*MfRW;Sn5-gE$e-q6~NiWg_1f z{TrpfN#*o~EjR(6#BsO>BX}66GQN6?hCFZqWuWhHF8+>VaQdk5!9^$$YR9eEjS`6u zQSQHnGGKW{IKV8F0b5Y|?Lg_T8>_J&n;2g`PeUef5oN_UP$Dq0GVGucr*OOumtzd; z@NHa#myl4ZTet%otCZqTy}-{Ld>y6#Pq7hi;$o~NoH-e=gN6*SA0;%e;{AB0c>W7) z=J+P=#Mw+=RyKeQcpSIjXSfM#Smpzm!0mVxyYOd}y>A~IPOxh%@n6dcn-j9KbExq* zJUE1K5x318zr<)Vz;&F9QF@UH@4$7~Up&5uEgWA%nMf@gzXp3zB6J34RLUt1e?Bev2|-1y9TQX($6P$H&n?nc#Vp=Wn2NIG)~RV$G=W37m=t zkVUKGC<{7^i!k>I4H@t+l#UvBx(S~`7O#$>~EUAP=y!&bbCjF(g6n4V;38!`vgixR5CC?PzB^57NRgClep(td2^_!w@* zt0=ir&%+X#y%@t2XkjUx(S=H56~2h=^8UX`qlFVcp-iNnpCPz{Dj}C55s-)FJ(eO9 zYNkF+m1m^LswGJ^l^_LCkr3ZqB-!sSb&MbEuk1-Xm2C{l8h-iy1Y01h;o}&T(xS2g z*-zO5A{o5r5PVn`N`oTXB*`t?Dn&BBf+~w0N|lmZ92)F-v8fi&Aph|^d(%q z&+>ZwFUzL-f0lLDu1m+9{)}hFwPV{JS6$P~X0+)zw&QOue`cJMP3vqXZg^(Hzg^_t zFK;fHpqn#}+0vJk)3J~a&@q@-C0kkZJjY(H`C)7uBj7tHXVdseYr+@U)rgF;d>#pz~xQAJ;(?qIwl8cZ@Xa z3OcwGO1;-kc~RANZwLOA$tPFbp0z}@a5`oc@, 2019\n" "Language-Team: Hungarian (https://www.transifex.com/calamares/teams/20061/hu/)\n" @@ -38,8 +38,7 @@ msgstr "Partíciók csatolása." #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -48,7 +47,7 @@ msgstr "Konfigurációs hiba" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "Nincsenek partíciók meghatározva a
{!s}
használatához." @@ -219,22 +218,6 @@ msgstr "mkinitcpio konfigurálása." msgid "No root mount point is given for
{!s}
to use." msgstr "Nincs root csatolási pont megadva a
{!s}
használatához." -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "initramfs létrehozása mkinitcpio utasítással." - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "Folyamat elhalt" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" -"
mkinitcpio
folyamat elhalt, hibakód {!s}. A parancs " -"
{!s}
volt." - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "Titkosított swap konfigurálása." @@ -331,18 +314,6 @@ msgstr "Rendszerbetöltő telepítése." msgid "Remove live user from target system" msgstr "Éles felhasználó eltávolítása a cél rendszerből" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "initramfs létrehozása." - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "Nem sikerült futtatni update-initramfs a célon." - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "A kilépési kód {} volt." - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "Rendszeridő beállítása." @@ -355,6 +326,10 @@ msgstr "initramfs létrehozása ezzel: dracut." msgid "Failed to run dracut on the target" msgstr "dracut futtatása nem sikerült a célon." +#: src/modules/dracut/main.py:59 +msgid "The exit code was {}" +msgstr "A kilépési kód {} volt." + #: src/modules/initramfscfg/main.py:41 msgid "Configuring initramfs." msgstr "initramfs konfigurálása." @@ -363,18 +338,6 @@ msgstr "initramfs konfigurálása." msgid "Configuring OpenRC dmcrypt service." msgstr "OpenRC dmcrypt szolgáltatás konfigurálása." -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "LUKS kulcs fájl konfigurálása." - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "Titkosított rootfs telepítési hiba" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "A rootfs partíció {!s} az LUKS de nem található a jelszó." - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "fstab írása." diff --git a/lang/python/id/LC_MESSAGES/python.po b/lang/python/id/LC_MESSAGES/python.po index 4763d81fb..f06076b0a 100644 --- a/lang/python/id/LC_MESSAGES/python.po +++ b/lang/python/id/LC_MESSAGES/python.po @@ -13,7 +13,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Wantoyo , 2018\n" "Language-Team: Indonesian (https://www.transifex.com/calamares/teams/20061/id/)\n" @@ -37,8 +37,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -47,7 +46,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -211,20 +210,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -313,18 +298,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -337,6 +310,10 @@ msgstr "" 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 "" @@ -345,18 +322,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/is/LC_MESSAGES/python.po b/lang/python/is/LC_MESSAGES/python.po index 8aa035ee5..fdfb49daa 100644 --- a/lang/python/is/LC_MESSAGES/python.po +++ b/lang/python/is/LC_MESSAGES/python.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Kristján Magnússon, 2018\n" "Language-Team: Icelandic (https://www.transifex.com/calamares/teams/20061/is/)\n" @@ -35,8 +35,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -45,7 +44,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -207,20 +206,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -311,18 +296,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -335,6 +308,10 @@ msgstr "" 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 "" @@ -343,18 +320,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/it_IT/LC_MESSAGES/python.po b/lang/python/it_IT/LC_MESSAGES/python.po index 4ff0f84e3..bd9ed4338 100644 --- a/lang/python/it_IT/LC_MESSAGES/python.po +++ b/lang/python/it_IT/LC_MESSAGES/python.po @@ -13,7 +13,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Pierfrancesco Passerini , 2019\n" "Language-Team: Italian (Italy) (https://www.transifex.com/calamares/teams/20061/it_IT/)\n" @@ -37,8 +37,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -47,7 +46,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -214,20 +213,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -320,18 +305,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "Rimuovi l'utente live dal sistema di destinazione" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -344,6 +317,10 @@ msgstr "" 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 "" @@ -352,18 +329,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/ja/LC_MESSAGES/python.mo b/lang/python/ja/LC_MESSAGES/python.mo index c49f8a384e02c70576b396e09531dc893679cd31..462a4d73cbe219ab898db8e8702f0edd2506660c 100644 GIT binary patch delta 3090 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 YM_YE>995lSn?|j@vTS7hc=<%v-&7>, YEAR. # # Translators: -# UTUMI Hirosi , 2019 # ブラシックデービッド, 2019 # Takefumi Nagata, 2019 +# UTUMI Hirosi , 2019 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" -"Last-Translator: Takefumi Nagata, 2019\n" +"Last-Translator: UTUMI Hirosi , 2019\n" "Language-Team: Japanese (https://www.transifex.com/calamares/teams/20061/ja/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -37,8 +37,7 @@ msgstr "パーティションのマウント。" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -47,9 +46,9 @@ msgstr "コンフィグレーションエラー" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." -msgstr "" +msgstr "
{!s}
に使用するパーティションが定義されていません。" #: src/modules/services-systemd/main.py:35 msgid "Configure systemd services" @@ -64,6 +63,7 @@ msgstr "サービスが変更できません" msgid "" "systemctl {arg!s} call in chroot returned error code {num!s}." msgstr "" +"chroot で systemctl {arg!s} を呼び出すと、エラーコード {num!s} が返されました。" #: src/modules/services-systemd/main.py:72 #: src/modules/services-systemd/main.py:76 @@ -80,13 +80,15 @@ msgstr "systemd でターゲット {name!s}が停止できません #: src/modules/services-systemd/main.py:80 msgid "Cannot mask systemd unit {name!s}." -msgstr "" +msgstr "systemd ユニット {name!s} をマスクできません。" #: src/modules/services-systemd/main.py:82 msgid "" "Unknown systemd commands {command!s} and " "{suffix!s} for unit {name!s}." msgstr "" +"ユニット {name!s} に対する未知の systemd コマンド {command!s} と " +"{suffix!s}。" #: src/modules/umount/main.py:40 msgid "Unmount file systems." @@ -94,7 +96,7 @@ msgstr "ファイルシステムをアンマウントする。" #: src/modules/unpackfs/main.py:41 msgid "Filling up filesystems." -msgstr "" +msgstr "ファイルシステムを埋める。" #: src/modules/unpackfs/main.py:159 msgid "rsync failed with error code {}." @@ -209,21 +211,6 @@ msgstr "mkinitcpioを設定中" msgid "No root mount point is given for
{!s}
to use." msgstr "
{!s}
を使用するのにルートマウントポイントが与えられていません。" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "mkinitcpioとinitramfsを作成中" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "プロセスを失敗しました" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" -"
mkinitcpio
プロセスがエラーコード {!s} により失敗しました。 コマンドは
{!s}
でした。" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "暗号化したswapを設定中" @@ -249,11 +236,12 @@ msgid "" "Unknown service-action {arg!s} for service {name!s} in run-" "level {level!s}." msgstr "" +"ランレベル {level!s} 内のサービス {name!s} に対する未知のサービスアクション {arg!s}。" #: src/modules/services-openrc/main.py:103 msgid "" "rc-update {arg!s} call in chroot returned error code {num!s}." -msgstr "" +msgstr "chrootで rc-update {arg!s} を呼び出すとエラーコード {num!s} が返されました。" #: src/modules/services-openrc/main.py:110 msgid "Target runlevel does not exist" @@ -263,7 +251,7 @@ msgstr "ターゲットとするランレベルは存在しません" msgid "" "The path for runlevel {level!s} is {path!s}, which does not " "exist." -msgstr "" +msgstr "ランレベル {level!s} のパスが {path!s} です。これは存在しません。" #: src/modules/services-openrc/main.py:119 msgid "Target service does not exist" @@ -273,7 +261,7 @@ msgstr "ターゲットとするサービスは存在しません" msgid "" "The path for service {name!s} is {path!s}, which does not " "exist." -msgstr "" +msgstr "サービス {name!s} のパスが {path!s} です。これは存在しません。" #: src/modules/plymouthcfg/main.py:36 msgid "Configure Plymouth theme" @@ -312,18 +300,6 @@ msgstr "ブートローダーをインストール" msgid "Remove live user from target system" msgstr "ターゲットシステムからliveユーザーを消去" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "initramfsを作成中" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "ターゲット上の initramfs のアップデートに失敗" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "停止コードは {} でした" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "ハードウェアクロックの設定" @@ -336,6 +312,10 @@ msgstr "dracutとinitramfsを作成中" msgid "Failed to run dracut on the target" msgstr "ターゲット上で dracut の実行に失敗" +#: src/modules/dracut/main.py:59 +msgid "The exit code was {}" +msgstr "停止コードは {} でした" + #: src/modules/initramfscfg/main.py:41 msgid "Configuring initramfs." msgstr "initramfsを設定中" @@ -344,18 +324,6 @@ msgstr "initramfsを設定中" msgid "Configuring OpenRC dmcrypt service." msgstr "OpenRC dmcryptサービスを設定中" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "LUKSキーファイルを設定中" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "暗号化したrootfsセットアップエラー" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "Rootfs のパーティションは {!s} LUKS ですが、パスフレーズが見つかりません。" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "fstabを書き込み中" diff --git a/lang/python/kk/LC_MESSAGES/python.po b/lang/python/kk/LC_MESSAGES/python.po index 3e98b3368..6d0bc8364 100644 --- a/lang/python/kk/LC_MESSAGES/python.po +++ b/lang/python/kk/LC_MESSAGES/python.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Language-Team: Kazakh (https://www.transifex.com/calamares/teams/20061/kk/)\n" "MIME-Version: 1.0\n" @@ -31,8 +31,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -41,7 +40,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -203,20 +202,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -307,18 +292,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -331,6 +304,10 @@ msgstr "" 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 "" @@ -339,18 +316,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/kn/LC_MESSAGES/python.po b/lang/python/kn/LC_MESSAGES/python.po index b73c03f02..0f5e704ca 100644 --- a/lang/python/kn/LC_MESSAGES/python.po +++ b/lang/python/kn/LC_MESSAGES/python.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Language-Team: Kannada (https://www.transifex.com/calamares/teams/20061/kn/)\n" "MIME-Version: 1.0\n" @@ -31,8 +31,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -41,7 +40,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -203,20 +202,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -307,18 +292,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -331,6 +304,10 @@ msgstr "" 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 "" @@ -339,18 +316,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/ko/LC_MESSAGES/python.mo b/lang/python/ko/LC_MESSAGES/python.mo index 5a79cb0a126fef06db9da28270a4091c9c2a4ee1..fc0658fd0d5c4ff6cf01f5b586b3b2d8221d3d1c 100644 GIT binary patch delta 1643 zcmXxkSx8h-9LMp0<7keWxuuReI;EMFEv7A|EmN6ViB>`p6-L1j*$zb+OhHkBFL@~i zqo9b0ply2cDU*z%APT|?iXIB09(szb9{T?7j0etq&bfE)S^ocX@9U-)p~%N9??t0D zQj4hV9DfDk*0Y1lS{DS%DA8%HJ^Wuh4_b=lde1((HlFb&G zMJ$&_Dg9O~!^1cY`{Mmam`(o+PQ+34qt6$cuoShBdek_Zun@a27ke=W?_eGdVF`Y~ zO6Iq}G%~qRkrMmkV%$K#6}8iAr~#j#2KbB`a1^z$^wik%Q!s;m4JrZ+s0AHIZR`qa zV?(Itzhi*;&C<;3pcp6P7MzbKkPz7eoQdC21LjRIn~Qa*fjcpP7f=hli^cdfe*G)f z)Ay#EZN(630aq|Gi$;`2D}KfntRl|SF@l@%7IvVA?J0LVk-yq8T!rUQ8+eI9^byVj z6;U=4~$$ZR*G8r@{?yJu0j!4KZvg>a6gVx<%+-l3Mrl z^7gr3!lmdIr#q)4I+9eK;FPEIIlofcop9>OXii$G$GMh%Ji2jW*yp^>zwZSS%5*Wc+ zI19QKm^AB1j?<`UgJzh2)s*>%&D2a;(`5g|y*uSUIZo5m_jh+Stdz@zqfp^1=|xKtJJ3{2j;Q)YRCE^H3sGj+?L+B@!1= zp8p9+CnDJFR4Vl1Yloj7ZiNNUeSO-NoiSre>7^^T3 z-^F=&1qr3Pja#rNLn;1Lki(Ps4od%@Vi6iRA9D$3KnAR!Ap`723C$sV3_plp{}M|$ zH}ECQXZo_TR-A=z<3{`p*JC!zEWjFk0XuOk{(_SG@^P^VZXHMb%edg?f~@QuYWxj7 zBM299+sb(}qgCNelohX{7uf@QaWx*s>G&hA#Uv6g6RAMC--l~(7$tJWtnxXm%p(3X zX!LVoCVquBl$|A!DMX^GHY4d(+fX9pLfLftkw4YPL2`c)<-M?x+OYs}zT{VGGWS}`5WajH}2f9%vegmbWBwm(&=AvxMT9g#F zqonG6loSue&u`!Y&I7k-$Yz_t*3QRGC>`!WnZOAw!cTBB-oiP!lHQhKBTDWs;XX`b zRN3usqV)3~&cvnz(Qm}0o6uBLUl6k=O~+M7$p_iTB+r@3U^`$vd`3?xCk@o zWhJh`m$4HU;;-n!0>a_NFiL-^Q)4Mzgs;l?znX@f8<$a5nnwah;M3H{sZu1T%*R@p zoG+%9P*+iT%_@8xRwOhMB(;J%k9vP8yZ?lC9^+eKmK>E+NvBnob4;PiW|L2eA4jVs z#?3(4NV0MwYlRxD$jCmBA{$y#D&d#1mda0yDy5F3N(s!5Y5iu$n^u0=e-D(UoIOL8 z&q{W(Y`*xv2t4L&JzetfZu8jOE zm(%aH*Vp*;E~mdPbS-&u=uUEF?h03xx6$KwRBNx>?dPt~;cxJ0hu7=&hBl<^8}Ds! z=>|`=-S3!nuZw{XQ%Vvtb&1F8D6QWvm#aKZcS)g~hcd=aD9-ckwdu`u4qfH0ueZCZ z^)91+L>;3XgIBT(WclWJa(_&>36zaTAtTVpSG5^t--Hd zZtb!Ae4aY5-RICX?gm%2O;xO06Y5KyGH@_`S#pl`XtX(^qrsrrdr1$UKV`O@(PreJ zEp$EeZ2CVlHjZBk*|R21>oMB9to!QT61k;~6G0<%_g<(uYj>X6-4zWFMvrtEojrF0 zX0}AkW8K;eM~vg)(4DL!GmK!9`Px47aHrYQ^Pkvhvm+8c^oB)npfmfsgh1?7ZGPOv zaMp^=-gEiGr<)3N^sQ6T?tU39+SOw8^_VS#W_#rSBhL%5Ui+hm+RXOzMn{{`5wU6G zWUF!Pg4x^j?+lnnTjiO|j);1ocbQ?ZKlDmYczrw{L^9fO+H4KSXV;WZ#0spWFjezJ i6QR, 2019\n" "Language-Team: Korean (https://www.transifex.com/calamares/teams/20061/ko/)\n" @@ -36,8 +36,7 @@ msgstr "파티션 마운트 중." #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -46,7 +45,7 @@ msgstr "구성 오류" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "사용할
{!s}
에 대해 정의된 파티션이 없음." @@ -211,22 +210,6 @@ msgstr "mkinitcpio 구성 중." msgid "No root mount point is given for
{!s}
to use." msgstr "
{!s}
에서 사용할 루트 마운트 지점이 제공되지 않음." -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "mkinitcpio를 사용하여 initramfs 만드는 중." - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "프로세스 실패" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" -"오류 코드 {!s}이(가) 포함된 프로세스
mkinitcpio
가 실패했습니다. 명령은 " -"
{!s}
입니다" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "암호화된 스왑 구성 중." @@ -317,18 +300,6 @@ msgstr "부트로더 설치." msgid "Remove live user from target system" msgstr "대상 시스템에서 라이브 사용자 제거" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "initramfs를 만드는 중." - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "대상에서 update-initramfs 실행 실패" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "종료 코드 {}" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "하드웨어 클럭 설정 중." @@ -341,6 +312,10 @@ msgstr "dracut을 사용하여 initramfs 만들기." msgid "Failed to run dracut on the target" msgstr "대상에서 dracut을 실행하지 못함" +#: src/modules/dracut/main.py:59 +msgid "The exit code was {}" +msgstr "종료 코드 {}" + #: src/modules/initramfscfg/main.py:41 msgid "Configuring initramfs." msgstr "initramfs 구성 중." @@ -349,18 +324,6 @@ msgstr "initramfs 구성 중." msgid "Configuring OpenRC dmcrypt service." msgstr "OpenRC dmcrypt 서비스 구성 중." -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "LUKS 키 파일 구성 중." - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "암호화된 rootfs 설정 오류" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "Rootfs 파티션 {!s}은(는) LUKS이지만 암호구문을 찾을 수 없음." - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "fstab 쓰기." diff --git a/lang/python/lo/LC_MESSAGES/python.po b/lang/python/lo/LC_MESSAGES/python.po index 1671e9608..d61c2778f 100644 --- a/lang/python/lo/LC_MESSAGES/python.po +++ b/lang/python/lo/LC_MESSAGES/python.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Language-Team: Lao (https://www.transifex.com/calamares/teams/20061/lo/)\n" "MIME-Version: 1.0\n" @@ -31,8 +31,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -41,7 +40,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -203,20 +202,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -305,18 +290,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -329,6 +302,10 @@ msgstr "" 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 "" @@ -337,18 +314,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/lt/LC_MESSAGES/python.mo b/lang/python/lt/LC_MESSAGES/python.mo index e2d60c86f80578dd6c6b9866586422ba5078b18a..2bd7d661b8b47c71440cf9518c2dd01b409b7523 100644 GIT binary patch delta 1631 zcmXxkSxA&o7{>9p(Z6;8L(3L|b}aBB5`rw6?kcDtz9NH= z@S>2Qz@eK6l0>LLm%kp9n^@xb|h=X^7BmiN48zO_s?g+FB^UN=e$ zwSc9^rL?7@ZD7w->aCjBVR!ao?qv z&iwX|MmjIbQet1M!*=>@sGSa=1{_5VFpe7V4{Bk7)Y$J!a5nuKR0KAn7SxN{SU+lG zBdFg`U?KCH%`~frA}q!|Sc_+n5ZMqe!3orWIca8F&YJm^12%p8@f5is+ zi2<{{*o<00KZcjmh|p-maombk#CZ{haTgBae)O?Do!ueit9A-E;04qMUSSB63Fnt- zW{Yt*{QzN-N3k5Aq89ukllW_ZG?o*>c5K8R)PO^{2ESt+mNUD~t_wHed91+KSc#KZ zjTIcc`iD?CaE%9Z+C9|7Pf*GJF`M`+RDXG)vk4NvDr`n2RZrY2s2mu?`8bN2cmkD- z`J}!Eti=v&M;+N6R1Uq3fBp+uqh;_TSr(?Dt}RON=s zTIvcabGf1g)lw5A)>wJg?kPwj51 z=&ZGC{wi!8wSlT|t89$n!kIyvTk6Vko(eff?vhe3b;SH_xT34v9G~BG4OdZh?Gz1_ z66y@siv9DY(ypg+%UqIjl*YfV3pcp%PFI7XYo;5Z+?Xm0Xe3Z|%;dXEKplz8T=K?U z5tod58F}dMOz;+@^m)HiwtHQv=OS4%OMTuzpf}Pn>v6JI6CCkYud`H0D<)sK^6nQ6~Bp=i#3?7H5o%9&A9#P%Cc6ohX@j z7v=u1Q6?-YjV73lGGP0!xD30n z22WxGo<~xtZs5aMH%ck~)RX+&fiIwp{{hzFbzFqiq%$iMc2JQC_MxQaC{D%K^Zl2w zk@j`mhI3fH?Cb!}$K%+JAL1sgWSes_fe+$SxE-&dy!+O1(E_)RBmXUQICRL)-a?JP z;?*Ifi@ZHV`wwOl+j)8(zJ{{k&rzQL9W^fDMK|GAl<|(?a{LUJ;&^s94cl-H+7;w~ z0hKd!)ZzEI5X(7P(r!hbRr^ui;WH=`zlw4eawwU)f|5x&neysp;hne%<#1;69>*%$ zXK)r?mJ5=q8z?EQ;ci*bBBV{L5Foz^V{fxKcFt#lzt3#Q1FRsIvu@is77&em*)}~IQ zJoi2>#b2-o=aT=`codm0tG=S5=_uew9+-jrsWyHj0}eLhA>4zPP!`rgI%J{Sa0?zl zIecHDY-ld&u&@nx-~h^aReTD30IC63$@kwvrJjz1C_8%(hv0HTG9pC=WS!v|koGd7 zkyuM`dss&E+fHbLq=mbbS2MV@3~o@bVgB%6F?lDggrrVNGf_gwPUU`UDKQJ^j^#F z4n8WL7W`G*S-slsax*DE9@DPl_+0hkembS&uIso#Tgl@S+_bIJshIKO^KTB(|8_}Z zLAh>Bx$&mnq;z+sET?gSw1ZJ&C)L+@kJjq@yW_gc>FqUkOz$;bbo+iTMK{)}dtIk1 z?sU3ZjKg_GOlm=mSbzVUt69Ix3(kgYunK&<9VrW*LZQAaME_HR&{J# zADkLFz5nU5zT%1bn_ZLiFZAmKgB!0lsI2&8N=G`Gb}iFu24%xG>6o+2*nTijp@VA` zR?UT%tc06(eCK9LatB;vCml~GdyEw`!F`p7gEuOx$J~;a%atD&OpUhn--d6=&jWhq z@-ROe97&DQJJNfc|4R;|q>P_&bA8&5d%3=3Z|+!dvg*^8e4@N03$pBt7bPm=nlMxI lv~O}pER*Ib^5h%6%Sl>n!0Rz7-y~e~NUqQ8-(6i+_%D$0Wl;bC diff --git a/lang/python/lt/LC_MESSAGES/python.po b/lang/python/lt/LC_MESSAGES/python.po index 2a876e187..40932607b 100644 --- a/lang/python/lt/LC_MESSAGES/python.po +++ b/lang/python/lt/LC_MESSAGES/python.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Moo, 2019\n" "Language-Team: Lithuanian (https://www.transifex.com/calamares/teams/20061/lt/)\n" @@ -35,8 +35,7 @@ msgstr "Prijungiami skaidiniai." #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -45,7 +44,7 @@ msgstr "Konfigūracijos klaida" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "Nėra apibrėžta jokių skaidinių, skirtų
{!s}
naudojimui." @@ -217,22 +216,6 @@ msgstr "" "Nėra nurodyta jokių šaknies prijungimo taškų, skirtų
{!s}
" "naudojimui." -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "Sukuriama initramfs naudojant mkinitcpio." - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "Procesas patyrė nesėkmę" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" -"Procesas
mkinitcpio
patyrė nesėkmę su klaidos kodu {!s}. Komanda " -"buvo
{!s}
." - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "Konfigūruojamas šifruotas sukeitimų skaidinys." @@ -334,18 +317,6 @@ msgstr "Įdiegti paleidyklę." msgid "Remove live user from target system" msgstr "Šalinti demonstracinį naudotoją iš paskirties sistemos" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "Sukuriama initramfs." - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "Nepavyko paskirties vietoje paleisti update-initramfs" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "Išėjimo kodas buvo {}" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "Nustatomas aparatinės įrangos laikrodis." @@ -358,6 +329,10 @@ msgstr "Sukuriama initramfs naudojant dracut." msgid "Failed to run dracut on the target" msgstr "Nepavyko paskirties vietoje paleisti dracut" +#: src/modules/dracut/main.py:59 +msgid "The exit code was {}" +msgstr "Išėjimo kodas buvo {}" + #: src/modules/initramfscfg/main.py:41 msgid "Configuring initramfs." msgstr "Konfigūruojama initramfs." @@ -366,18 +341,6 @@ msgstr "Konfigūruojama initramfs." msgid "Configuring OpenRC dmcrypt service." msgstr "Konfigūruojama OpenRC dmcrypt tarnyba." -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "Konfigūruojamas LUKS raktų failas." - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "Šifruoto rootfs sąrankos klaida" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "Rootfs skaidinys {!s} yra LUKS, tačiau nerasta jokios slaptafrazės." - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "Rašoma fstab." diff --git a/lang/python/mk/LC_MESSAGES/python.po b/lang/python/mk/LC_MESSAGES/python.po index b847e7f10..188a74ad9 100644 --- a/lang/python/mk/LC_MESSAGES/python.po +++ b/lang/python/mk/LC_MESSAGES/python.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Martin Ristovski , 2018\n" "Language-Team: Macedonian (https://www.transifex.com/calamares/teams/20061/mk/)\n" @@ -35,8 +35,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -45,7 +44,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -207,20 +206,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -311,18 +296,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -335,6 +308,10 @@ msgstr "" 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 "" @@ -343,18 +320,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/mr/LC_MESSAGES/python.po b/lang/python/mr/LC_MESSAGES/python.po index d8b4f1cac..3c570148e 100644 --- a/lang/python/mr/LC_MESSAGES/python.po +++ b/lang/python/mr/LC_MESSAGES/python.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Language-Team: Marathi (https://www.transifex.com/calamares/teams/20061/mr/)\n" "MIME-Version: 1.0\n" @@ -31,8 +31,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -41,7 +40,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -203,20 +202,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -307,18 +292,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -331,6 +304,10 @@ msgstr "" 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 "" @@ -339,18 +316,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/nb/LC_MESSAGES/python.po b/lang/python/nb/LC_MESSAGES/python.po index b9ab8b7b9..cd50bfad6 100644 --- a/lang/python/nb/LC_MESSAGES/python.po +++ b/lang/python/nb/LC_MESSAGES/python.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Tyler Moss , 2017\n" "Language-Team: Norwegian Bokmål (https://www.transifex.com/calamares/teams/20061/nb/)\n" @@ -35,8 +35,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -45,7 +44,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -207,20 +206,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -311,18 +296,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -335,6 +308,10 @@ msgstr "" 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 "" @@ -343,18 +320,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/ne_NP/LC_MESSAGES/python.po b/lang/python/ne_NP/LC_MESSAGES/python.po index 0f63dcd5d..0377c110f 100644 --- a/lang/python/ne_NP/LC_MESSAGES/python.po +++ b/lang/python/ne_NP/LC_MESSAGES/python.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Language-Team: Nepali (Nepal) (https://www.transifex.com/calamares/teams/20061/ne_NP/)\n" "MIME-Version: 1.0\n" @@ -31,8 +31,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -41,7 +40,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -203,20 +202,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -307,18 +292,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -331,6 +304,10 @@ msgstr "" 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 "" @@ -339,18 +316,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/nl/LC_MESSAGES/python.po b/lang/python/nl/LC_MESSAGES/python.po index eb7e6a754..0a7c305fb 100644 --- a/lang/python/nl/LC_MESSAGES/python.po +++ b/lang/python/nl/LC_MESSAGES/python.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Adriaan de Groot , 2019\n" "Language-Team: Dutch (https://www.transifex.com/calamares/teams/20061/nl/)\n" @@ -35,8 +35,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -45,7 +44,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -209,20 +208,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -313,18 +298,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -337,6 +310,10 @@ msgstr "" 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 "" @@ -345,18 +322,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/pl/LC_MESSAGES/python.mo b/lang/python/pl/LC_MESSAGES/python.mo index ea1d342693fcc31e4e4f7db0a09b9f82a2d295a8..79c4cbd7d0b5792637bd8b474cbeaf71546c6523 100644 GIT binary patch delta 1123 zcmXxjPe@cz6vy%7%rrVRHsee>W?KH8F`XGTB9u(A9B5Hse+U;6Z3xTuXQ3EW6X3q^G0riF|(yK0>}z zwrLvru!nWHh-YvGGq{Nt@Bs6eikj8nFlyW#yo*op9DWI&|3FRr6E*$_lbEbDyNoT^ z#{BkxhE_g}Ih;p*_!~Ci7GA|a*n(H8%(`(Ld+`nG{Uy}+&A>w(q+b^!Yj_U}_!%$a zHr6t~Rh=|DjpuO`3#bX7VKXjbB4oCPIr=+s#$sjl@q)6b4Bf;ooJ1|q!y+yR{XJAh z8kj7FMJy}zBQ$jO6Q~rvLY>hp>TExu#;v1vxQG21=Rj2pCDc(pMD6rBDpTvI34aIu z82MMf88_$<310RlJD4we^EPV=ioGO3=8-eOX#6ezJWb>gi}~#TY7&Em5~+H zf_HHU!_58^uj3{Bm?r-!svRC^$8lz3tYz^Q4xnCmi<)R3`9Z9MOPM00ZsB@YJ5vEG zv^eV3Em}Vk`*EQxDm14uuKIIDq_%=gxzO&FdY$M0hy)ESQ0aCxfU1dRF6~^Q-&MP( zzKoJF%Ebls=(3?BQ&3WNjiYp-^V0vUIK{=^;-Zf`*|qF(*A)~=aM9z>L}n_yj_A0* Z6ulktYhtCS_cAf*XOagYzdqd>{s+ABTfqPT delta 1281 zcmY+^OGs2v9LMp$LOp*6wbRF_ z=cZAa^O5FtSd2PDyK~9EY8zuf85l&pFo{}-3aa};)O`yo&~`kJ2T_@Ni_0;{s5&N(WZ=*`_9@&$H3dnyG7bQeLf!k1l9->k5pwk;)D3@@2VOyZNCfwJ&>TFuyMz>+N@Y, 2019\n" "Language-Team: Polish (https://www.transifex.com/calamares/teams/20061/pl/)\n" @@ -37,8 +37,7 @@ msgstr "Montowanie partycji." #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -47,7 +46,7 @@ msgstr "Błąd konfiguracji" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -217,20 +216,6 @@ msgstr "Konfigurowanie mkinitcpio." msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "Tworzenie initramfs z mkinitcpio." - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "Błąd procesu" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -325,18 +310,6 @@ msgstr "Instalacja programu rozruchowego." msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "Tworzenie initramfs." - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -349,6 +322,10 @@ msgstr "Tworzenie initramfs z dracut." 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 "Konfigurowanie initramfs." @@ -357,18 +334,6 @@ msgstr "Konfigurowanie initramfs." msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "Konfigurowanie pliku klucza LUKS." - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "Zapisywanie fstab." diff --git a/lang/python/pt_BR/LC_MESSAGES/python.mo b/lang/python/pt_BR/LC_MESSAGES/python.mo index 39de8487c8829d2b6b85d9e4e9fa77b5f331b3f0..a004f563d372fcb11c7dbb55f77a7853798d7bc7 100644 GIT binary patch delta 1633 zcmXxkTS!zv9LMp0>sGp!rk1x#%}uj1Q`0VL=~`+;Wtdr1LLnqXQsI+UY)}si6%mJS z5Eep31r;s5>_bG+g`g;epn|{$D-env3Z$35zjKZQv!9uB&d$vF|7Xsxwo8%d*UaEW zqqI@yQ9A=>`|)g$AIhw0W}7g>cP|#xzm56$23O!1=3?G-vl^`S?M2ke`%f{8{urj?1mZ+BjI;4R=HPQI z#4lLR{PvGV1{cag-h*}6LBAdKro*TKU!VpUMGZKCT3A}D_y1y?MZX3Wffm$)22n3I zgnF^(sQ-`SeC9WsVO9?XxBz!!EgnZgWRGwuj-v+5nQ2yu^{9al;e5P+THpgLz*qkD zZ`eRTm}a&YBd7%oVRRXdIE{83#VuGxoEKvhci|n}hXGzsx$8k5wE^6KG1LpZ#Ue~0 zoad*QEx}IuiA=LDOeb8`cmTEVt69W<8;vJiDAfZjs})z`Mm&L<;H7^(mD%-N2X4gy z)SJD=wK$c8H{p6z|1>Hh&ycm*XH;ayQ7H}O5PxlkQl2WqR#YetqyBh~ALh23sNJ1F z-5emSc5-t z6^7aBns5*5`cYIQZlNangL3b#vWDyNJ4mI+M!0ZVLF`xSJK+qUbbH^>UiuEjpJf z6&~)d_QPaR$Vj#Esjy~h165&FY4NZUWTWdeyG1*_j!Np?RO+H~&S%3dI?54$emCT+ zxu9dGyr?K#$!^R0^6|ZJkC}F|_6VsozPj#F0{5#pRSilxRcX*^nk+gwNz^4&ZC33g zww3qYS57&FZf=wgi$9*$mE@F$t~h@~olbA+$@uIU;ea!oHW=TY{yoL%$s3vyaW3R$ eIh*o#Iq&k%#81tA7H|>;F=xlTh4BZ4O~L;b%$7y~ delta 2342 zcmZwITWl0n9LMoPsYpv(q##?M$SGAspi6~m_Owh?qqlBx=wQA@LGZG|B^lO~gp#LF0>w8pUW76VwMTiHUxHvxC9lNzZ;}&YV4$ z|M}1MK>LN|g>P%iUo?~$wVt}a%$Po`x`7YM2g8i%#1BKuZ!~5y_c0ugKF-FyScj*u z1-}j*IlT0IDbA#QC*F)laGo&*bApRT8ZP0jIHAIr+i?-Y?N3~s{+K8=%@-@L+wzHkCH(GNHSFXAX{98vn>98`olaXt2+ zB5@qm{~OeVl~tt)rl2NlLyg;o8m|X$!d=+H{N_0>w1AILJ3fbs!0_tQ0L?g&`wm=) zacsa>aSonBLTN7H1K3<+41Z=1AJg$5YW&mKjOTGK))UTxChX!u6YNBV<^bM;Z-?!l zV=MRPaT88u`P$i2*n}@(3_ry+SjRT+z$D&_`*1V!bRLRaDRx|y73~;!ZnPdg+GSt@Gwr%b6kcKIq(&jK#l(vs{Kz?zxnKPEpCnw zf9>oY8t%s5a1l-;vvl8wipWu9bLJE(GGCz1`VX9h)nw#UYzpm0MYMqW{>!L{y@!0o zd=@@Grw%&HA*3*yHjUVZbCJ!MJhEuB8+Dei;X`;9HSv5_p-|t4Gx15(cmqhZ%~z<2 ze-7{e3h!&kI(?5ys&X2&lUaBVZooM1M>cOR<6Im~rw6eU zl?z9(8Lwalr!ik8gu-7loJ zQkPTd9+Z)M#;BG`&`bw)4)xliWW2UCFn^E`I-^dicBZm~%I{B*JUZXuRF(1)!TYVe zP*xM!Ak=!KB-L@M%%EyRI%kztRDN25%??!qrJxY1=W!no;9g8nTZ>?S@|0#=ZW2C!Mf6oNTH4!#pZ=jGA@6 z7k9H+yUby^iQ=zSPb^qpT13Y2bE#a)OI!7~sjLmQwk4mlY0qYyY&O&DJ6YEzy?iJn%yG#}yMi>-gL9sqLOkuz+4?yK56(FhI1}5qY!tWn^sebYx=jLL@!C zgM9|wymT_vllPs$HwIr1TEcL+#3z->ISH@0scuh0(BJW_yVH&5bB=#~XuhjEQ&x!C zOlfc4{|Ct?ovpoIUg5ExjSmhaQa!<}ihHoiXctY#2U|_-U}K;p8jD zV-p@--cFo|VrfHRT!Uy19xX+)pEF6j>E3+5W0Q(zQz=-Qj%|Bs@+IL6G}kA~{{i~H BZ~XuO diff --git a/lang/python/pt_BR/LC_MESSAGES/python.po b/lang/python/pt_BR/LC_MESSAGES/python.po index 9059b758f..f9630896b 100644 --- a/lang/python/pt_BR/LC_MESSAGES/python.po +++ b/lang/python/pt_BR/LC_MESSAGES/python.po @@ -12,7 +12,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Guilherme , 2019\n" "Language-Team: Portuguese (Brazil) (https://www.transifex.com/calamares/teams/20061/pt_BR/)\n" @@ -36,8 +36,7 @@ msgstr "Montando partições." #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -46,7 +45,7 @@ msgstr "Erro de Configuração." #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "Sem partições definidas para uso por
{!s}
." @@ -218,22 +217,6 @@ msgid "No root mount point is given for
{!s}
to use." msgstr "" "Nenhum ponto de montagem para o root fornecido para uso por
{!s}
." -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "Criando initramfs com mkinitcpio." - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "O Processo Falhou" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" -"O processo
mkinitcpio
falhou com o código de erro {!s}. O comando" -" foi
{!s}
." - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "Configurando swap encriptada." @@ -334,18 +317,6 @@ msgstr "Instalar bootloader." msgid "Remove live user from target system" msgstr "Remover usuário live do sistema de destino" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "Criando initramfs." - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "Erro ao executar update-initramfs no alvo" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "O código de saída foi {}" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "Configurando relógio de hardware." @@ -358,6 +329,10 @@ msgstr "Criando initramfs com dracut." msgid "Failed to run dracut on the target" msgstr "Erro ao executar dracut no alvo" +#: src/modules/dracut/main.py:59 +msgid "The exit code was {}" +msgstr "O código de saída foi {}" + #: src/modules/initramfscfg/main.py:41 msgid "Configuring initramfs." msgstr "Configurando initramfs." @@ -366,18 +341,6 @@ msgstr "Configurando initramfs." msgid "Configuring OpenRC dmcrypt service." msgstr "Configurando serviço dmcrypt do OpenRC." -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "Configurando o arquivo de chave do LUKS." - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "Erro de configuração de rootfs encriptado" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "A partição Rootfs {!s} é LUKS mas nenhuma frase-chave foi encontrada." - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "Escrevendo fstab." diff --git a/lang/python/pt_PT/LC_MESSAGES/python.mo b/lang/python/pt_PT/LC_MESSAGES/python.mo index a1760e7bd4eac0342be5ba265ed2d7e0aa5ee845..60d342d6e242279944db636a824f390eb2f137f6 100644 GIT binary patch delta 1472 zcmYM!OGs2v7{Kw*$4qLznn}w{9m~>uHmT*S=tY_ND7BK3aMZ~`2QLmP;lf!IxQUW9 z6B26GqDX=vS`-zJ6Af)y}x_z+8)KM*4>1?tS@mD&q@EEYl7wzd!$YVYUO*klAg1CC+=%ya6F$R2oWl($ zvElz6*i8SD%SAf(M^ImwvL2X4?f4byiytu=zo5?WH|oGk;=%)OK^^#I)B)VX419vs zIEUGov|gkf-B>{X(!+%|G=aPEDQYBEFcTBv!wnT;4fQ%~$1yCzPuPTx1d#^p#9jCp z+i)H`urx6o`bj)W{Q(AbWZ$@OVFB@-iV&&CbJUlau3F9X^Kk+-QZKL>=W!<%IYf?Q zD;~xf)D9N$80HX0olqa1!f~v`B`5K(;v$`R?Z>mI^-0vVe2cUppHVwrwM-#{G+EuK zxzLFG#AnqwP~8ronR7U6Z&5k5!lZ~-r& zlT_b>BX}MkVFShx9)0gD_TyFT#qXGf7YUax%_wR=FHx5y_>&8kT*x7_L~>?KW+G}* zGGVjqv#dfA*_^e`OrzrB(5UImw2*IRVaJ&}N_T}ur^dYd|CFcupZ?A55sf6gS#(Ks z)|DLkVbYoDXm$H((a>pzYb10wQ5;${S2Q8D=+<2;x{C;)xx|Uq%|gtQli`{s3Evsv zqh=P}w`+xMZhqnRA{)ajMBQ8-qAPX|P2T)awrwEF?l-zTesAbXj58vx(=Z18hNs&b z2wjW)YRjq}>M>kLJb_`4-)FdLd{q0a+CiT&7`mM_ZL^sTgfdgABhn04mnRVL_ISFD VfUDcA*HsAGn|2;W|FAU^1q}nq^@gYC=D1Azhe(L0pelumqTrHT)!xgtqz^T|9{I{HA%8Z`%MqMG zmEad{#Y`q)?bhhpo5IOG(ShFJ(D~p{V7Nax*whzZOuiixzLs7T6@H)5 G?EMS%E`pZ; diff --git a/lang/python/pt_PT/LC_MESSAGES/python.po b/lang/python/pt_PT/LC_MESSAGES/python.po index 3fb39b9e6..dcefb6c66 100644 --- a/lang/python/pt_PT/LC_MESSAGES/python.po +++ b/lang/python/pt_PT/LC_MESSAGES/python.po @@ -5,17 +5,17 @@ # # Translators: # Nuno Amorim , 2018 -# Hugo Carvalho , 2019 # Ricardo Simões , 2019 +# Hugo Carvalho , 2019 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" -"Last-Translator: Ricardo Simões , 2019\n" +"Last-Translator: Hugo Carvalho , 2019\n" "Language-Team: Portuguese (Portugal) (https://www.transifex.com/calamares/teams/20061/pt_PT/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -37,8 +37,7 @@ msgstr "A montar partições." #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -47,7 +46,7 @@ msgstr "Erro de configuração" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "Nenhuma partição está definida para
{!s}
usar." @@ -218,20 +217,6 @@ msgstr "A configurar o mkintcpio." msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -325,24 +310,12 @@ msgstr[1] "A remover %(num)d pacotes." #: src/modules/bootloader/main.py:51 msgid "Install bootloader." -msgstr "" +msgstr "Instalar o carregador de arranque." #: src/modules/removeuser/main.py:34 msgid "Remove live user from target system" msgstr "Remover utilizador ativo do sistema de destino" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -355,6 +328,10 @@ msgstr "" 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 "A configurar o initramfs." @@ -363,18 +340,6 @@ msgstr "A configurar o initramfs." msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" @@ -389,7 +354,7 @@ msgstr "Passo Dummy python {}" #: src/modules/localecfg/main.py:39 msgid "Configuring locales." -msgstr "" +msgstr "A configurar o local." #: src/modules/networkcfg/main.py:37 msgid "Saving network configuration." diff --git a/lang/python/ro/LC_MESSAGES/python.po b/lang/python/ro/LC_MESSAGES/python.po index d5866ca40..36a8ba3d0 100644 --- a/lang/python/ro/LC_MESSAGES/python.po +++ b/lang/python/ro/LC_MESSAGES/python.po @@ -12,7 +12,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Sebastian Brici , 2018\n" "Language-Team: Romanian (https://www.transifex.com/calamares/teams/20061/ro/)\n" @@ -36,8 +36,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -46,7 +45,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -208,20 +207,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -314,18 +299,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -338,6 +311,10 @@ msgstr "" 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 "" @@ -346,18 +323,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/ru/LC_MESSAGES/python.po b/lang/python/ru/LC_MESSAGES/python.po index d4198ca14..46e90df6c 100644 --- a/lang/python/ru/LC_MESSAGES/python.po +++ b/lang/python/ru/LC_MESSAGES/python.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Aleksey Kabanov , 2018\n" "Language-Team: Russian (https://www.transifex.com/calamares/teams/20061/ru/)\n" @@ -35,8 +35,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -45,7 +44,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -207,20 +206,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -315,18 +300,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -339,6 +312,10 @@ msgstr "" 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 "" @@ -347,18 +324,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/sk/LC_MESSAGES/python.po b/lang/python/sk/LC_MESSAGES/python.po index 955951f29..82bab4642 100644 --- a/lang/python/sk/LC_MESSAGES/python.po +++ b/lang/python/sk/LC_MESSAGES/python.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Dušan Kazik , 2018\n" "Language-Team: Slovak (https://www.transifex.com/calamares/teams/20061/sk/)\n" @@ -35,8 +35,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -45,7 +44,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -207,20 +206,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -315,18 +300,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -339,6 +312,10 @@ msgstr "" 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 "" @@ -347,18 +324,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/sl/LC_MESSAGES/python.po b/lang/python/sl/LC_MESSAGES/python.po index 9ed9c5784..6c3f25699 100644 --- a/lang/python/sl/LC_MESSAGES/python.po +++ b/lang/python/sl/LC_MESSAGES/python.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Language-Team: Slovenian (https://www.transifex.com/calamares/teams/20061/sl/)\n" "MIME-Version: 1.0\n" @@ -31,8 +31,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -41,7 +40,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -203,20 +202,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -311,18 +296,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -335,6 +308,10 @@ msgstr "" 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 "" @@ -343,18 +320,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/sq/LC_MESSAGES/python.mo b/lang/python/sq/LC_MESSAGES/python.mo index 64347c01fd699538256981fae15bb298f46f193a..1ae01a16eea811ee6b591317e23c103b5294275d 100644 GIT binary patch delta 1627 zcmXxkZ)nX?9LMqR?yk+fo0(zT9hC|SQSv#Kh^M{h1X0{F|dA4E+{Q)e%SGW+rU_OS@&7v6b+>iSI6Ra+G!tZ!WXCsKBFcaMFp0Xk^FrLX48+NGSG+$s1voZ ztEi1VNB#aA7P7usrr9zm!eZQkHQ0ru$R6T6{Dzt^Z-QABE<;Ux2n+END!_YKgfG4E zuUJRlpJmpHF;oCoF+QJ0f<_a5#tm3ap66g3Tkt0CLLb}H+3i6dwd1%N&!9H&2E!O2 zon0wrbFrEJKu*%XSV4aiX;Z-6lgWQAjVlZ&#qY5mf1)Ce5T-nWi}5zresjMJ;gA>pw+evaiUL_8YZM1{Xtjs63baPp1)MKxfm2bMdtIzys8+evP_hLm0+? zsDQ%cTX&}gwZK7a!)~m^52z!{WD*5lg(Sf?q5^1-(;&Nc!W%e;+Szr~jy|CR3h=a! zDvDZYx7R<0Yw7o+p8JmLFpp@r>N!*(Pf-6K#s!!|8q|+B(9mT$jQrNlV;FCsUXzzt zi^JG~C8SFM^q?lXg?d{CaSK+mO-+0Xcj6t~hZ9(YN2~*tflIhv?|(my7y~01#t5sX zAm1VPa)GU&E}|-hDyyh9RKGfuQ&2GXgztYc*{jg{15cOdTmbD3->kCjjpD0BF0zO{RV)0eB;!h=q;$Cu2IJ;Wtd9U@o<0L zS6N5yo(uQFJy+f4dJQHXrEN=f%7VSluVAyYKjUO#N@l6g>C5U&Y?+u6a60o7&Vf*y a^CNU2@wniQ&v{jN);T+^IB~ydB=tWtJd{-c delta 2281 zcmZ|QTWl0n7{KvEsX(tl!7YUfr&ORSELB=ArB;*{q|}zQ&=|aR+MVrAm)%)rW`%-e zy+ji)h-Q>TP1MF1O`4dP8blInnm(W*=z}jxqz}Lg@}Ni}XiV_`%?^e{J?WX>IcH|h z=`CDH$7d+jj$ecp&QxkC^)6h94z9t&xBw@x z0ndcao|V7fimPegkGJB-xL&E88mCZ8!&ST;7ZoYB0ym-56F3hK<7^zkD*O~>z*8s_ zxe$6CrN4#6^o1=L!QD6?_hKc!fJ+!(y-Pt}7)KfC9InLQaW2-Dz=iBLOs;~+{T zPM|!07G=QV()<9+Q3h;5>9+@^zd@XX!`Q(1>Lm&?fv-?jd>$nNv&!-v)Z=Z`+i)We zU=6;9jW~gXQeDMIu)bU={?sd6?!tFa`ag;FcnQ~HHQ~(3fISpsfc+?;If{$%ld%0X zHdDWZk76Cumz6z_tMF~?!msfmT);B#z&JjPuVEivMA`fHiu?roDu{n84K@w3vd>WC zulUq7!bRM6Qh$}v#Phfk*VBtk*u*A$4kh&C*n($JCS1kFi@mrGeU$f3;Rd`IA^vp~ zYFW0-xC3Q?C&T&&$fDF~ls%k68R$2ZLs-rUtj0QAhHWTYm&7~KM|o}>`BOh|k;8f! zHJ0YMD_gJ%nUw0rb!Z{cQX?n>kD+vY5+BE3Fp8b@wjK|m?C~*_6`nzYsIDQ8suE_+ z?x|%c^+w!)xh@K_@)uENJchETQz!$MvOKA4+=`tj&mF~foWNaJ%BW&LO2m$%Oz<0& z=da;vtmR;B#2%zQr;bqIPo3Z*Gy4%WUcn_epGy-qpoccf#4ez8cn!O;PSYtKL>cfq zd;~Yr{fAsBjNiw&La_5xS2o-?xNMLLB~!P}?ZW z7D?jE3l1dP9i*brdVC-(%emlqshQFwr~Se3MhAA1`Ck+Kw8|H-oGd55j4bf&+-!fw?#|* zKZ<&*+tLHhaKj}p8J@Z7pDxCZ6*m_|baTcr zTT)4B9>`dB^J=O4<#VeVYTQFny)$9z0Xvm4(lNcyaPyBJR@U8Sx={JoiSWDlW+{z)NwnTjzv{Z$2NbYWa-%J zWk1b|Bzf7~GdZf0!;>GGZX$R$>OU5l^sh&%{40?fe{p5simgV!mD1UvnB@+cL*|Y3 zd%PHT6J~(2G4U{^Z)<= diff --git a/lang/python/sq/LC_MESSAGES/python.po b/lang/python/sq/LC_MESSAGES/python.po index 5ba1cbf07..2eaca42fc 100644 --- a/lang/python/sq/LC_MESSAGES/python.po +++ b/lang/python/sq/LC_MESSAGES/python.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Besnik , 2019\n" "Language-Team: Albanian (https://www.transifex.com/calamares/teams/20061/sq/)\n" @@ -35,8 +35,7 @@ msgstr "Po montohen pjesë." #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -45,7 +44,7 @@ msgstr "Gabim Formësimi" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "S’ka pjesë të përkufizuara për
{!s}
për t’u përdorur." @@ -216,22 +215,6 @@ msgid "No root mount point is given for
{!s}
to use." msgstr "" "S’është dhënë pikë montimi rrënjë për
{!s}
për t’u përdorur." -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "Po krijohet initramfs me mkinitcpio." - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "Procesi Dështoi" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" -"Procesi
mkinitcpio
dështoi me kod gabimi {!s}. Urdhri qe " -"
{!s}
." - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "Po formësohet pjesë swap e fshehtëzuar." @@ -330,18 +313,6 @@ msgstr "Instalo ngarkues nisjesh." msgid "Remove live user from target system" msgstr "Hiq përdoruesin live nga sistemi i synuar" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "Po krijohet initramfs." - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "S’u arrit të xhirohej update-initramfs mbi objektivin" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "Kodi i daljes qe {}" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "Po caktohet ora hardware." @@ -354,6 +325,10 @@ msgstr "Po krijohet initramfs me dracut." msgid "Failed to run dracut on the target" msgstr "S’u arrit të xhirohej dracut mbi objektivin" +#: src/modules/dracut/main.py:59 +msgid "The exit code was {}" +msgstr "Kodi i daljes qe {}" + #: src/modules/initramfscfg/main.py:41 msgid "Configuring initramfs." msgstr "Po formësohet initramfs." @@ -362,18 +337,6 @@ msgstr "Po formësohet initramfs." msgid "Configuring OpenRC dmcrypt service." msgstr "Po formësohet shërbim OpenRC dmcrypt." -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "Po formësohet kartelë kyçesh LUKS." - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "Gabim ujdisjeje rootfs të fshehtëzuar" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "Pjesa rootfs {!s} është LUKS, por s’u gjet frazëkalim." - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "Po shkruhet fstab." diff --git a/lang/python/sr/LC_MESSAGES/python.po b/lang/python/sr/LC_MESSAGES/python.po index ed037af81..7ee71668a 100644 --- a/lang/python/sr/LC_MESSAGES/python.po +++ b/lang/python/sr/LC_MESSAGES/python.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Slobodan Simić , 2019\n" "Language-Team: Serbian (https://www.transifex.com/calamares/teams/20061/sr/)\n" @@ -35,8 +35,7 @@ msgstr "Монтирање партиција." #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -45,7 +44,7 @@ msgstr "Грешка поставе" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -207,20 +206,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -313,18 +298,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -337,6 +310,10 @@ msgstr "" 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 "" @@ -345,18 +322,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "Уписивање fstab." diff --git a/lang/python/sr@latin/LC_MESSAGES/python.po b/lang/python/sr@latin/LC_MESSAGES/python.po index 1f08cddfd..74c8f2782 100644 --- a/lang/python/sr@latin/LC_MESSAGES/python.po +++ b/lang/python/sr@latin/LC_MESSAGES/python.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Language-Team: Serbian (Latin) (https://www.transifex.com/calamares/teams/20061/sr@latin/)\n" "MIME-Version: 1.0\n" @@ -31,8 +31,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -41,7 +40,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -203,20 +202,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -309,18 +294,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -333,6 +306,10 @@ msgstr "" 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 "" @@ -341,18 +318,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/sv/LC_MESSAGES/python.po b/lang/python/sv/LC_MESSAGES/python.po index f618e8767..1e83eabe8 100644 --- a/lang/python/sv/LC_MESSAGES/python.po +++ b/lang/python/sv/LC_MESSAGES/python.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Language-Team: Swedish (https://www.transifex.com/calamares/teams/20061/sv/)\n" "MIME-Version: 1.0\n" @@ -31,8 +31,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -41,7 +40,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -203,20 +202,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -307,18 +292,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -331,6 +304,10 @@ msgstr "" 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 "" @@ -339,18 +316,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/th/LC_MESSAGES/python.po b/lang/python/th/LC_MESSAGES/python.po index e584eb538..a41b2ac35 100644 --- a/lang/python/th/LC_MESSAGES/python.po +++ b/lang/python/th/LC_MESSAGES/python.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Language-Team: Thai (https://www.transifex.com/calamares/teams/20061/th/)\n" "MIME-Version: 1.0\n" @@ -31,8 +31,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -41,7 +40,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -203,20 +202,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -305,18 +290,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -329,6 +302,10 @@ msgstr "" 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 "" @@ -337,18 +314,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/tr_TR/LC_MESSAGES/python.mo b/lang/python/tr_TR/LC_MESSAGES/python.mo index 1e461e3703eaf251d0a67bdb622e650fb625af37..1197e1a652ed7f3b1114ee43e2d6667936d6597f 100644 GIT binary patch delta 1639 zcmXxkTS!zv9LMp$yIZE_YPqecxvtv9w5yjg-7+f^f-*`nO6VeGQ4c}%kO><^6x2g` z2n)h46wymT3(Q(snGNeGT*RIac8poQ!#?X4P1kv=jCJd7O*=I0 zS*=;z!co^OAsOrWDIedNMATt~YFwbIL|0iU7<7(fj;jG9<5W90r4%%)w9%0LrpLS3kZ z^`RE_1ayAI@1JBTarIBEeeFp6oU z^F)eSIkwThJ<)6f21%FB!Vc6HoXa8qi>chDLo@!38ZgZCG~i~e!(Ob$*QmWuWfr=w z7&XzISdOPq3%Z|de?^^v5I@{%6{rj^#VBqMlYey_p<@# zyaP3%ExCTF?#;f9$(DhqU3p|Qiz!fAZ_ApL`tl2BnKp#;l`iXO}jH~Bj z8&={m)Ij%86MKtG@Gt7R7_UMj?#1PJ1GS(ZSc4HxvNGO^x<1}RMFTxXz5j!#Q|hNd z)hbXaZN@!#0LiKi;B@?r+KLD#upT>5_g}z$_zZVpEwkoQyM%PvLtLx(|2-AmIGcQz z;ciSpzC&(cum)lQp&M1SGOZ?{24ykPOhk!AL?*$oZVOXUhjp|pq_UJKb{%o|>t?K) zQa)NVnbD$Dv8BeR!j=&+LTOcL8o{Qa_LR5O6>V1?!A`m@Rj1AfpAA=(^~U7$U5abz z&}r7eQqjkUkDV)7{ALi!l+Me1LfgYv*Bvl$2WyNf6dk^K#7Z@iMcd^k^rmpG-8Q<6 zYF{`X?rWw)xP)-U>kAbn-i)pCd(+d;dcV?Jz0QooiO~2`pLaRfl~|v(D9yVw`IGk{ fuie{{-x8N?6NPL3Q z{(F=G%O-{c%t0Bj4W-{+l>T<%oj8EajIUmxAQSiuWyP0KA~3!@?4SwnrrwS#upb+6 z2$$eFB$VnpZpWqyrT9~W{LIIrDE)tqO?VBL;&j4UkO6xs$N>9LLh~BlgD0Zv7qON4 zHGB-`F@0ItAzX;BV-J3To3NH;-iry`hDUG*{*1EsomJrkcT^Go^<1#IAS?SAHU5e( z77;Gu_6YSi8Lbb0$Hmx1FZK8guEe)cCVUB{zrRuXTg%3`;M3TQr%}$%FDUKC*ARc1 z=_ZzaAMQn2(c4k|Yox9E3uVPsoHz;nT-4YR)t^KO^&l?5Q&Ig#l!;DaRM~<>sBtSw zPI`{?~v4|snKQ2NEX&hzd2eA#`LuvODuEA;!&N|$NkK-FC6aEt= zB9(Nq1Xtin+>I^xA<|DlU8Nuc)Db88RBb4ye>*ZKbr5AshA@Q}k?mE>wNi7i2W2n! z;0pW{<@xKF!+Q2BiAPZSzk$q6RrBs{miNDzf;@N#Wh>5M5z1_5lO;*$88>*3r7rDT z$q$lc@{%gaJ!DOmf!fKk^4pV4^!C)i_`z39Le@!U8-pYv<@*!7j&eZxI0mUCvI6B` zZXgrDAk+}-vFxiPIUlm1MN%PcB=czrwsDMHAQhH|28S*x2Kz6E=k~OQ$||zF-*TYj zZHfLxs1C}qr;=oAmXRgIl1f8@56{}DEay$Ob{uc0dVs=1(Ty(bCiA~0__WGNl|7dI zEGNssD<-cdFDJ{nm@ra4wr@;D*Vc`_I%N*%gq1d9eqZUkHR~MH@T}}EZDlRbF)|5P z@3p+7|5a(df1|W-dV99t8OV8NTsyYyao07yd`_E=V>^C#*|Sred{*akalbqYq(+a{oD#0#?)rV z?l)amZ!nl{+`l^Uxt1;AByxu1S)OHQwY1lktAnNO%zHX(>zv`bxuj#brcT)TY&@oV zyE^>i6K0IOR6eD2e$dp&8cEM^bli3a40m)`4;Z=8;WTp@9d;;;4iDH)%zvl)O4+8H zEAXwF`l1fsuF223aLh_LX4=eVtP4Z`#U_<^^67j=Ck;>f^e@*OsQrIzbkdBQ3C|qq zsQsY0Aqdf}0m7AQx=foHOBUzn>KmH$MmxjOg2uN3q^-CWQ==aRjrCgN!jQqt8TTpw zx4PrYqfo^yH>G!;Kbby%CUgEw7%z#y0-Z2YhDWd*J8kHlOgw9343, 2019\n" "Language-Team: Turkish (Turkey) (https://www.transifex.com/calamares/teams/20061/tr_TR/)\n" @@ -35,8 +35,7 @@ msgstr "Disk bölümleri bağlanıyor." #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -45,7 +44,7 @@ msgstr "Yapılandırma Hatası" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "
{!s}
kullanması için hiçbir bölüm tanımlanmadı." @@ -215,22 +214,6 @@ msgstr "Mkinitcpio yapılandırılıyor." msgid "No root mount point is given for
{!s}
to use." msgstr "
{!s}
kullanması için kök bağlama noktası verilmedi." -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "Mkinitcpio ile initramfs oluşturuluyor." - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "İşlem Başarısız" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" -"
Mkinitcpio
işlemi {!s} hata koduyla başarısız oldu. Komut " -"
{!s}
idi." - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "Şifreli takas alanı yapılandırılıyor." @@ -325,18 +308,6 @@ msgstr "Önyükleyici kur." msgid "Remove live user from target system" msgstr "Liveuser kullanıcısını hedef sistemden kaldırın" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "Initramfs oluşturuluyor." - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "update-initramfs hedefte çalıştırılamadı" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "Çıkış kodu {} idi" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "Donanım saati ayarlanıyor." @@ -349,6 +320,10 @@ msgstr "Dracut ile initramfs oluşturuluyor." msgid "Failed to run dracut on the target" msgstr "Hedef üzerinde dracut çalıştırılamadı" +#: src/modules/dracut/main.py:59 +msgid "The exit code was {}" +msgstr "Çıkış kodu {} idi" + #: src/modules/initramfscfg/main.py:41 msgid "Configuring initramfs." msgstr "Initramfs yapılandırılıyor." @@ -357,18 +332,6 @@ msgstr "Initramfs yapılandırılıyor." msgid "Configuring OpenRC dmcrypt service." msgstr "OpenRC dmcrypt servisi yapılandırılıyor." -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "LUKS anahtar dosyası yapılandırılıyor." - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "Şifrelenmiş rootfs kurulum hatası" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "Rootfs disk bölümü {!s} LUKS, fakat parola bulunamadı." - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "Fstab dosyasına yazılıyor." diff --git a/lang/python/uk/LC_MESSAGES/python.po b/lang/python/uk/LC_MESSAGES/python.po index 47033db11..98788d9c3 100644 --- a/lang/python/uk/LC_MESSAGES/python.po +++ b/lang/python/uk/LC_MESSAGES/python.po @@ -12,7 +12,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: Paul S , 2019\n" "Language-Team: Ukrainian (https://www.transifex.com/calamares/teams/20061/uk/)\n" @@ -36,8 +36,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -46,7 +45,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -214,20 +213,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -322,18 +307,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -346,6 +319,10 @@ msgstr "" 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 "" @@ -354,18 +331,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/ur/LC_MESSAGES/python.po b/lang/python/ur/LC_MESSAGES/python.po index b4415d41c..48d98d4dd 100644 --- a/lang/python/ur/LC_MESSAGES/python.po +++ b/lang/python/ur/LC_MESSAGES/python.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Language-Team: Urdu (https://www.transifex.com/calamares/teams/20061/ur/)\n" "MIME-Version: 1.0\n" @@ -31,8 +31,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -41,7 +40,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -203,20 +202,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -307,18 +292,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -331,6 +304,10 @@ msgstr "" 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 "" @@ -339,18 +316,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/uz/LC_MESSAGES/python.po b/lang/python/uz/LC_MESSAGES/python.po index 415882529..f174f0ce5 100644 --- a/lang/python/uz/LC_MESSAGES/python.po +++ b/lang/python/uz/LC_MESSAGES/python.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Language-Team: Uzbek (https://www.transifex.com/calamares/teams/20061/uz/)\n" "MIME-Version: 1.0\n" @@ -31,8 +31,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -41,7 +40,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -203,20 +202,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -305,18 +290,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -329,6 +302,10 @@ msgstr "" 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 "" @@ -337,18 +314,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/zh_CN/LC_MESSAGES/python.po b/lang/python/zh_CN/LC_MESSAGES/python.po index eae99810e..a7760096f 100644 --- a/lang/python/zh_CN/LC_MESSAGES/python.po +++ b/lang/python/zh_CN/LC_MESSAGES/python.po @@ -13,7 +13,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" "Last-Translator: leonfeng , 2018\n" "Language-Team: Chinese (China) (https://www.transifex.com/calamares/teams/20061/zh_CN/)\n" @@ -37,8 +37,7 @@ msgstr "" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -47,7 +46,7 @@ msgstr "" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "" @@ -209,20 +208,6 @@ msgstr "" msgid "No root mount point is given for
{!s}
to use." msgstr "" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "" @@ -311,18 +296,6 @@ msgstr "" msgid "Remove live user from target system" msgstr "" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "" @@ -335,6 +308,10 @@ msgstr "" 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 "" @@ -343,18 +320,6 @@ msgstr "" msgid "Configuring OpenRC dmcrypt service." msgstr "" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "" diff --git a/lang/python/zh_TW/LC_MESSAGES/python.mo b/lang/python/zh_TW/LC_MESSAGES/python.mo index 54b7a355585c281bfcaf9bc10458be67288a2633..d1525888b32a169961de94b675a464fd98291d78 100644 GIT binary patch delta 1646 zcmYk+Sx8h-9LMp0GgCU2=B|^Cj#*~5y0w@sQ`tzOLPeJOVD;cj5EVhTFaz}v(aI(A zAzJJqLMm{2%9lbSiUND7FbF2F1>c2;pzrU_4LZz!KIh!!-2YkbO+-hV<6rUvH;fV^ z<`cVpW(V+6fImv^EVCV$=h=%3Xg|Pt_y!wr5=$|ZVb+NCp8crvw{RtnV-Z@W*;=!> z6;r9A-GvMBI4;IPul*bgXiwr?{DmP52Gb9$LM76I>Zcpa@H7_VO)SL6Sb}3%fuC_1 z&$r)H@;FeFmAJQtPT#)(b7?oCW}p?7&?(fwZleY^ zhPr)@*nxG-^Ae2XUVMms=wosz;~64tW!!}7pdGt$0ND=q9<>=$ z*oHIdB#ND=2VBD*9Kl1FO}13+D5~GfxRK}EeJX1?@D=r5mXX#BQ*T&4OOLM)!33Ex^Ht}D13cBU$nWyC6CyBc1pMn6$Yus_{paA%a6cXugoo%8#yO|LjDva88xa8Ok}8+%>m85d1lM?%SQKKZc(ruNJHhINwVi aITNKFPFtuyIT6bBIeX`yNM?pl`u_qSkCnXu delta 2369 zcmZwIdr(wW9Ki9TkP3)~DT-Mfw9rbC6w!ppcZwz^rH(b_1`F&cyW8ExN7gJl1wNo; zE@q;mp)@f%f{LRAiP=BZG}cTr^#?QcNABH+{?k9@IMY<$-`;E5;|ym%=bU@*dHl|~ zm;U+n3qwDRNj|7ZW#mcZ)}cym#*z2&L+Tx-R4IPqm^@sm$<)hmA{sawn{fhO#R433 z96iFmz658|z8%M5C(ctUqy{KVq2U%jf)A!BH5C`2)NAkoY{t>pj#+pPWx%gdCK7i1 z6Q#e2sq}>rFgUmc?$4-B9T^fOM!-!KEGq}dP7L5WZ)uElDUNc5rH z|0BwPsUz(Ha#02>LFu;~rN3&tA9r8@PxW*D=-I- z;~cz-gi_tYmoR^nQv9hVexAT1DE)td`FIlxaT4JS$$;e)WPt4`p?M!4#xAG*8WvN( zi7(?crY|dd2WMa#mf@H998O@Fk6{&Vzyr7m<0yMyI>w&hrZL2S2@O6PWMvmn<1e^t z2;m}b>#3WJCf-Du=wf=2GvGp5`A(DxUBCkT%JC1!*&Kk`wAUbAtD`8-b!QTPIXp2M zWbcw#zN|bOrCx&UhT4ckO;w`|v=wxZCYpnCUlGc9&!cSd zmJkKmqgIp~KSPF5Bi#{uLVs!YNpr#csxV<|2~6J?<9aUMh${39)-_6%9xZ#hVE=$wBMY6WH4 zQ%Mq9i6*<0NPLYGDWBg(PB{-{%ZE$TTne&(l2(ydllfnh__Xr9P`PAzRno~b$^3s( z3&>BAGtAYgyT%%IUR~#}bOqfr{_djZ zVrucwOkM0Z+$FV}rMbfI@fFXMx;ZK%s~{)vR-S&L#;q%SwY4s9rQYTW*thTGl6_;I zT4VSs+<|~z=3=^)=8ciN=dZOV;ddE9PtfD@YPnx~0y?p@*Xn}W>(hQ$AmFbtTmiSP z^3{1O^Hlk&6=r+dw_k5gDm^?P|XuPo{-f}i_sx{KS=X(8a z^V@O#vm$3sT1Pv>m#;)yJN4alXsf?3dV2reh;hHN?=`n(y0mraytVH`tGglE_V%5q z#X8SeU2XBE?%1gg^M}luDRdk?(iQ1E9PZs`9lsQ7Z~AW(3&&3w8j2l07(LJs?c8tm zz4!kS)mHDtSj!>1^Kk#k=!sA5uvi`EA_osKyGT=GxW6O1yYJsImYLfF*!Mciu$yB2 z$K$8XSF, YEAR. # # Translators: -# Jeff Huang , 2019 +# 黃柏諺 , 2019 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" +"POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" -"Last-Translator: Jeff Huang , 2019\n" +"Last-Translator: 黃柏諺 , 2019\n" "Language-Team: Chinese (Taiwan) (https://www.transifex.com/calamares/teams/20061/zh_TW/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -35,8 +35,7 @@ msgstr "正在掛載分割區。" #: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:171 #: src/modules/machineid/main.py:49 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/luksbootkeyfile/main.py:51 src/modules/fstab/main.py:312 +#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:312 #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" @@ -45,7 +44,7 @@ msgstr "設定錯誤" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 -#: src/modules/luksbootkeyfile/main.py:52 src/modules/fstab/main.py:313 +#: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." msgstr "沒有分割區被定義為
{!s}
以供使用。" @@ -209,20 +208,6 @@ msgstr "正在設定 mkinitcpio。" msgid "No root mount point is given for
{!s}
to use." msgstr "沒有給定的根掛載點
{!s}
以供使用。" -#: src/modules/initcpio/main.py:33 -msgid "Creating initramfs with mkinitcpio." -msgstr "正在使用 mkinitcpio 建立 initramfs。" - -#: src/modules/initcpio/main.py:47 -msgid "Process Failed" -msgstr "處理失敗" - -#: src/modules/initcpio/main.py:48 -msgid "" -"Process
mkinitcpio
failed with error code {!s}. The command was " -"
{!s}
." -msgstr "處理程序
mkinitcpio
帶著錯誤代碼 {!s} 失敗。指令為
{!s}
。" - #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." msgstr "正在設定已加密的 swap。" @@ -311,18 +296,6 @@ msgstr "安裝開機載入程式。" msgid "Remove live user from target system" msgstr "從目標系統移除 live 使用者" -#: src/modules/initramfs/main.py:35 -msgid "Creating initramfs." -msgstr "正在建立 initramfs。" - -#: src/modules/initramfs/main.py:49 -msgid "Failed to run update-initramfs on the target" -msgstr "在目標上執行 update-initramfs 失敗" - -#: src/modules/initramfs/main.py:50 src/modules/dracut/main.py:59 -msgid "The exit code was {}" -msgstr "結束碼為 {}" - #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." msgstr "正在設定硬體時鐘。" @@ -335,6 +308,10 @@ msgstr "正在使用 dracut 建立 initramfs。" msgid "Failed to run dracut on the target" msgstr "在目標上執行 dracut 失敗" +#: src/modules/dracut/main.py:59 +msgid "The exit code was {}" +msgstr "結束碼為 {}" + #: src/modules/initramfscfg/main.py:41 msgid "Configuring initramfs." msgstr "正在設定 initramfs。" @@ -343,18 +320,6 @@ msgstr "正在設定 initramfs。" msgid "Configuring OpenRC dmcrypt service." msgstr "正在設定 OpenRC dmcrypt 服務。" -#: src/modules/luksbootkeyfile/main.py:35 -msgid "Configuring LUKS key file." -msgstr "正在設定 LUKS 金鑰檔案。" - -#: src/modules/luksbootkeyfile/main.py:74 -msgid "Encrypted rootfs setup error" -msgstr "已加密的 rootfs 設定錯誤" - -#: src/modules/luksbootkeyfile/main.py:75 -msgid "Rootfs partition {!s} is LUKS but no passphrase found." -msgstr "Rootfs 分割區 {!s} 是 LUKS 但找不到通關密語。" - #: src/modules/fstab/main.py:38 msgid "Writing fstab." msgstr "正在寫入 fstab。" From 8a545941d484ea29b6e44b604477473293c79892 Mon Sep 17 00:00:00 2001 From: apt-ghetto Date: Mon, 29 Jul 2019 16:01:30 +0200 Subject: [PATCH 015/302] Remove flake8 errors Remove the flake8 errors. This commit does not change any behaviour. --- src/modules/fstab/main.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/modules/fstab/main.py b/src/modules/fstab/main.py index abbd3d524..f793c9b7f 100644 --- a/src/modules/fstab/main.py +++ b/src/modules/fstab/main.py @@ -162,7 +162,6 @@ class FstabGenerator(object): return None mapper_name = partition["luksMapperName"] - mount_point = partition["mountPoint"] luks_uuid = partition["luksUuid"] if not mapper_name or not luks_uuid: return None @@ -266,12 +265,12 @@ class FstabGenerator(object): self.root_is_ssd = is_ssd if filesystem == "btrfs" and "subvol" in partition: - options="subvol={},".format(partition["subvol"]) + options + options = "subvol={},".format(partition["subvol"]) + options if has_luks: - device="/dev/mapper/" + partition["luksMapperName"] + device = "/dev/mapper/" + partition["luksMapperName"] else: - device="UUID=" + partition["uuid"] + device = "UUID=" + partition["uuid"] return dict(device=device, mount_point=mount_point, @@ -308,13 +307,17 @@ def run(): root_mount_point = global_storage.value("rootMountPoint") if not partitions: - libcalamares.utils.warning("partitions is empty, {!s}".format(partitions)) + libcalamares.utils.warning("partitions is empty, {!s}" + .format(partitions)) return (_("Configuration Error"), - _("No partitions are defined for
{!s}
to use." ).format("fstab")) + _("No partitions are defined for
{!s}
to use.") + .format("fstab")) if not root_mount_point: - libcalamares.utils.warning("rootMountPoint is empty, {!s}".format(root_mount_point)) + libcalamares.utils.warning("rootMountPoint is empty, {!s}" + .format(root_mount_point)) return (_("Configuration Error"), - _("No root mount point is given for
{!s}
to use." ).format("fstab")) + _("No root mount point is given for
{!s}
to use.") + .format("fstab")) mount_options = conf["mountOptions"] ssd_extra_mount_options = conf.get("ssdExtraMountOptions", {}) From 0f5ff9a5174499e42a547a7f7813d508cfbcd05a Mon Sep 17 00:00:00 2001 From: apt-ghetto Date: Mon, 29 Jul 2019 16:06:52 +0200 Subject: [PATCH 016/302] Add possibility to set mount options for the ESP Added new configuration "efiMountOptions" to fstab.conf When generating the fstab entry for the ESP, take the mount options from the new configuration or fall back to "mountOptions". --- src/modules/fstab/fstab.conf | 5 +++++ src/modules/fstab/main.py | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/modules/fstab/fstab.conf b/src/modules/fstab/fstab.conf index 11adff2ed..06a935e3a 100644 --- a/src/modules/fstab/fstab.conf +++ b/src/modules/fstab/fstab.conf @@ -12,6 +12,11 @@ mountOptions: default: defaults,noatime btrfs: defaults,noatime,space_cache,autodefrag +# Mount options to use for the EFI System Partition. If not defined, it +# takes either the value of *vfat*, or if also missing, *default* from +# *mountOptions* +efiMountOptions: umask=0077 + # If a filesystem is on an SSD, add the following options. If a specific # filesystem is listed here, use those options, otherwise no additional # options are set (i.e. there is no *default* like in *mountOptions*). diff --git a/src/modules/fstab/main.py b/src/modules/fstab/main.py index f793c9b7f..4a696f46b 100644 --- a/src/modules/fstab/main.py +++ b/src/modules/fstab/main.py @@ -246,8 +246,8 @@ class FstabGenerator(object): if not mount_point: mount_point = "swap" - options = self.mount_options.get(filesystem, - self.mount_options["default"]) + options = self.get_mount_options(filesystem, mount_point) + if is_ssd: extra = self.ssd_extra_mount_options.get(filesystem) @@ -295,6 +295,16 @@ class FstabGenerator(object): if partition["mountPoint"]: mkdir_p(self.root_mount_point + partition["mountPoint"]) + def get_mount_options(self, filesystem, mount_point): + efiMountPoint = libcalamares.globalstorage.value("efiSystemPartition") + job_config = libcalamares.job.configuration + + if (mount_point == efiMountPoint and "efiMountOptions" in job_config): + return job_config["efiMountOptions"] + + return self.mount_options.get(filesystem, + self.mount_options["default"]) + def run(): """ Configures fstab. From fff86f1115346b8959a0b3069e7fa70e152287e5 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 30 Jul 2019 13:23:23 +0200 Subject: [PATCH 017/302] Changes: Credits for newly-merged patches --- CHANGES | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index a73684e6a..a3c14296c 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,8 @@ website will have to do for older versions. # 3.2.12 (unreleased) # This release contains contributions from (alphabetically by first name): + - Bill Auger + - embar ## Core ## From 8f7d183a0c1eaa5f4279a355f74f616d9c5f2a58 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 30 Jul 2019 14:41:42 +0200 Subject: [PATCH 018/302] libcalamaresui: don't always fail - The paste-branch was merged too soon. Now undoing the damage. --- src/libcalamaresui/ViewManager.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libcalamaresui/ViewManager.cpp b/src/libcalamaresui/ViewManager.cpp index b0f2b00a8..ae146d0bd 100644 --- a/src/libcalamaresui/ViewManager.cpp +++ b/src/libcalamaresui/ViewManager.cpp @@ -137,8 +137,6 @@ ViewManager::ViewManager( QObject* parent ) if (Calamares::Settings::instance()->disableCancel()) m_quit->setVisible( false ); - -onInstallationFailed("amessage","somedetails"); // TODO: remove this } From d49ddf6463ce51643b6cdfc6d32a4313f222cd59 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 30 Jul 2019 15:09:25 +0200 Subject: [PATCH 019/302] libcalamaresui: factor out the pastebin functionality - While called from the ViewManager (to post the debug log) this isn't really part of the ViewManager itself, so factor out the pasting code into its own file. --- src/libcalamaresui/CMakeLists.txt | 1 + src/libcalamaresui/ViewManager.cpp | 86 +++++--------------------- src/libcalamaresui/utils/Paste.cpp | 99 ++++++++++++++++++++++++++++++ src/libcalamaresui/utils/Paste.h | 30 +++++++++ 4 files changed, 144 insertions(+), 72 deletions(-) create mode 100644 src/libcalamaresui/utils/Paste.cpp create mode 100644 src/libcalamaresui/utils/Paste.h diff --git a/src/libcalamaresui/CMakeLists.txt b/src/libcalamaresui/CMakeLists.txt index f6c8c9ac7..703a8bbe1 100644 --- a/src/libcalamaresui/CMakeLists.txt +++ b/src/libcalamaresui/CMakeLists.txt @@ -16,6 +16,7 @@ set( calamaresui_SOURCES utils/CalamaresUtilsGui.cpp utils/DebugWindow.cpp utils/ImageRegistry.cpp + utils/Paste.cpp utils/qjsonmodel.cpp utils/qjsonitem.cpp diff --git a/src/libcalamaresui/ViewManager.cpp b/src/libcalamaresui/ViewManager.cpp index ae146d0bd..b1334ecfa 100644 --- a/src/libcalamaresui/ViewManager.cpp +++ b/src/libcalamaresui/ViewManager.cpp @@ -21,23 +21,23 @@ #include "ViewManager.h" -#include "utils/Logger.h" #include "viewpages/BlankViewStep.h" #include "viewpages/ViewStep.h" + +#include "Branding.h" #include "ExecutionViewStep.h" #include "JobQueue.h" -#include "utils/Retranslator.h" -#include "Branding.h" #include "Settings.h" +#include "utils/Logger.h" +#include "utils/Paste.h" +#include "utils/Retranslator.h" + #include #include #include #include #include -#include -#include -#include namespace Calamares { @@ -193,9 +193,7 @@ ViewManager::insertViewStep( int before, ViewStep* step ) void ViewManager::onInstallationFailed( const QString& message, const QString& details ) { -bool shouldOfferWebPaste = true; // TODO: config var -QString ficheHost = "termbin.com"; // TODO: config var -quint16 fichePort = 9999; // TODO: config var + bool shouldOfferWebPaste = true; // TODO: config var cError() << "Installation failed:"; cDebug() << "- message:" << message; @@ -205,8 +203,6 @@ quint16 fichePort = 9999; // TODO: config var ? tr( "Setup Failed" ) : tr( "Installation Failed" ); QString pasteMsg = tr( "Would you like to paste the install log to the web?" ); - QString pasteUrlFmt = tr( "Install log posted to:\n%1" ); - QString pasteUrlTitle = tr( "Install Log Paste URL" ); QString text = "

" + message + "

"; if ( !details.isEmpty() ) text += "

" + details + "

"; @@ -235,7 +231,7 @@ quint16 fichePort = 9999; // TODO: config var cDebug() << "Calamares will quit when the dialog closes."; connect( msgBox, &QMessageBox::buttonClicked, - [msgBox, ficheHost, fichePort, pasteUrlFmt, pasteUrlTitle] ( QAbstractButton* button ) + [msgBox] ( QAbstractButton* button ) { if ( button->text() != tr( "&Yes" ) ) { @@ -243,69 +239,15 @@ quint16 fichePort = 9999; // TODO: config var return; } - QFile pasteSourceFile( Logger::logFile() ); - if ( !pasteSourceFile.open( QIODevice::ReadOnly | QIODevice::Text ) ) + // TODO: host and port should be configurable + QString pasteUrlMsg = CalamaresUtils::pastebin( msgBox, QStringLiteral( "termbin.com" ), 9999 ); + + QString pasteUrlTitle = tr( "Install Log Paste URL" ); + if ( pasteUrlMsg.isEmpty() ) { - cError() << "Could not open log file"; - return; + pasteUrlMsg = tr( "The upload was unsuccessful. No web-paste was done." ); } - QByteArray pasteData; - while ( !pasteSourceFile.atEnd() ) - { - pasteData += pasteSourceFile.readLine(); - } - - QTcpSocket* socket = new QTcpSocket(msgBox); - socket->connectToHost( ficheHost, fichePort ); - - if ( !socket->waitForConnected() ) - { - cError() << "Could not connect to paste server"; - socket->close(); - return; - } - - cDebug() << "Connected to paste server"; - - socket->write( pasteData ); - - if ( !socket->waitForBytesWritten() ) - { - cError() << "Could not write to paste server"; - socket->close(); - return; - } - - cDebug() << "Paste data written to paste server"; - - if ( !socket->waitForReadyRead() ) - { - cError() << "No data from paste server"; - socket->close(); - return; - } - - cDebug() << "Reading response from paste server"; - - char resp[1024]; resp[0] = '\0'; - qint64 nBytesRead = socket->readLine(resp, 1024); - socket->close(); - - QUrl pasteUrl = QUrl( QString( resp ).trimmed(), QUrl::StrictMode ); - QString pasteUrlStr = pasteUrl.toString() ; - QRegularExpression pasteUrlRegex( "^http[s]?://" + ficheHost ); - QString pasteUrlMsg = QString( pasteUrlFmt ).arg( pasteUrlStr ); - - if ( nBytesRead < 8 || !pasteUrl.isValid() || - !pasteUrlRegex.match( pasteUrlStr ).hasMatch() ) - { - cError() << "No data from paste server"; - return; - } - - cDebug() << pasteUrlMsg; - QMessageBox* pasteUrlMsgBox = new QMessageBox(); pasteUrlMsgBox->setIcon( QMessageBox::Critical ); pasteUrlMsgBox->setWindowTitle( pasteUrlTitle ); diff --git a/src/libcalamaresui/utils/Paste.cpp b/src/libcalamaresui/utils/Paste.cpp new file mode 100644 index 000000000..7833d18d6 --- /dev/null +++ b/src/libcalamaresui/utils/Paste.cpp @@ -0,0 +1,99 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, Bill Auger + * + * 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 "Paste.h" + +#include "utils/Logger.h" + +#include +#include +#include +#include + +namespace CalamaresUtils +{ + +QString +pastebin( QObject* parent, const QString& ficheHost, int fichePort ) +{ + QString pasteUrlFmt = parent->tr( "Install log posted to:\n%1" ); + QFile pasteSourceFile( Logger::logFile() ); + if ( !pasteSourceFile.open( QIODevice::ReadOnly | QIODevice::Text ) ) + { + cError() << "Could not open log file"; + return QString(); + } + + QByteArray pasteData; + while ( !pasteSourceFile.atEnd() ) + { + pasteData += pasteSourceFile.readLine(); + } + + QTcpSocket* socket = new QTcpSocket( parent ); + socket->connectToHost( ficheHost, fichePort ); + + if ( !socket->waitForConnected() ) + { + cError() << "Could not connect to paste server"; + socket->close(); + return QString(); + } + + cDebug() << "Connected to paste server"; + + socket->write( pasteData ); + + if ( !socket->waitForBytesWritten() ) + { + cError() << "Could not write to paste server"; + socket->close(); + return QString(); + } + + cDebug() << "Paste data written to paste server"; + + if ( !socket->waitForReadyRead() ) + { + cError() << "No data from paste server"; + socket->close(); + return QString(); + } + + cDebug() << "Reading response from paste server"; + + char resp[ 1024 ]; + resp[ 0 ] = '\0'; + qint64 nBytesRead = socket->readLine( resp, 1024 ); + socket->close(); + + QUrl pasteUrl = QUrl( QString( resp ).trimmed(), QUrl::StrictMode ); + QString pasteUrlStr = pasteUrl.toString(); + QRegularExpression pasteUrlRegex( "^http[s]?://" + ficheHost ); + QString pasteUrlMsg = QString( pasteUrlFmt ).arg( pasteUrlStr ); + + if ( nBytesRead < 8 || !pasteUrl.isValid() || !pasteUrlRegex.match( pasteUrlStr ).hasMatch() ) + { + cError() << "No data from paste server"; + return QString(); + } + + cDebug() << "Paste server results:" << pasteUrlMsg; + return pasteUrlMsg; +} +} // namespace CalamaresUtils diff --git a/src/libcalamaresui/utils/Paste.h b/src/libcalamaresui/utils/Paste.h new file mode 100644 index 000000000..4def700fd --- /dev/null +++ b/src/libcalamaresui/utils/Paste.h @@ -0,0 +1,30 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, Bill Auger + * + * 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 UTILS_PASTE_H +#define UTILS_PASTE_H + +class QObject; +class QString; + +namespace CalamaresUtils +{ +QString pastebin( QObject* parent, const QString& ficheHost, int fichePort ); +} + +#endif From 630694b2425759c28123e997cbcf58f6950b8ae0 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 30 Jul 2019 15:12:05 +0200 Subject: [PATCH 020/302] libcalamaresui: apply coding style to viewmanager --- src/libcalamaresui/ViewManager.cpp | 155 ++++++++++++++++------------- src/libcalamaresui/ViewManager.h | 7 +- 2 files changed, 89 insertions(+), 73 deletions(-) diff --git a/src/libcalamaresui/ViewManager.cpp b/src/libcalamaresui/ViewManager.cpp index b1334ecfa..bb39f325a 100644 --- a/src/libcalamaresui/ViewManager.cpp +++ b/src/libcalamaresui/ViewManager.cpp @@ -112,9 +112,7 @@ ViewManager::ViewManager( QObject* parent ) m_next = makeButton( m_widget, "go-next" ); m_quit = makeButton( m_widget, "dialog-cancel" ); - CALAMARES_RETRANSLATE( - updateButtonLabels(); - ) + CALAMARES_RETRANSLATE( updateButtonLabels(); ) QBoxLayout* bottomLayout = new QHBoxLayout; mainLayout->addLayout( bottomLayout ); @@ -128,15 +126,19 @@ ViewManager::ViewManager( QObject* parent ) connect( m_back, &QPushButton::clicked, this, &ViewManager::back ); m_back->setEnabled( false ); - connect( m_quit, &QPushButton::clicked, this, - [this]() { if ( this->confirmCancelInstallation() ) qApp->quit(); } ); - connect( JobQueue::instance(), &JobQueue::failed, - this, &ViewManager::onInstallationFailed ); - connect( JobQueue::instance(), &JobQueue::finished, - this, &ViewManager::next ); + connect( m_quit, &QPushButton::clicked, this, [this]() { + if ( this->confirmCancelInstallation() ) + { + qApp->quit(); + } + } ); + connect( JobQueue::instance(), &JobQueue::failed, this, &ViewManager::onInstallationFailed ); + connect( JobQueue::instance(), &JobQueue::finished, this, &ViewManager::next ); - if (Calamares::Settings::instance()->disableCancel()) + if ( Calamares::Settings::instance()->disableCancel() ) + { m_quit->setVisible( false ); + } } @@ -160,7 +162,9 @@ ViewManager::addViewStep( ViewStep* step ) insertViewStep( m_steps.size(), step ); // If this is the first inserted view step, update status of "Next" button if ( m_steps.count() == 1 ) + { m_next->setEnabled( step->isNextEnabled() ); + } } @@ -170,18 +174,20 @@ ViewManager::insertViewStep( int before, ViewStep* step ) m_steps.insert( before, step ); QLayout* layout = step->widget()->layout(); if ( layout ) + { layout->setContentsMargins( 0, 0, 0, 0 ); + } m_stack->insertWidget( before, step->widget() ); connect( step, &ViewStep::enlarge, this, &ViewManager::enlarge ); - connect( step, &ViewStep::nextStatusChanged, - this, [this]( bool status ) - { + connect( step, &ViewStep::nextStatusChanged, this, [this]( bool status ) { ViewStep* vs = qobject_cast< ViewStep* >( sender() ); if ( vs ) { if ( vs == m_steps.at( m_currentStep ) ) + { m_next->setEnabled( status ); + } } } ); @@ -193,21 +199,24 @@ ViewManager::insertViewStep( int before, ViewStep* step ) void ViewManager::onInstallationFailed( const QString& message, const QString& details ) { - bool shouldOfferWebPaste = true; // TODO: config var + bool shouldOfferWebPaste = true; // TODO: config var cError() << "Installation failed:"; cDebug() << "- message:" << message; cDebug() << "- details:" << details; - QString heading = Calamares::Settings::instance()->isSetupMode() - ? tr( "Setup Failed" ) - : tr( "Installation Failed" ); + QString heading + = Calamares::Settings::instance()->isSetupMode() ? tr( "Setup Failed" ) : tr( "Installation Failed" ); QString pasteMsg = tr( "Would you like to paste the install log to the web?" ); QString text = "

" + message + "

"; if ( !details.isEmpty() ) + { text += "

" + details + "

"; + } if ( shouldOfferWebPaste ) + { text += "

" + pasteMsg + "

"; + } QMessageBox* msgBox = new QMessageBox(); msgBox->setIcon( QMessageBox::Critical ); @@ -230,9 +239,7 @@ ViewManager::onInstallationFailed( const QString& message, const QString& detail msgBox->show(); cDebug() << "Calamares will quit when the dialog closes."; - connect( msgBox, &QMessageBox::buttonClicked, - [msgBox] ( QAbstractButton* button ) - { + connect( msgBox, &QMessageBox::buttonClicked, [msgBox]( QAbstractButton* button ) { if ( button->text() != tr( "&Yes" ) ) { QApplication::quit(); @@ -250,33 +257,36 @@ ViewManager::onInstallationFailed( const QString& message, const QString& detail QMessageBox* pasteUrlMsgBox = new QMessageBox(); pasteUrlMsgBox->setIcon( QMessageBox::Critical ); - pasteUrlMsgBox->setWindowTitle( pasteUrlTitle ); + pasteUrlMsgBox->setWindowTitle( pasteUrlTitle ); pasteUrlMsgBox->setStandardButtons( QMessageBox::Close ); pasteUrlMsgBox->setText( pasteUrlMsg ); pasteUrlMsgBox->show(); connect( pasteUrlMsgBox, &QMessageBox::buttonClicked, qApp, &QApplication::quit ); - }); + } ); } void -ViewManager::onInitFailed( const QStringList& modules) +ViewManager::onInitFailed( const QStringList& modules ) { // Because this means the installer / setup program is broken by the distributor, // don't bother being precise about installer / setup wording. QString title( tr( "Calamares Initialization Failed" ) ); - QString description( tr( "%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." ) ); + QString description( tr( "%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." ) ); QString detailString; if ( modules.count() > 0 ) { description.append( tr( "
The following modules could not be loaded:" ) ); QStringList details; - details << QLatin1Literal("
    "); - for( const auto& m : modules ) - details << QLatin1Literal("
  • ") << m << QLatin1Literal("
  • "); - details << QLatin1Literal("
"); + details << QLatin1Literal( "
    " ); + for ( const auto& m : modules ) + { + details << QLatin1Literal( "
  • " ) << m << QLatin1Literal( "
  • " ); + } + details << QLatin1Literal( "
" ); detailString = details.join( QString() ); } @@ -311,10 +321,8 @@ ViewManager::currentStepIndex() const static inline bool stepIsExecute( const ViewStepList& steps, int index ) { - return - ( 0 <= index ) && - ( index < steps.count() ) && - ( qobject_cast< ExecutionViewStep* >( steps.at( index ) ) != nullptr ); + return ( 0 <= index ) && ( index < steps.count() ) + && ( qobject_cast< ExecutionViewStep* >( steps.at( index ) ) != nullptr ); } void @@ -329,11 +337,10 @@ ViewManager::next() // Special case when the user clicks next on the very last page in a view phase // and right before switching to an execution phase. // Depending on Calamares::Settings, we show an "are you sure" prompt or not. - if ( settings->showPromptBeforeExecution() && stepIsExecute( m_steps, m_currentStep+1 ) ) + if ( settings->showPromptBeforeExecution() && stepIsExecute( m_steps, m_currentStep + 1 ) ) { - QString title = settings->isSetupMode() - ? tr( "Continue with setup?" ) - : tr( "Continue with installation?" ); + QString title + = settings->isSetupMode() ? tr( "Continue with setup?" ) : tr( "Continue with installation?" ); QString question = settings->isSetupMode() ? tr( "The %1 setup program is about to make changes to your " "disk in order to set up %2.
You will not be able " @@ -341,21 +348,21 @@ ViewManager::next() : tr( "The %1 installer is about to make changes to your " "disk in order to install %2.
You will not be able " "to undo these changes." ); - QString confirm = settings->isSetupMode() - ? tr( "&Set up now" ) - : tr( "&Install now" ); + QString confirm = settings->isSetupMode() ? tr( "&Set up now" ) : tr( "&Install now" ); - int reply = - QMessageBox::question( m_widget, - title, - question.arg( *Calamares::Branding::ShortProductName, *Calamares::Branding::ShortVersionedName ), - confirm, - tr( "Go &back" ), - QString(), - 0, - 1 ); + int reply = QMessageBox::question( + m_widget, + title, + question.arg( *Calamares::Branding::ShortProductName, *Calamares::Branding::ShortVersionedName ), + confirm, + tr( "Go &back" ), + QString(), + 0, + 1 ); if ( reply == 1 ) + { return; + } } m_currentStep++; @@ -376,7 +383,7 @@ ViewManager::next() m_next->setEnabled( false ); m_back->setEnabled( false ); } - updateCancelEnabled( !settings->disableCancel() && !(executing && settings->disableCancelDuringExec() ) ); + updateCancelEnabled( !settings->disableCancel() && !( executing && settings->disableCancelDuringExec() ) ); } else { @@ -397,9 +404,7 @@ ViewManager::updateButtonLabels() { const auto* const settings = Calamares::Settings::instance(); - QString nextIsInstallationStep = settings->isSetupMode() - ? tr( "&Set up" ) - : tr( "&Install" ); + QString nextIsInstallationStep = settings->isSetupMode() ? tr( "&Set up" ) : tr( "&Install" ); QString quitOnCompleteTooltip = settings->isSetupMode() ? tr( "Setup is complete. Close the setup program." ) : tr( "The installation is complete. Close the installer." ); @@ -408,7 +413,7 @@ ViewManager::updateButtonLabels() : tr( "Cancel installation without changing the system." ); // If we're going into the execution step / install phase, other message - if ( stepIsExecute( m_steps, m_currentStep+1 ) ) + if ( stepIsExecute( m_steps, m_currentStep + 1 ) ) { m_next->setText( nextIsInstallationStep ); setButtonIcon( m_next, "run-install" ); @@ -434,8 +439,11 @@ ViewManager::updateButtonLabels() else { if ( settings->disableCancel() ) + { m_quit->setVisible( false ); // In case we went back from final - updateCancelEnabled( !settings->disableCancel() && !( stepIsExecute( m_steps, m_currentStep ) && settings->disableCancelDuringExec() ) ); + } + updateCancelEnabled( !settings->disableCancel() + && !( stepIsExecute( m_steps, m_currentStep ) && settings->disableCancelDuringExec() ) ); m_quit->setText( tr( "&Cancel" ) ); m_quit->setToolTip( cancelBeforeInstallationTooltip ); @@ -456,46 +464,53 @@ ViewManager::back() emit currentStepChanged(); } else if ( !step->isAtBeginning() ) + { step->back(); - else return; + } + else + { + return; + } m_next->setEnabled( m_steps.at( m_currentStep )->isNextEnabled() ); m_back->setEnabled( m_steps.at( m_currentStep )->isBackEnabled() ); if ( m_currentStep == 0 && m_steps.first()->isAtBeginning() ) + { m_back->setEnabled( false ); + } updateButtonLabels(); } -bool ViewManager::confirmCancelInstallation() +bool +ViewManager::confirmCancelInstallation() { const auto* const settings = Calamares::Settings::instance(); // When we're at the very end, then it's always OK to exit. if ( isAtVeryEnd() ) + { return true; + } // Not at the very end, cancel/quit might be disabled if ( settings->disableCancel() ) + { return false; + } if ( settings->disableCancelDuringExec() && stepIsExecute( m_steps, m_currentStep ) ) + { return false; + } // Otherwise, confirm cancel/quit. - QString title = settings->isSetupMode() - ? tr( "Cancel setup?" ) - : tr( "Cancel installation?" ); - QString question = settings->isSetupMode() - ? tr( "Do you really want to cancel the current setup process?\n" - "The setup program will quit and all changes will be lost." ) - : tr( "Do you really want to cancel the current install process?\n" - "The installer will quit and all changes will be lost." ); - QMessageBox mb( QMessageBox::Question, - title, - question, - QMessageBox::Yes | QMessageBox::No, - m_widget ); + QString title = settings->isSetupMode() ? tr( "Cancel setup?" ) : tr( "Cancel installation?" ); + QString question = settings->isSetupMode() ? tr( "Do you really want to cancel the current setup process?\n" + "The setup program will quit and all changes will be lost." ) + : tr( "Do you really want to cancel the current install process?\n" + "The installer will quit and all changes will be lost." ); + QMessageBox mb( QMessageBox::Question, title, question, QMessageBox::Yes | QMessageBox::No, m_widget ); mb.setDefaultButton( QMessageBox::No ); mb.button( QMessageBox::Yes )->setText( tr( "&Yes" ) ); mb.button( QMessageBox::No )->setText( tr( "&No" ) ); @@ -510,4 +525,4 @@ ViewManager::updateCancelEnabled( bool enabled ) emit cancelEnabled( enabled ); } -} // namespace +} // namespace Calamares diff --git a/src/libcalamaresui/ViewManager.h b/src/libcalamaresui/ViewManager.h index c9f554ee8..fca74a367 100644 --- a/src/libcalamaresui/ViewManager.h +++ b/src/libcalamaresui/ViewManager.h @@ -133,7 +133,8 @@ private: bool isAtVeryEnd() const { - return ( m_currentStep >= m_steps.count() ) || ( m_currentStep == m_steps.count() - 1 && m_steps.last()->isAtEnd() ); + return ( m_currentStep >= m_steps.count() ) + || ( m_currentStep == m_steps.count() - 1 && m_steps.last()->isAtEnd() ); } static ViewManager* s_instance; @@ -148,6 +149,6 @@ private: QPushButton* m_quit; }; -} +} // namespace Calamares -#endif // VIEWMANAGER_H +#endif // VIEWMANAGER_H From fac9ccde888e231b718fad6d0f6a27363c69047a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 30 Jul 2019 15:15:41 +0200 Subject: [PATCH 021/302] libcalamaresui: document magic constants in question() --- src/libcalamaresui/ViewManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcalamaresui/ViewManager.cpp b/src/libcalamaresui/ViewManager.cpp index bb39f325a..d9a03fee6 100644 --- a/src/libcalamaresui/ViewManager.cpp +++ b/src/libcalamaresui/ViewManager.cpp @@ -357,8 +357,8 @@ ViewManager::next() confirm, tr( "Go &back" ), QString(), - 0, - 1 ); + 0 /* default first button, i.e. confirm */, + 1 /* escape is second button, i.e. cancel */ ); if ( reply == 1 ) { return; From 675a35bb2e925c62a141cdaa9177537af8d83f99 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 30 Jul 2019 15:28:17 +0200 Subject: [PATCH 022/302] libcalamaresui: when displaying pasted URL, don't be fancy - Just call the static method and then quit, rather than being careful about allocations. --- src/libcalamaresui/ViewManager.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/libcalamaresui/ViewManager.cpp b/src/libcalamaresui/ViewManager.cpp index d9a03fee6..5b932e6d4 100644 --- a/src/libcalamaresui/ViewManager.cpp +++ b/src/libcalamaresui/ViewManager.cpp @@ -239,7 +239,9 @@ ViewManager::onInstallationFailed( const QString& message, const QString& detail msgBox->show(); cDebug() << "Calamares will quit when the dialog closes."; - connect( msgBox, &QMessageBox::buttonClicked, [msgBox]( QAbstractButton* button ) { + connect( msgBox, &QMessageBox::buttonClicked, [this,msgBox]( QAbstractButton* button ) { + cDebug() << "Button role:" << msgBox->buttonRole( button ); + if ( button->text() != tr( "&Yes" ) ) { QApplication::quit(); @@ -255,14 +257,10 @@ ViewManager::onInstallationFailed( const QString& message, const QString& detail pasteUrlMsg = tr( "The upload was unsuccessful. No web-paste was done." ); } - QMessageBox* pasteUrlMsgBox = new QMessageBox(); - pasteUrlMsgBox->setIcon( QMessageBox::Critical ); - pasteUrlMsgBox->setWindowTitle( pasteUrlTitle ); - pasteUrlMsgBox->setStandardButtons( QMessageBox::Close ); - pasteUrlMsgBox->setText( pasteUrlMsg ); - pasteUrlMsgBox->show(); - - connect( pasteUrlMsgBox, &QMessageBox::buttonClicked, qApp, &QApplication::quit ); + QMessageBox::critical(nullptr, + pasteUrlTitle, + pasteUrlMsg); + QApplication::quit(); } ); } From 2aae30f51728ff9c78f4317c52da2f82dba11391 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 30 Jul 2019 15:43:20 +0200 Subject: [PATCH 023/302] libcalamaresui: don't rely on translations to interpret button - Keep the debug-failure-call in the code, but commented out - Check ButtonRole, rather than the button's text, to see which one it is. --- src/libcalamaresui/ViewManager.cpp | 35 ++++++++++++++---------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/src/libcalamaresui/ViewManager.cpp b/src/libcalamaresui/ViewManager.cpp index 5b932e6d4..4b1842bfc 100644 --- a/src/libcalamaresui/ViewManager.cpp +++ b/src/libcalamaresui/ViewManager.cpp @@ -139,6 +139,8 @@ ViewManager::ViewManager( QObject* parent ) { m_quit->setVisible( false ); } + + // onInstallationFailed( "Tile of Failure", "Body of Failure"); // for testing paste functionality } @@ -199,7 +201,7 @@ ViewManager::insertViewStep( int before, ViewStep* step ) void ViewManager::onInstallationFailed( const QString& message, const QString& details ) { - bool shouldOfferWebPaste = true; // TODO: config var + bool shouldOfferWebPaste = false; // TODO: config var cError() << "Installation failed:"; cDebug() << "- message:" << message; @@ -240,26 +242,21 @@ ViewManager::onInstallationFailed( const QString& message, const QString& detail cDebug() << "Calamares will quit when the dialog closes."; connect( msgBox, &QMessageBox::buttonClicked, [this,msgBox]( QAbstractButton* button ) { - cDebug() << "Button role:" << msgBox->buttonRole( button ); - - if ( button->text() != tr( "&Yes" ) ) + if ( msgBox->buttonRole( button ) == QMessageBox::ButtonRole::YesRole ) { - QApplication::quit(); - return; + // TODO: host and port should be configurable + QString pasteUrlMsg = CalamaresUtils::pastebin( msgBox, QStringLiteral( "termbin.com" ), 9999 ); + + QString pasteUrlTitle = tr( "Install Log Paste URL" ); + if ( pasteUrlMsg.isEmpty() ) + { + pasteUrlMsg = tr( "The upload was unsuccessful. No web-paste was done." ); + } + + QMessageBox::critical(nullptr, + pasteUrlTitle, + pasteUrlMsg); } - - // TODO: host and port should be configurable - QString pasteUrlMsg = CalamaresUtils::pastebin( msgBox, QStringLiteral( "termbin.com" ), 9999 ); - - QString pasteUrlTitle = tr( "Install Log Paste URL" ); - if ( pasteUrlMsg.isEmpty() ) - { - pasteUrlMsg = tr( "The upload was unsuccessful. No web-paste was done." ); - } - - QMessageBox::critical(nullptr, - pasteUrlTitle, - pasteUrlMsg); QApplication::quit(); } ); } From 566be48f1601b8ecec604dfc808ef9d041adce47 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 30 Jul 2019 15:46:37 +0200 Subject: [PATCH 024/302] libcalamaresui: rename and document pastebin method --- src/libcalamaresui/ViewManager.cpp | 3 ++- src/libcalamaresui/utils/Paste.cpp | 2 +- src/libcalamaresui/utils/Paste.h | 10 ++++++++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/libcalamaresui/ViewManager.cpp b/src/libcalamaresui/ViewManager.cpp index 4b1842bfc..b27b36f80 100644 --- a/src/libcalamaresui/ViewManager.cpp +++ b/src/libcalamaresui/ViewManager.cpp @@ -245,7 +245,7 @@ ViewManager::onInstallationFailed( const QString& message, const QString& detail if ( msgBox->buttonRole( button ) == QMessageBox::ButtonRole::YesRole ) { // TODO: host and port should be configurable - QString pasteUrlMsg = CalamaresUtils::pastebin( msgBox, QStringLiteral( "termbin.com" ), 9999 ); + QString pasteUrlMsg = CalamaresUtils::sendLogToPastebin( msgBox, QStringLiteral( "termbin.com" ), 9999 ); QString pasteUrlTitle = tr( "Install Log Paste URL" ); if ( pasteUrlMsg.isEmpty() ) @@ -253,6 +253,7 @@ ViewManager::onInstallationFailed( const QString& message, const QString& detail pasteUrlMsg = tr( "The upload was unsuccessful. No web-paste was done." ); } + // TODO: make the URL clickable, or copy it to the clipboard automatically QMessageBox::critical(nullptr, pasteUrlTitle, pasteUrlMsg); diff --git a/src/libcalamaresui/utils/Paste.cpp b/src/libcalamaresui/utils/Paste.cpp index 7833d18d6..6fead59e6 100644 --- a/src/libcalamaresui/utils/Paste.cpp +++ b/src/libcalamaresui/utils/Paste.cpp @@ -29,7 +29,7 @@ namespace CalamaresUtils { QString -pastebin( QObject* parent, const QString& ficheHost, int fichePort ) +sendLogToPastebin( QObject* parent, const QString& ficheHost, int fichePort ) { QString pasteUrlFmt = parent->tr( "Install log posted to:\n%1" ); QFile pasteSourceFile( Logger::logFile() ); diff --git a/src/libcalamaresui/utils/Paste.h b/src/libcalamaresui/utils/Paste.h index 4def700fd..2ac77f2f3 100644 --- a/src/libcalamaresui/utils/Paste.h +++ b/src/libcalamaresui/utils/Paste.h @@ -24,7 +24,13 @@ class QString; namespace CalamaresUtils { -QString pastebin( QObject* parent, const QString& ficheHost, int fichePort ); -} + +/** @brief Send the current log file to a pastebin + * + * Returns the (string) URL that the pastebin gives us. + */ +QString sendLogToPastebin( QObject* parent, const QString& ficheHost, int fichePort ); + +} // namespace CalamaresUtils #endif From 58de7cea94f35c991d37b01f49c9bc4693818a9c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 5 Mar 2018 13:36:16 +0100 Subject: [PATCH 025/302] [calamares] Allow test-loading of View modules The view modules need a QApplication, not just a core application, and a ViewManager instance, so create those before really loading the module. --- src/calamares/testmain.cpp | 39 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/calamares/testmain.cpp b/src/calamares/testmain.cpp index 0f07e6e13..5671a591e 100644 --- a/src/calamares/testmain.cpp +++ b/src/calamares/testmain.cpp @@ -30,7 +30,9 @@ #include "Job.h" #include "JobQueue.h" #include "Settings.h" +#include "ViewManager.h" +#include #include #include #include @@ -40,26 +42,10 @@ struct ModuleConfig { - QString - moduleName() const - { - return m_module; - } - QString - configFile() const - { - return m_jobConfig; - } - QString - language() const - { - return m_language; - } - QString - globalConfigFile() const - { - return m_globalConfig; - } + QString moduleName() const { return m_module; } + QString configFile() const { return m_jobConfig; } + QString language() const { return m_language; } + QString globalConfigFile() const { return m_globalConfig; } QString m_module; QString m_jobConfig; @@ -202,6 +188,7 @@ int main( int argc, char* argv[] ) { QCoreApplication a( argc, argv ); + QApplication* aw = nullptr; ModuleConfig module = handle_args( a ); if ( module.moduleName().isEmpty() ) @@ -233,6 +220,13 @@ main( int argc, char* argv[] ) return 1; } + cDebug() << " .. got" << m->name() << m->typeString() << m->interfaceString(); + if ( m->type() == Calamares::Module::Type::View ) + { + aw = new QApplication( argc, argv ); + (void)Calamares::ViewManager::instance( nullptr ); + } + if ( !m->isLoaded() ) { m->loadSelf(); @@ -268,5 +262,10 @@ main( int argc, char* argv[] ) ++count; } + if ( aw ) + { + delete aw; + } + return failure_count ? 1 : 0; } From 20cf0c8f3da81b362679b3ebe835275f77fd4645 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 7 Aug 2018 14:50:29 -0400 Subject: [PATCH 026/302] [libcalamaresui] Remove unused code - This operator is declared, yet never defined or used. The definition was removed in fb44fb97b6. --- src/libcalamaresui/modulesystem/Module.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/libcalamaresui/modulesystem/Module.h b/src/libcalamaresui/modulesystem/Module.h index ae3b31e6d..e4101b767 100644 --- a/src/libcalamaresui/modulesystem/Module.h +++ b/src/libcalamaresui/modulesystem/Module.h @@ -28,13 +28,6 @@ #include -namespace Calamares -{ -class Module; -} - -void operator>>( const QVariantMap& moduleDescriptor, Calamares::Module* m ); - namespace Calamares { @@ -193,8 +186,6 @@ private: QString m_name; QString m_directory; QString m_instanceId; - - friend void ::operator>>( const QVariantMap& moduleDescriptor, Calamares::Module* m ); }; } // namespace Calamares From c19ce26e5ff78dea9db76b19679a7814e355ae22 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 2 Jul 2018 06:11:57 -0400 Subject: [PATCH 027/302] [libcalamares] Expand GlobalStorage with load() - Counterpart to save(), for JSON-style dumps --- src/libcalamares/GlobalStorage.cpp | 27 +++++++++++++++++++++++++++ src/libcalamares/GlobalStorage.h | 8 ++++++++ 2 files changed, 35 insertions(+) diff --git a/src/libcalamares/GlobalStorage.cpp b/src/libcalamares/GlobalStorage.cpp index 73236a311..99be39246 100644 --- a/src/libcalamares/GlobalStorage.cpp +++ b/src/libcalamares/GlobalStorage.cpp @@ -22,6 +22,7 @@ #include "utils/Logger.h" #include "utils/Yaml.h" +#include "utils/Units.h" #include #include @@ -37,6 +38,8 @@ namespace bp = boost::python; #endif +using CalamaresUtils::operator""_MiB; + namespace Calamares { GlobalStorage::GlobalStorage() @@ -110,6 +113,30 @@ GlobalStorage::save(const QString& filename) return true; } +bool +GlobalStorage::load( const QString& filename ) +{ + QFile f( filename ); + if ( !f.open( QFile::ReadOnly ) ) + return false; + + QJsonParseError e; + QJsonDocument d = QJsonDocument::fromJson( f.read( 1_MiB ), &e ); + if ( d.isNull() ) + cWarning() << filename << e.errorString(); + else if ( !d.isObject() ) + cWarning() << filename << "Not suitable JSON."; + else + { + auto map = d.toVariant().toMap(); + for( auto i = map.constBegin() ; i != map.constEnd() ; ++i ) + { + insert( i.key(), *i ); + } + return true; + } + return false; +} bool GlobalStorage::saveYaml( const QString& filename ) diff --git a/src/libcalamares/GlobalStorage.h b/src/libcalamares/GlobalStorage.h index 2c31a8f47..89ebb5050 100644 --- a/src/libcalamares/GlobalStorage.h +++ b/src/libcalamares/GlobalStorage.h @@ -70,6 +70,14 @@ public: */ bool save( const QString& filename ); + /** @brief Adds the keys from the given JSON file + * + * No tidying, sanitization, or censoring is done. + * The JSON file is read and each key is added as a value to + * the global storage. + */ + bool load( const QString& filename ); + /** @brief write as YAML to the given filename * * See also save(), above. From 4652df06439e672b3ec17ac0850f285d1202456e Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 7 Aug 2018 05:57:26 -0400 Subject: [PATCH 028/302] CMake: allow required modules in calamares_add_plugin - Add a REQUIRES keyword - Write out values to the descriptor - Add some documentation for the function as a whole --- CMakeModules/CalamaresAddPlugin.cmake | 41 +++++++++++++++++++++------ 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/CMakeModules/CalamaresAddPlugin.cmake b/CMakeModules/CalamaresAddPlugin.cmake index 1d749d51c..9c7b9d90e 100644 --- a/CMakeModules/CalamaresAddPlugin.cmake +++ b/CMakeModules/CalamaresAddPlugin.cmake @@ -21,8 +21,8 @@ # Convenience function for creating a C++ (qtplugin) module for Calamares. # This function provides cmake-time feedback about the plugin, adds # targets for compilation and boilerplate information, and creates -# a module.desc with standard values if none is provided (which only -# happens for very unusual plugins). +# a module.desc with standard values (if the module.desc file exists, +# that one is used instead, which happens only for unusual plugins). # # Usage: # @@ -34,16 +34,35 @@ # UI ui-file... # LINK_LIBRARIES lib... # LINK_PRIVATE_LIBRARIES lib... -# COMPILE_DEFINITIONS def... -# RESOURCES resource-file +# [COMPILE_DEFINITIONS def...] +# [RESOURCES resource-file] +# [REQUIRES module-name...] # [NO_INSTALL] # [SHARED_LIB] # [EMERGENCY] # ) # -# The COMPILE_DEFINITIONS are set on the resulting module with a suitable -# flag (i.e. `-D`) so only state the name (optionally, also the value) -# without a `-D` prefixed to it. +# Function parameters: +# - COMPILE_DEFINITIONS +# Definitions are set on the resulting module with a suitable +# flag (i.e. `-D`) so only state the name (optionally, also the value) +# without a `-D` prefixed to it. +# - RESOURCES +# One (single!) filename for the RCC file for the plugin. +# - REQUIRES +# One or more names of modules which are added to the *requiredModules* +# key in the descriptor. See *Module Requirements* in the module +# documentation. +# - NO_INSTALL +# If this is set, the module is not installed by default; use this to +# build testing modules or unit-testing modules. +# - SHARED_LIB +# In unusual circumstances, this function is used to add a library +# rather than a normal Calamares module / plugin. +# - EMERGENCY +# If this is set, the module is marked as an *emergency* module in the +# descriptor. See *Emergency Modules* in the module documentation. +# include( CMakeParseArguments ) include( CalamaresAddLibrary ) @@ -54,7 +73,7 @@ function( calamares_add_plugin ) set( NAME ${ARGV0} ) set( options NO_INSTALL SHARED_LIB EMERGENCY ) set( oneValueArgs NAME TYPE EXPORT_MACRO RESOURCES ) - set( multiValueArgs SOURCES UI LINK_LIBRARIES LINK_PRIVATE_LIBRARIES COMPILE_DEFINITIONS ) + set( multiValueArgs SOURCES UI LINK_LIBRARIES LINK_PRIVATE_LIBRARIES COMPILE_DEFINITIONS REQUIRES ) cmake_parse_arguments( PLUGIN "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) set( PLUGIN_NAME ${NAME} ) set( PLUGIN_DESTINATION ${CMAKE_INSTALL_LIBDIR}/calamares/modules/${PLUGIN_NAME} ) @@ -142,6 +161,12 @@ function( calamares_add_plugin ) set( _type ${PLUGIN_TYPE} ) file( WRITE ${_file} "# AUTO-GENERATED metadata file\n# Syntax is YAML 1.2\n---\n" ) file( APPEND ${_file} "type: \"${_type}\"\nname: \"${PLUGIN_NAME}\"\ninterface: \"qtplugin\"\nload: \"lib${target}.so\"\n" ) + if ( PLUGIN_REQUIRES ) + file( APPEND ${_file} "requiredModules:\n" ) + foreach( _r ${PLUGIN_REQUIRES} ) + file( APPEND ${_file} " - ${_r}\n" ) + endforeach() + endif() if ( PLUGIN_EMERGENCY ) file( APPEND ${_file} "emergency: true\n" ) endif() From b0bcdba867b8100dbcee22959138b62638ddf054 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 7 Aug 2018 06:01:04 -0400 Subject: [PATCH 029/302] [unpackfs] Needs mount before it - The mount module must happen before unpackfs because that (mount) module sets up the root mount point (in /tmp) and some other variables needed later. --- src/modules/unpackfs/module.desc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/modules/unpackfs/module.desc b/src/modules/unpackfs/module.desc index 67a56b06c..4b3086e44 100644 --- a/src/modules/unpackfs/module.desc +++ b/src/modules/unpackfs/module.desc @@ -4,3 +4,5 @@ type: "job" name: "unpackfs" interface: "python" script: "main.py" +requiredModules: + - mount From 2bb66b8b9ba4f44028d9fe4d1e20d632519c3f3c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 7 Aug 2018 14:10:40 -0400 Subject: [PATCH 030/302] [preservefiles] Example with REQUIRES - preservefiles generally needs to have the target filesystems mounted, so that it can preserve to them; but you can also configure it such that there is no need for mounted filesystems (e.g. in OEM setup). - Add an example line in CMakeLists.txt to show how that would be done. --- src/modules/preservefiles/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/preservefiles/CMakeLists.txt b/src/modules/preservefiles/CMakeLists.txt index c1021eeda..f6cd98008 100644 --- a/src/modules/preservefiles/CMakeLists.txt +++ b/src/modules/preservefiles/CMakeLists.txt @@ -8,6 +8,7 @@ calamares_add_plugin( preservefiles PreserveFiles.cpp LINK_PRIVATE_LIBRARIES calamares + # REQUIRES mount # To set the rootMountPoint SHARED_LIB EMERGENCY ) From 82055f68542be8e3564b088e1c4e551857eac313 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 1 Aug 2019 14:31:25 +0200 Subject: [PATCH 031/302] [netinstall] Logging; code duplication - If there was an error, the network reply was never deleted - Improve logging to show where data is coming from --- src/modules/netinstall/NetInstallPage.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/modules/netinstall/NetInstallPage.cpp b/src/modules/netinstall/NetInstallPage.cpp index dfa94744d..fa45f0c42 100644 --- a/src/modules/netinstall/NetInstallPage.cpp +++ b/src/modules/netinstall/NetInstallPage.cpp @@ -74,6 +74,9 @@ NetInstallPage::readGroups( const QByteArray& yamlData ) void NetInstallPage::dataIsHere( QNetworkReply* reply ) { + cDebug() << "NetInstall group data received" << reply->url(); + reply->deleteLater(); + // If m_required is *false* then we still say we're ready // even if the reply is corrupt or missing. if ( reply->error() != QNetworkReply::NoError ) @@ -92,7 +95,6 @@ NetInstallPage::dataIsHere( QNetworkReply* reply ) cDebug() << Logger::SubEntry << "Url: " << reply->url().toString(); cDebug() << Logger::SubEntry << "Headers: " << reply->rawHeaderList(); ui->netinst_status->setText( tr( "Network Installation. (Disabled: Received invalid groups data)" ) ); - reply->deleteLater(); emit checkReady( !m_required ); return; } @@ -101,7 +103,6 @@ NetInstallPage::dataIsHere( QNetworkReply* reply ) ui->groupswidget->header()->setSectionResizeMode( 0, QHeaderView::ResizeToContents ); ui->groupswidget->header()->setSectionResizeMode( 1, QHeaderView::Stretch ); - reply->deleteLater(); emit checkReady( true ); } @@ -120,6 +121,7 @@ NetInstallPage::selectedPackages() const void NetInstallPage::loadGroupList( const QString& confUrl ) { + cDebug() << "NetInstall loading groups from" << confUrl; QNetworkRequest request; request.setUrl( QUrl( confUrl ) ); // Follows all redirects except unsafe ones (https to http). From bedff6b252504e249193904364ec475939db15bc Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 1 Aug 2019 14:39:09 +0200 Subject: [PATCH 032/302] [netinstall] Log immediate failures - If the request is immediately bad (e.g. because of a botched url) then log that fact; in this case no finished() is ever emitted. --- src/modules/netinstall/NetInstallPage.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/modules/netinstall/NetInstallPage.cpp b/src/modules/netinstall/NetInstallPage.cpp index fa45f0c42..a4f52d5b7 100644 --- a/src/modules/netinstall/NetInstallPage.cpp +++ b/src/modules/netinstall/NetInstallPage.cpp @@ -132,7 +132,13 @@ NetInstallPage::loadGroupList( const QString& confUrl ) connect( &m_networkManager, &QNetworkAccessManager::finished, this, &NetInstallPage::dataIsHere ); - m_networkManager.get( request ); + auto* rq = m_networkManager.get( request ); + if ( rq->error() ) + { + cDebug() << Logger::Continuation << "request failed immediately," << rq->errorString(); + rq->deleteLater(); + ui->netinst_status->setText( tr( "Network Installation. (Disabled: Incorrect configuration)" ) ); + } } void From cac07c1472fdbec47eaa05458598c13e3a83b011 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 1 Aug 2019 22:47:42 +0200 Subject: [PATCH 033/302] [libcalamares] Use std::chrono::seconds for timeouts - Distinguish just-an-int from seconds all across the API --- src/libcalamares/ProcessJob.cpp | 2 +- src/libcalamares/ProcessJob.h | 6 ++-- src/libcalamares/PythonJobApi.cpp | 4 ++- .../utils/CalamaresUtilsSystem.cpp | 22 +++++++-------- src/libcalamares/utils/CalamaresUtilsSystem.h | 28 +++++++++---------- src/libcalamares/utils/CommandList.cpp | 12 ++++---- src/libcalamares/utils/CommandList.h | 22 ++++++++------- 7 files changed, 51 insertions(+), 45 deletions(-) diff --git a/src/libcalamares/ProcessJob.cpp b/src/libcalamares/ProcessJob.cpp index 47fcee05d..f952fefe6 100644 --- a/src/libcalamares/ProcessJob.cpp +++ b/src/libcalamares/ProcessJob.cpp @@ -31,7 +31,7 @@ namespace Calamares { ProcessJob::ProcessJob( const QString& command, const QString& workingPath, bool runInChroot, - int secondsTimeout, + std::chrono::seconds secondsTimeout, QObject* parent ) : Job( parent ) , m_command( command ) diff --git a/src/libcalamares/ProcessJob.h b/src/libcalamares/ProcessJob.h index 224ebdaf0..84f84e550 100644 --- a/src/libcalamares/ProcessJob.h +++ b/src/libcalamares/ProcessJob.h @@ -22,6 +22,8 @@ #include "Job.h" +#include + namespace Calamares { class ProcessJob : public Job @@ -31,7 +33,7 @@ public: explicit ProcessJob( const QString& command, const QString& workingPath, bool runInChroot = false, - int secondsTimeout = 30, + std::chrono::seconds secondsTimeout = std::chrono::seconds(30), QObject* parent = nullptr ); virtual ~ProcessJob() override; @@ -43,7 +45,7 @@ private: QString m_command; QString m_workingPath; bool m_runInChroot; - int m_timeoutSec; + std::chrono::seconds m_timeoutSec; }; } // namespace Calamares diff --git a/src/libcalamares/PythonJobApi.cpp b/src/libcalamares/PythonJobApi.cpp index 8e8b8b2ab..750d8ea73 100644 --- a/src/libcalamares/PythonJobApi.cpp +++ b/src/libcalamares/PythonJobApi.cpp @@ -89,11 +89,13 @@ _target_env_command( const std::string& stdin, int timeout ) { + // Since Python doesn't give us the type system for distinguishing + // seconds from other integral types, massage to seconds here. return CalamaresUtils::System::instance()-> targetEnvCommand( args, QString(), QString::fromStdString( stdin ), - timeout ); + std::chrono::seconds( timeout ) ); } int diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.cpp b/src/libcalamares/utils/CalamaresUtilsSystem.cpp index 4fe571e6d..894c434be 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.cpp +++ b/src/libcalamares/utils/CalamaresUtilsSystem.cpp @@ -219,7 +219,7 @@ System::runCommand( } process.closeWriteChannel(); - if ( !process.waitForFinished( timeoutSec ? ( timeoutSec * 1000 ) : -1 ) ) + if ( !process.waitForFinished( timeoutSec > std::chrono::seconds::zero() ? ( std::chrono::milliseconds( timeoutSec ).count() ) : -1 ) ) { cWarning().noquote().nospace() << "Timed out. Output so far:\n" << process.readAllStandardOutput(); @@ -249,7 +249,7 @@ QString System::targetPath( const QString& path ) const { QString completePath; - + if ( doChroot() ) { Calamares::GlobalStorage* gs = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; @@ -259,14 +259,14 @@ System::targetPath( const QString& path ) const cWarning() << "No rootMountPoint in global storage, cannot create target file" << path; return QString(); } - + completePath = gs->value( "rootMountPoint" ).toString() + '/' + path; } else { completePath = QStringLiteral( "/" ) + path; } - + return completePath; } @@ -278,32 +278,32 @@ System::createTargetFile( const QString& path, const QByteArray& contents ) cons { return QString(); } - + QFile f( completePath ); if ( f.exists() ) { return QString(); } - + QIODevice::OpenMode m = #if QT_VERSION >= QT_VERSION_CHECK( 5, 11, 0 ) // New flag from Qt 5.11, implies WriteOnly QIODevice::NewOnly | #endif QIODevice::WriteOnly | QIODevice::Truncate; - + if ( !f.open( m ) ) { return QString(); } - + if ( f.write( contents ) != contents.size() ) { f.close(); f.remove(); return QString(); } - + f.close(); return QFileInfo( f ).canonicalFilePath(); } @@ -371,7 +371,7 @@ System::doChroot() const } Calamares::JobResult -ProcessResult::explainProcess( int ec, const QString& command, const QString& output, int timeout ) +ProcessResult::explainProcess( int ec, const QString& command, const QString& output, std::chrono::seconds timeout ) { using Calamares::JobResult; @@ -401,7 +401,7 @@ ProcessResult::explainProcess( int ec, const QString& command, const QString& ou return JobResult::error( QCoreApplication::translate( "ProcessResult", "External command failed to finish." ), QCoreApplication::translate( "ProcessResult", "Command %1 failed to finish in %2 seconds." ) .arg( command ) - .arg( timeout ) + .arg( timeout.count() ) + outputMessage ); //Any other exit code diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.h b/src/libcalamares/utils/CalamaresUtilsSystem.h index d39bcaab1..5b10f7d1a 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.h +++ b/src/libcalamares/utils/CalamaresUtilsSystem.h @@ -62,16 +62,16 @@ public: * @param timeout Timeout passed to the process runner, for explaining * error code -4 (timeout). */ - static Calamares::JobResult explainProcess( int errorCode, const QString& command, const QString& output, int timeout ); + static Calamares::JobResult explainProcess( int errorCode, const QString& command, const QString& output, std::chrono::seconds timeout ); /// @brief Convenience wrapper for explainProcess() - inline Calamares::JobResult explainProcess( const QString& command, int timeout ) const + inline Calamares::JobResult explainProcess( const QString& command, std::chrono::seconds timeout ) const { return explainProcess( getExitCode(), command, getOutput(), timeout ); } /// @brief Convenience wrapper for explainProcess() - inline Calamares::JobResult explainProcess( const QStringList& command, int timeout ) const + inline Calamares::JobResult explainProcess( const QStringList& command, std::chrono::seconds timeout ) const { return explainProcess( getExitCode(), command.join( ' ' ), getOutput(), timeout ); } @@ -207,40 +207,40 @@ public: return targetEnvOutput( QStringList{ command }, output, workingPath, stdInput, timeoutSec ); } - + /** @brief Gets a path to a file in the target system, from the host. - * + * * @param path Path to the file; this is interpreted * from the root of the target system (whatever that may be, * but / in the chroot, or / in OEM modes). - * + * * @return The complete path to the target file, from * the root of the host system, or empty on failure. - * + * * For instance, during installation where the target root is * mounted on /tmp/calamares-something, asking for targetPath("/etc/passwd") * will give you /tmp/calamares-something/etc/passwd. - * + * * No attempt is made to canonicalize anything, since paths might not exist. - */ + */ DLLEXPORT QString targetPath( const QString& path ) const; - + /** @brief Create a (small-ish) file in the target system. - * + * * @param path Path to the file; this is interpreted * from the root of the target system (whatever that may be, * but / in the chroot, or / in OEM modes). * @param contents Actual content of the file. - * + * * Will not overwrite files. Returns an empty string if the * target file already exists. - * + * * @return The complete canonical path to the target file from the * root of the host system, or empty on failure. (Here, it is * possible to be canonical because the file exists). */ DLLEXPORT QString createTargetFile( const QString& path, const QByteArray& contents ) const; - + /** * @brief getTotalMemoryB returns the total main memory, in bytes. * diff --git a/src/libcalamares/utils/CommandList.cpp b/src/libcalamares/utils/CommandList.cpp index 9916c71fe..414cfa9e5 100644 --- a/src/libcalamares/utils/CommandList.cpp +++ b/src/libcalamares/utils/CommandList.cpp @@ -35,10 +35,10 @@ namespace CalamaresUtils static CommandLine get_variant_object( const QVariantMap& m ) { QString command = CalamaresUtils::getString( m, "command" ); - int timeout = CalamaresUtils::getInteger( m, "timeout", CommandLine::TimeoutNotSet ); + int timeout = CalamaresUtils::getInteger( m, "timeout", -1 ); if ( !command.isEmpty() ) - return CommandLine( command, timeout ); + return CommandLine( command, timeout >= 0 ? std::chrono::seconds( timeout ) : CommandLine::TimeoutNotSet() ); cWarning() << "Bad CommandLine element" << m; return CommandLine(); } @@ -50,7 +50,7 @@ static CommandList_t get_variant_stringlist( const QVariantList& l ) for ( const auto& v : l ) { if ( v.type() == QVariant::String ) - retl.append( CommandLine( v.toString(), CommandLine::TimeoutNotSet ) ); + retl.append( CommandLine( v.toString(), CommandLine::TimeoutNotSet() ) ); else if ( v.type() == QVariant::Map ) { auto command( get_variant_object( v.toMap() ) ); @@ -65,13 +65,13 @@ static CommandList_t get_variant_stringlist( const QVariantList& l ) return retl; } -CommandList::CommandList( bool doChroot, int timeout ) +CommandList::CommandList( bool doChroot, std::chrono::seconds timeout ) : m_doChroot( doChroot ) , m_timeout( timeout ) { } -CommandList::CommandList::CommandList( const QVariant& v, bool doChroot, int timeout ) +CommandList::CommandList::CommandList( const QVariant& v, bool doChroot, std::chrono::seconds timeout ) : CommandList( doChroot, timeout ) { if ( v.type() == QVariant::List ) @@ -155,7 +155,7 @@ Calamares::JobResult CommandList::run() QStringList shell_cmd { "/bin/sh", "-c" }; shell_cmd << processed_cmd; - int timeout = i->timeout() >= 0 ? i->timeout() : m_timeout; + std::chrono::seconds timeout = i->timeout() >= std::chrono::seconds::zero() ? i->timeout() : m_timeout; ProcessResult r = System::runCommand( location, shell_cmd, QString(), QString(), timeout ); diff --git a/src/libcalamares/utils/CommandList.h b/src/libcalamares/utils/CommandList.h index 3dccdec6a..7453ae6ce 100644 --- a/src/libcalamares/utils/CommandList.h +++ b/src/libcalamares/utils/CommandList.h @@ -24,6 +24,8 @@ #include #include +#include + namespace CalamaresUtils { @@ -31,23 +33,23 @@ namespace CalamaresUtils * Each command can have an associated timeout in seconds. The timeout * defaults to 10 seconds. Provide some convenience naming and construction. */ -struct CommandLine : public QPair< QString, int > +struct CommandLine : public QPair< QString, std::chrono::seconds > { - enum { TimeoutNotSet = -1 }; + static inline constexpr std::chrono::seconds TimeoutNotSet() { return std::chrono::seconds(-1); } /// An invalid command line CommandLine() - : QPair< QString, int >( QString(), TimeoutNotSet ) + : QPair( QString(), TimeoutNotSet() ) { } CommandLine( const QString& s ) - : QPair< QString, int >( s, TimeoutNotSet ) + : QPair( s, TimeoutNotSet() ) { } - CommandLine( const QString& s, int t ) - : QPair< QString, int >( s, t) + CommandLine( const QString& s, std::chrono::seconds t ) + : QPair( s, t) { } @@ -56,7 +58,7 @@ struct CommandLine : public QPair< QString, int > return first; } - int timeout() const + std::chrono::seconds timeout() const { return second; } @@ -82,8 +84,8 @@ class CommandList : protected CommandList_t { public: /** @brief empty command-list with timeout to apply to entries. */ - CommandList( bool doChroot = true, int timeout = 10 ); - CommandList( const QVariant& v, bool doChroot = true, int timeout = 10 ); + CommandList( bool doChroot = true, std::chrono::seconds timeout = std::chrono::seconds( 10 ) ); + CommandList( const QVariant& v, bool doChroot = true, std::chrono::seconds timeout = std::chrono::seconds( 10 ) ); ~CommandList(); bool doChroot() const @@ -106,7 +108,7 @@ protected: private: bool m_doChroot; - int m_timeout; + std::chrono::seconds m_timeout; } ; } // namespace From e2504627aaf3420ec7ee0b9f6ccc5c76a306c8a7 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 1 Aug 2019 22:51:52 +0200 Subject: [PATCH 034/302] [libcalamaresui] Chase timeout-type into the UI library (TODO: move ProcessJobModule to libcalamares, it has no UI dependency) --- src/libcalamaresui/modulesystem/ProcessJobModule.cpp | 9 ++++++--- src/libcalamaresui/modulesystem/ProcessJobModule.h | 4 +++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/libcalamaresui/modulesystem/ProcessJobModule.cpp b/src/libcalamaresui/modulesystem/ProcessJobModule.cpp index f15e5c457..74c195b6b 100644 --- a/src/libcalamaresui/modulesystem/ProcessJobModule.cpp +++ b/src/libcalamaresui/modulesystem/ProcessJobModule.cpp @@ -72,10 +72,13 @@ ProcessJobModule::initFrom( const QVariantMap& moduleDescriptor ) m_command = moduleDescriptor.value( "command" ).toString(); } - m_secondsTimeout = 30; + m_secondsTimeout = std::chrono::seconds( 30 ); if ( moduleDescriptor.contains( "timeout" ) && !moduleDescriptor.value( "timeout" ).isNull() ) { - m_secondsTimeout = moduleDescriptor.value( "timeout" ).toInt(); + int sec = moduleDescriptor.value( "timeout" ).toInt(); + if ( sec < 0 ) + sec = 0; + m_secondsTimeout = std::chrono::seconds( sec ); } m_runInChroot = false; @@ -88,7 +91,7 @@ ProcessJobModule::initFrom( const QVariantMap& moduleDescriptor ) ProcessJobModule::ProcessJobModule() : Module() - , m_secondsTimeout( 30 ) + , m_secondsTimeout( std::chrono::seconds( 30 ) ) , m_runInChroot( false ) { } diff --git a/src/libcalamaresui/modulesystem/ProcessJobModule.h b/src/libcalamaresui/modulesystem/ProcessJobModule.h index 9c20aa4f4..96fb2ed47 100644 --- a/src/libcalamaresui/modulesystem/ProcessJobModule.h +++ b/src/libcalamaresui/modulesystem/ProcessJobModule.h @@ -24,6 +24,8 @@ #include "UiDllMacro.h" +#include + namespace Calamares { @@ -46,7 +48,7 @@ private: QString m_command; QString m_workingPath; - int m_secondsTimeout; + std::chrono::seconds m_secondsTimeout; bool m_runInChroot; job_ptr m_job; }; From a0854a999e4c4a1a5020d0f9316b13b6b7dc00fb Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 1 Aug 2019 22:59:06 +0200 Subject: [PATCH 035/302] Modules: chase API change, use std::chrono::seconds --- .../ContextualProcessJob.cpp | 2 +- src/modules/initcpio/InitcpioJob.cpp | 6 ++-- src/modules/initramfs/InitramfsJob.cpp | 6 ++-- .../luksbootkeyfile/LuksBootKeyFileJob.cpp | 4 +-- src/modules/shellprocess/ShellProcessJob.cpp | 2 +- src/modules/shellprocess/Tests.cpp | 35 +++++++++++-------- src/modules/tracking/TrackingJobs.cpp | 2 +- src/modules/users/CreateUserJob.cpp | 6 ++-- 8 files changed, 34 insertions(+), 29 deletions(-) diff --git a/src/modules/contextualprocess/ContextualProcessJob.cpp b/src/modules/contextualprocess/ContextualProcessJob.cpp index 428e54cd5..5d6b20afc 100644 --- a/src/modules/contextualprocess/ContextualProcessJob.cpp +++ b/src/modules/contextualprocess/ContextualProcessJob.cpp @@ -170,7 +170,7 @@ ContextualProcessJob::setConfigurationMap( const QVariantMap& configurationMap ) continue; } - CalamaresUtils::CommandList* commands = new CalamaresUtils::CommandList( valueiter.value(), !dontChroot, timeout ); + CalamaresUtils::CommandList* commands = new CalamaresUtils::CommandList( valueiter.value(), !dontChroot, std::chrono::seconds( timeout ) ); binding->append( valueString, commands ); } diff --git a/src/modules/initcpio/InitcpioJob.cpp b/src/modules/initcpio/InitcpioJob.cpp index 38017d83e..38f3a8961 100644 --- a/src/modules/initcpio/InitcpioJob.cpp +++ b/src/modules/initcpio/InitcpioJob.cpp @@ -74,8 +74,8 @@ InitcpioJob::exec() cDebug() << "Updating initramfs with kernel" << m_kernel; auto r = CalamaresUtils::System::instance()->targetEnvCommand( - { "mkinitcpio", "-p", m_kernel }, QString(), QString(), 0 ); - return r.explainProcess( "mkinitcpio", 10 ); + { "mkinitcpio", "-p", m_kernel }, QString(), QString() /* no timeout , 0 */ ); + return r.explainProcess( "mkinitcpio", std::chrono::seconds( 10 ) /* fake timeout */ ); } void @@ -89,7 +89,7 @@ InitcpioJob::setConfigurationMap( const QVariantMap& configurationMap ) else if ( m_kernel == "$uname" ) { auto r = CalamaresUtils::System::runCommand( - CalamaresUtils::System::RunLocation::RunInHost, { "/bin/uname", "-r" }, QString(), QString(), 3 ); + CalamaresUtils::System::RunLocation::RunInHost, { "/bin/uname", "-r" }, QString(), QString(), std::chrono::seconds( 3 ) ); if ( r.getExitCode() == 0 ) { m_kernel = r.getOutput(); diff --git a/src/modules/initramfs/InitramfsJob.cpp b/src/modules/initramfs/InitramfsJob.cpp index 01d400443..af8e07ca7 100644 --- a/src/modules/initramfs/InitramfsJob.cpp +++ b/src/modules/initramfs/InitramfsJob.cpp @@ -63,8 +63,8 @@ InitramfsJob::exec() // And then do the ACTUAL work. auto r = CalamaresUtils::System::instance()->targetEnvCommand( - { "update-initramfs", "-k", m_kernel, "-c", "-t" }, QString(), QString(), 0 ); - return r.explainProcess( "update-initramfs", 10 ); + { "update-initramfs", "-k", m_kernel, "-c", "-t" }, QString(), QString() /* no timeout, 0 */ ); + return r.explainProcess( "update-initramfs", std::chrono::seconds( 10 ) /* fake timeout */ ); } @@ -79,7 +79,7 @@ InitramfsJob::setConfigurationMap( const QVariantMap& configurationMap ) else if ( m_kernel == "$uname" ) { auto r = CalamaresUtils::System::runCommand( - CalamaresUtils::System::RunLocation::RunInHost, { "/bin/uname", "-r" }, QString(), QString(), 3 ); + CalamaresUtils::System::RunLocation::RunInHost, { "/bin/uname", "-r" }, QString(), QString(), std::chrono::seconds( 3 ) ); if ( r.getExitCode() == 0 ) { m_kernel = r.getOutput(); diff --git a/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp b/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp index 292c768a9..9bcea6538 100644 --- a/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp +++ b/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp @@ -71,7 +71,7 @@ struct LuksDevice * Given a list of partitions (as set up by the partitioning module, * so there's maps with keys inside), returns just the list of * luks passphrases for each device. - */ + */ static QList< LuksDevice > getLuksDevices( const QVariantList& list ) { @@ -130,7 +130,7 @@ static bool setupLuks( const LuksDevice& d ) { auto r = CalamaresUtils::System::instance()->targetEnvCommand( - { "cryptsetup", "luksAddKey", d.device, keyfile }, QString(), d.passphrase, 15 ); + { "cryptsetup", "luksAddKey", d.device, keyfile }, QString(), d.passphrase, std::chrono::seconds( 15 ) ); if ( r.getExitCode() != 0 ) { cWarning() << "Could not configure LUKS keyfile on" << d.device << ':' << r.getOutput() << "(exit code" diff --git a/src/modules/shellprocess/ShellProcessJob.cpp b/src/modules/shellprocess/ShellProcessJob.cpp index d688540ae..ba3e9a299 100644 --- a/src/modules/shellprocess/ShellProcessJob.cpp +++ b/src/modules/shellprocess/ShellProcessJob.cpp @@ -75,7 +75,7 @@ ShellProcessJob::setConfigurationMap( const QVariantMap& configurationMap ) if ( configurationMap.contains( "script" ) ) { - m_commands = new CalamaresUtils::CommandList( configurationMap.value( "script" ), !dontChroot, timeout ); + m_commands = new CalamaresUtils::CommandList( configurationMap.value( "script" ), !dontChroot, std::chrono::seconds( timeout ) ); if ( m_commands->isEmpty() ) cDebug() << "ShellProcessJob: \"script\" contains no commands for" << moduleInstanceKey(); } diff --git a/src/modules/shellprocess/Tests.cpp b/src/modules/shellprocess/Tests.cpp index 488f4a7af..149fbc2d3 100644 --- a/src/modules/shellprocess/Tests.cpp +++ b/src/modules/shellprocess/Tests.cpp @@ -34,6 +34,8 @@ QTEST_GUILESS_MAIN( ShellProcessTests ) using CommandList = CalamaresUtils::CommandList; +using std::operator""s; + ShellProcessTests::ShellProcessTests() { @@ -68,8 +70,9 @@ ShellProcessTests::testProcessListSampleConfig() CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) ); QVERIFY( !cl.isEmpty() ); QCOMPARE( cl.count(), 3 ); - QCOMPARE( cl.at(0).timeout(), -1 ); - QCOMPARE( cl.at(2).timeout(), 3600 ); // slowloris + + QCOMPARE( cl.at(0).timeout(), CalamaresUtils::CommandLine::TimeoutNotSet() ); + QCOMPARE( cl.at(2).timeout(), 3600s ); // slowloris } void ShellProcessTests::testProcessListFromList() @@ -105,9 +108,10 @@ script: "ls /tmp" )" ); CommandList cl( CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) ); + QVERIFY( !cl.isEmpty() ); QCOMPARE( cl.count(), 1 ); - QCOMPARE( cl.at(0).timeout(), 10 ); + QCOMPARE( cl.at(0).timeout(), 10s ); QCOMPARE( cl.at(0).command(), QStringLiteral( "ls /tmp" ) ); // Not a string @@ -118,7 +122,6 @@ script: false CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) ); QVERIFY( cl1.isEmpty() ); QCOMPARE( cl1.count(), 0 ); - } void ShellProcessTests::testProcessFromObject() @@ -130,9 +133,10 @@ script: )" ); CommandList cl( CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) ); + QVERIFY( !cl.isEmpty() ); QCOMPARE( cl.count(), 1 ); - QCOMPARE( cl.at(0).timeout(), 20 ); + QCOMPARE( cl.at(0).timeout(), 20s ); QCOMPARE( cl.at(0).command(), QStringLiteral( "ls /tmp" ) ); } @@ -148,9 +152,9 @@ script: CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) ); QVERIFY( !cl.isEmpty() ); QCOMPARE( cl.count(), 2 ); - QCOMPARE( cl.at(0).timeout(), 12 ); + QCOMPARE( cl.at(0).timeout(), 12s ); QCOMPARE( cl.at(0).command(), QStringLiteral( "ls /tmp" ) ); - QCOMPARE( cl.at(1).timeout(), -1 ); // not set + QCOMPARE( cl.at(1).timeout(), CalamaresUtils::CommandLine::TimeoutNotSet() ); // not set } void ShellProcessTests::testRootSubstitution() @@ -182,30 +186,31 @@ script: QVERIFY( gs != nullptr ); qDebug() << "Expect WARNING, ERROR, WARNING"; + // Doesn't use @@ROOT@@, so no failures - QVERIFY( bool(CommandList(plainScript, false, 10 ).run()) ); + QVERIFY( bool(CommandList(plainScript, false, 10s ).run()) ); // Doesn't use @@ROOT@@, but does chroot, so fails - QVERIFY( !bool(CommandList(plainScript, true, 10 ).run()) ); + QVERIFY( !bool(CommandList(plainScript, true, 10s ).run()) ); // Does use @@ROOT@@, which is not set, so fails - QVERIFY( !bool(CommandList(rootScript, false, 10 ).run()) ); + QVERIFY( !bool(CommandList(rootScript, false, 10s ).run()) ); // .. fails for two reasons - QVERIFY( !bool(CommandList(rootScript, true, 10 ).run()) ); + QVERIFY( !bool(CommandList(rootScript, true, 10s ).run()) ); gs->insert( "rootMountPoint", "/tmp" ); // Now that the root is set, two variants work .. still can't // chroot, unless the rootMountPoint contains a full system, // *and* we're allowed to chroot (ie. running tests as root). qDebug() << "Expect no output."; - QVERIFY( bool(CommandList(plainScript, false, 10 ).run()) ); - QVERIFY( bool(CommandList(rootScript, false, 10 ).run()) ); + QVERIFY( bool(CommandList(plainScript, false, 10s ).run()) ); + QVERIFY( bool(CommandList(rootScript, false, 10s ).run()) ); qDebug() << "Expect ERROR"; // But no user set yet - QVERIFY( !bool(CommandList(userScript, false, 10 ).run()) ); + QVERIFY( !bool(CommandList(userScript, false, 10s ).run()) ); // Now play dangerous games with shell expansion gs->insert( "username", "`id -u`" ); - QVERIFY( bool(CommandList(userScript, false, 10 ).run()) ); + QVERIFY( bool(CommandList(userScript, false, 10s ).run()) ); } diff --git a/src/modules/tracking/TrackingJobs.cpp b/src/modules/tracking/TrackingJobs.cpp index 7875ee6db..53884445e 100644 --- a/src/modules/tracking/TrackingJobs.cpp +++ b/src/modules/tracking/TrackingJobs.cpp @@ -125,7 +125,7 @@ sed -i "s,URI =.*,URI = http://releases.neon.kde.org/meta-release/${MACHINE_ID}, sed -i "s,URI_LTS =.*,URI_LTS = http://releases.neon.kde.org/meta-release-lts/${MACHINE_ID}," /etc/update-manager/meta-release true )x"), - 1); + std::chrono::seconds( 1 ) ); if ( r == 0 ) return Calamares::JobResult::ok(); diff --git a/src/modules/users/CreateUserJob.cpp b/src/modules/users/CreateUserJob.cpp index d7e356231..788ba0195 100644 --- a/src/modules/users/CreateUserJob.cpp +++ b/src/modules/users/CreateUserJob.cpp @@ -158,7 +158,7 @@ CreateUserJob::exec() if ( commandResult.getExitCode() ) { cError() << "useradd failed" << commandResult.getExitCode(); - return commandResult.explainProcess( useradd, 10 /* bogus timeout */ ); + return commandResult.explainProcess( useradd, std::chrono::seconds( 10 ) /* bogus timeout */ ); } commandResult = CalamaresUtils::System::instance()->targetEnvCommand( @@ -166,7 +166,7 @@ CreateUserJob::exec() if ( commandResult.getExitCode() ) { cError() << "usermod failed" << commandResult.getExitCode(); - return commandResult.explainProcess( "usermod", 10 ); + return commandResult.explainProcess( "usermod", std::chrono::seconds( 10 ) /* bogus timeout */ ); } QString userGroup = QString( "%1:%2" ).arg( m_userName ).arg( m_userName ); @@ -176,7 +176,7 @@ CreateUserJob::exec() if ( commandResult.getExitCode() ) { cError() << "chown failed" << commandResult.getExitCode(); - return commandResult.explainProcess( "chown", 10 ); + return commandResult.explainProcess( "chown", std::chrono::seconds( 10 ) /* bogus timeout */ ); } return Calamares::JobResult::ok(); From 518320051599365706f7880b4b4892c3d63e0a06 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 1 Aug 2019 23:05:42 +0200 Subject: [PATCH 036/302] [tracking] Apply current coding style --- src/modules/tracking/TrackingJobs.cpp | 61 ++++---- src/modules/tracking/TrackingPage.cpp | 167 +++++++++++++--------- src/modules/tracking/TrackingPage.h | 4 +- src/modules/tracking/TrackingType.h | 4 +- src/modules/tracking/TrackingViewStep.cpp | 36 +++-- src/modules/tracking/TrackingViewStep.h | 19 ++- 6 files changed, 174 insertions(+), 117 deletions(-) diff --git a/src/modules/tracking/TrackingJobs.cpp b/src/modules/tracking/TrackingJobs.cpp index 53884445e..8652b8e6f 100644 --- a/src/modules/tracking/TrackingJobs.cpp +++ b/src/modules/tracking/TrackingJobs.cpp @@ -38,22 +38,26 @@ TrackingInstallJob::~TrackingInstallJob() delete m_networkManager; } -QString TrackingInstallJob::prettyName() const +QString +TrackingInstallJob::prettyName() const { return tr( "Installation feedback" ); } -QString TrackingInstallJob::prettyDescription() const +QString +TrackingInstallJob::prettyDescription() const { return prettyName(); } -QString TrackingInstallJob::prettyStatusMessage() const +QString +TrackingInstallJob::prettyStatusMessage() const { return tr( "Sending installation feedback." ); } -Calamares::JobResult TrackingInstallJob::exec() +Calamares::JobResult +TrackingInstallJob::exec() { m_networkManager = new QNetworkAccessManager(); @@ -66,16 +70,13 @@ Calamares::JobResult TrackingInstallJob::exec() request.setRawHeader( "User-Agent", "Mozilla/5.0 (compatible; Calamares)" ); QTimer timeout; - timeout.setSingleShot(true); + timeout.setSingleShot( true ); QEventLoop loop; - connect( m_networkManager, &QNetworkAccessManager::finished, - this, &TrackingInstallJob::dataIsHere ); - connect( m_networkManager, &QNetworkAccessManager::finished, - &loop, &QEventLoop::quit ); - connect( &timeout, &QTimer::timeout, - &loop, &QEventLoop::quit ); + connect( m_networkManager, &QNetworkAccessManager::finished, this, &TrackingInstallJob::dataIsHere ); + connect( m_networkManager, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit ); + connect( &timeout, &QTimer::timeout, &loop, &QEventLoop::quit ); m_networkManager->get( request ); // The semaphore is released when data is received timeout.start( 5000 /* ms */ ); @@ -93,46 +94,52 @@ Calamares::JobResult TrackingInstallJob::exec() return Calamares::JobResult::ok(); } -void TrackingInstallJob::dataIsHere( QNetworkReply* reply ) +void +TrackingInstallJob::dataIsHere( QNetworkReply* reply ) { cDebug() << "Installation feedback request OK"; reply->deleteLater(); } -QString TrackingMachineNeonJob::prettyName() const +QString +TrackingMachineNeonJob::prettyName() const { return tr( "Machine feedback" ); } -QString TrackingMachineNeonJob::prettyDescription() const +QString +TrackingMachineNeonJob::prettyDescription() const { return prettyName(); } -QString TrackingMachineNeonJob::prettyStatusMessage() const +QString +TrackingMachineNeonJob::prettyStatusMessage() const { return tr( "Configuring machine feedback." ); } -Calamares::JobResult TrackingMachineNeonJob::exec() +Calamares::JobResult +TrackingMachineNeonJob::exec() { - int r = CalamaresUtils::System::instance()->targetEnvCall( - "/bin/sh", - QString(), // Working dir - QString( -R"x(MACHINE_ID=`cat /etc/machine-id` + int r = CalamaresUtils::System::instance()->targetEnvCall( "/bin/sh", + QString(), // Working dir + QString( + 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"), - std::chrono::seconds( 1 ) ); +)x" ), + std::chrono::seconds( 1 ) ); if ( r == 0 ) return Calamares::JobResult::ok(); else if ( r > 0 ) - return Calamares::JobResult::error( tr( "Error in machine feedback configuration." ), - tr( "Could not configure machine feedback correctly, script error %1." ).arg( r ) ); + return Calamares::JobResult::error( + tr( "Error in machine feedback configuration." ), + tr( "Could not configure machine feedback correctly, script error %1." ).arg( r ) ); else - return Calamares::JobResult::error( tr( "Error in machine feedback configuration." ), - tr( "Could not configure machine feedback correctly, Calamares error %1." ).arg( r ) ); + return Calamares::JobResult::error( + tr( "Error in machine feedback configuration." ), + tr( "Could not configure machine feedback correctly, Calamares error %1." ).arg( r ) ); } diff --git a/src/modules/tracking/TrackingPage.cpp b/src/modules/tracking/TrackingPage.cpp index 924ac43d9..82ee6b01d 100644 --- a/src/modules/tracking/TrackingPage.cpp +++ b/src/modules/tracking/TrackingPage.cpp @@ -21,18 +21,18 @@ #include "ui_page_trackingstep.h" #include "Branding.h" -#include "JobQueue.h" #include "GlobalStorage.h" -#include "utils/Logger.h" -#include "utils/CalamaresUtilsGui.h" -#include "utils/Retranslator.h" +#include "JobQueue.h" #include "ViewManager.h" +#include "utils/CalamaresUtilsGui.h" +#include "utils/Logger.h" +#include "utils/Retranslator.h" #include #include #include -TrackingPage::TrackingPage(QWidget *parent) +TrackingPage::TrackingPage( QWidget* parent ) : QWidget( parent ) , ui( new Ui::TrackingPage ) { @@ -40,14 +40,22 @@ TrackingPage::TrackingPage(QWidget *parent) ui->setupUi( this ); CALAMARES_RETRANSLATE( - 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( *StringEntry::ShortProductName ) ); - 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( *StringEntry::ShortProductName ) ); - ui->userExplanation->setText( tr( "By selecting this you will regularly send information about your installation, hardware, applications and usage patterns, to %1." ).arg( *StringEntry::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( *StringEntry::ShortProductName ) ); + 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( *StringEntry::ShortProductName ) ); + ui->userExplanation->setText( tr( "By selecting this you will regularly send information about your " + "installation, hardware, applications and usage patterns, to %1." ) + .arg( *StringEntry::ShortProductName ) ); ) - QButtonGroup *group = new QButtonGroup( this ); + QButtonGroup* group = new QButtonGroup( this ); group->setExclusive( true ); group->addButton( ui->noneRadio ); group->addButton( ui->installRadio ); @@ -56,114 +64,143 @@ TrackingPage::TrackingPage(QWidget *parent) ui->noneRadio->setChecked( true ); } -void TrackingPage::enableTrackingOption(TrackingType t, bool enabled) +void +TrackingPage::enableTrackingOption( TrackingType t, bool enabled ) { QWidget* group = nullptr; switch ( t ) { - case TrackingType::InstallTracking: - group = ui->installGroup; - break; - case TrackingType::MachineTracking: - group = ui->machineGroup; - break; - case TrackingType::UserTracking: - group = ui->userGroup; - break; + 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); + { + cWarning() << "unknown tracking option" << int( t ); + } } -bool TrackingPage::getTrackingOption(TrackingType 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() +#define ch( x ) ui->x->isChecked() switch ( t ) { - 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; + 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) +void +TrackingPage::setTrackingPolicy( TrackingType t, QString url ) { - QToolButton *button = nullptr; - switch( t ) + QToolButton* button = nullptr; + switch ( t ) { - case TrackingType::InstallTracking: - button = ui->installPolicyButton; - break; - case TrackingType::MachineTracking: - button = ui->machinePolicyButton; - break; - case TrackingType::UserTracking: - button = ui->userPolicyButton; - break; + 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; + 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 ) -{ - 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 ); } ); + cWarning() << "unknown tracking option" << int( t ); } } -void TrackingPage::setTrackingLevel(const QString& l) +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( const QString& l ) { QString level = l.toLower(); QRadioButton* button = nullptr; - if (level.isEmpty() || level == "none") + if ( level.isEmpty() || level == "none" ) + { button = ui->noneRadio; - else if (level == "install") + } + else if ( level == "install" ) + { button = ui->installRadio; - else if (level == "machine") + } + else if ( level == "machine" ) + { button = ui->machineRadio; - else if (level == "user") + } + else if ( level == "user" ) + { button = ui->userRadio; + } 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 ac667d5e6..560115b92 100644 --- a/src/modules/tracking/TrackingPage.h +++ b/src/modules/tracking/TrackingPage.h @@ -21,8 +21,8 @@ #include "TrackingType.h" -#include #include +#include namespace Ui { @@ -61,4 +61,4 @@ private: Ui::TrackingPage* ui; }; -#endif //TRACKINGPAGE_H +#endif //TRACKINGPAGE_H diff --git a/src/modules/tracking/TrackingType.h b/src/modules/tracking/TrackingType.h index 5c97e8485..02dbd934e 100644 --- a/src/modules/tracking/TrackingType.h +++ b/src/modules/tracking/TrackingType.h @@ -24,6 +24,6 @@ enum class TrackingType InstallTracking, MachineTracking, UserTracking -} ; +}; -#endif //TRACKINGTYPE_H +#endif //TRACKINGTYPE_H diff --git a/src/modules/tracking/TrackingViewStep.cpp b/src/modules/tracking/TrackingViewStep.cpp index cb48b340b..a51864ea9 100644 --- a/src/modules/tracking/TrackingViewStep.cpp +++ b/src/modules/tracking/TrackingViewStep.cpp @@ -21,20 +21,21 @@ #include "TrackingJobs.h" #include "TrackingPage.h" -#include "JobQueue.h" #include "GlobalStorage.h" +#include "JobQueue.h" -#include "utils/Logger.h" #include "utils/CalamaresUtilsSystem.h" +#include "utils/Logger.h" #include "utils/Variant.h" #include #include -CALAMARES_PLUGIN_FACTORY_DEFINITION( TrackingViewStepFactory, registerPlugin(); ) +CALAMARES_PLUGIN_FACTORY_DEFINITION( TrackingViewStepFactory, registerPlugin< TrackingViewStep >(); ) /** @brief Is @p s a valid machine-tracking style. */ -static bool isValidStyle( const QString& s ) +static bool +isValidStyle( const QString& s ) { static QStringList knownStyles { "neon" }; return knownStyles.contains( s ); @@ -51,7 +52,9 @@ TrackingViewStep::TrackingViewStep( QObject* parent ) TrackingViewStep::~TrackingViewStep() { if ( m_widget && m_widget->parent() == nullptr ) + { m_widget->deleteLater(); + } } @@ -97,11 +100,12 @@ TrackingViewStep::isAtEnd() const } -void TrackingViewStep::onLeave() +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 ); + 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(); @@ -123,10 +127,7 @@ TrackingViewStep::jobs() const memory.setNum( s->getTotalMemoryB().first ); disk.setNum( s->getTotalDiskB() ); - installUrl - .replace( "$CPU", s->getCpuDescription() ) - .replace( "$MEMORY", memory ) - .replace( "$DISK", disk ); + installUrl.replace( "$CPU", s->getCpuDescription() ).replace( "$MEMORY", memory ).replace( "$DISK", disk ); cDebug() << Logger::SubEntry << "install-tracking URL" << installUrl; @@ -137,13 +138,16 @@ TrackingViewStep::jobs() const { Q_ASSERT( isValidStyle( m_machineTrackingStyle ) ); if ( m_machineTrackingStyle == "neon" ) + { l.append( Calamares::job_ptr( new TrackingMachineNeonJob() ) ); + } } return l; } -QVariantMap TrackingViewStep::setTrackingOption(const QVariantMap& configurationMap, const QString& key, TrackingType t) +QVariantMap +TrackingViewStep::setTrackingOption( const QVariantMap& configurationMap, const QString& key, TrackingType t ) { bool settingEnabled = false; @@ -159,8 +163,8 @@ QVariantMap TrackingViewStep::setTrackingOption(const QVariantMap& configuration trackingConfiguration.settingEnabled = settingEnabled; trackingConfiguration.userEnabled = false; - m_widget->enableTrackingOption(t, settingEnabled); - m_widget->setTrackingPolicy(t, CalamaresUtils::getString( config, "policy" ) ); + m_widget->enableTrackingOption( t, settingEnabled ); + m_widget->setTrackingPolicy( t, CalamaresUtils::getString( config, "policy" ) ); return config; } @@ -176,7 +180,9 @@ TrackingViewStep::setConfigurationMap( const QVariantMap& configurationMap ) config = setTrackingOption( configurationMap, "machine", TrackingType::MachineTracking ); auto s = CalamaresUtils::getString( config, "style" ); if ( isValidStyle( s ) ) + { m_machineTrackingStyle = s; + } setTrackingOption( configurationMap, "user", TrackingType::UserTracking ); diff --git a/src/modules/tracking/TrackingViewStep.h b/src/modules/tracking/TrackingViewStep.h index aaaf3bbae..dc952253a 100644 --- a/src/modules/tracking/TrackingViewStep.h +++ b/src/modules/tracking/TrackingViewStep.h @@ -21,9 +21,9 @@ #include "TrackingType.h" +#include #include #include -#include #include #include @@ -65,12 +65,13 @@ private: struct TrackingEnabled { bool settingEnabled; // Enabled in config file - bool userEnabled; // User checked "yes" + bool userEnabled; // User checked "yes" TrackingEnabled() : settingEnabled( false ) , userEnabled( false ) - {} + { + } bool enabled() const { return settingEnabled && userEnabled; } }; @@ -78,15 +79,21 @@ private: inline TrackingEnabled& tracking( TrackingType t ) { - if (t == TrackingType::UserTracking) + if ( t == TrackingType::UserTracking ) + { return m_userTracking; - else if (t == TrackingType::MachineTracking) + } + else if ( t == TrackingType::MachineTracking ) + { return m_machineTracking; + } else + { return m_installTracking; + } } }; CALAMARES_PLUGIN_FACTORY_DECLARATION( TrackingViewStepFactory ) -#endif // TRACKINGVIEWSTEP_H +#endif // TRACKINGVIEWSTEP_H From d36373230266e7ee5c0fbf17815fdb2663c77849 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 1 Aug 2019 23:07:45 +0200 Subject: [PATCH 037/302] [tracking] Use std::chrono where appropriate --- src/modules/tracking/TrackingJobs.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/modules/tracking/TrackingJobs.cpp b/src/modules/tracking/TrackingJobs.cpp index 8652b8e6f..26f0b67aa 100644 --- a/src/modules/tracking/TrackingJobs.cpp +++ b/src/modules/tracking/TrackingJobs.cpp @@ -27,6 +27,8 @@ #include #include +#include + TrackingInstallJob::TrackingInstallJob( const QString& url ) : m_url( url ) , m_networkManager( nullptr ) @@ -79,7 +81,7 @@ TrackingInstallJob::exec() connect( &timeout, &QTimer::timeout, &loop, &QEventLoop::quit ); m_networkManager->get( request ); // The semaphore is released when data is received - timeout.start( 5000 /* ms */ ); + timeout.start( std::chrono::milliseconds( 5000 ) ); loop.exec(); From a0430f76b74a11b44a865b28bb894a958e05f470 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 1 Aug 2019 23:10:20 +0200 Subject: [PATCH 038/302] [shellprocess] Apply current coding style --- src/modules/shellprocess/ShellProcessJob.cpp | 17 ++-- src/modules/shellprocess/ShellProcessJob.h | 2 +- src/modules/shellprocess/Tests.cpp | 92 ++++++++++---------- 3 files changed, 57 insertions(+), 54 deletions(-) diff --git a/src/modules/shellprocess/ShellProcessJob.cpp b/src/modules/shellprocess/ShellProcessJob.cpp index ba3e9a299..59d37d34b 100644 --- a/src/modules/shellprocess/ShellProcessJob.cpp +++ b/src/modules/shellprocess/ShellProcessJob.cpp @@ -18,13 +18,13 @@ #include "ShellProcessJob.h" -#include #include +#include #include #include "CalamaresVersion.h" -#include "JobQueue.h" #include "GlobalStorage.h" +#include "JobQueue.h" #include "utils/CommandList.h" #include "utils/Logger.h" @@ -55,7 +55,7 @@ Calamares::JobResult ShellProcessJob::exec() { - if ( ! m_commands || m_commands->isEmpty() ) + if ( !m_commands || m_commands->isEmpty() ) { cWarning() << "No commands to execute" << moduleInstanceKey(); return Calamares::JobResult::ok(); @@ -71,16 +71,23 @@ ShellProcessJob::setConfigurationMap( const QVariantMap& configurationMap ) bool dontChroot = CalamaresUtils::getBool( configurationMap, "dontChroot", false ); int timeout = CalamaresUtils::getInteger( configurationMap, "timeout", 10 ); if ( timeout < 1 ) + { timeout = 10; + } if ( configurationMap.contains( "script" ) ) { - m_commands = new CalamaresUtils::CommandList( configurationMap.value( "script" ), !dontChroot, std::chrono::seconds( timeout ) ); + m_commands = new CalamaresUtils::CommandList( + configurationMap.value( "script" ), !dontChroot, std::chrono::seconds( timeout ) ); if ( m_commands->isEmpty() ) + { cDebug() << "ShellProcessJob: \"script\" contains no commands for" << moduleInstanceKey(); + } } else + { cWarning() << "No script given for ShellProcessJob" << moduleInstanceKey(); + } } -CALAMARES_PLUGIN_FACTORY_DEFINITION( ShellProcessJobFactory, registerPlugin(); ) +CALAMARES_PLUGIN_FACTORY_DEFINITION( ShellProcessJobFactory, registerPlugin< ShellProcessJob >(); ) diff --git a/src/modules/shellprocess/ShellProcessJob.h b/src/modules/shellprocess/ShellProcessJob.h index 3111fc26e..b9a255d95 100644 --- a/src/modules/shellprocess/ShellProcessJob.h +++ b/src/modules/shellprocess/ShellProcessJob.h @@ -50,4 +50,4 @@ private: CALAMARES_PLUGIN_FACTORY_DECLARATION( ShellProcessJobFactory ) -#endif // SHELLPROCESSJOB_H +#endif // SHELLPROCESSJOB_H diff --git a/src/modules/shellprocess/Tests.cpp b/src/modules/shellprocess/Tests.cpp index 149fbc2d3..943a70957 100644 --- a/src/modules/shellprocess/Tests.cpp +++ b/src/modules/shellprocess/Tests.cpp @@ -37,13 +37,9 @@ using CommandList = CalamaresUtils::CommandList; using std::operator""s; -ShellProcessTests::ShellProcessTests() -{ -} +ShellProcessTests::ShellProcessTests() {} -ShellProcessTests::~ShellProcessTests() -{ -} +ShellProcessTests::~ShellProcessTests() {} void ShellProcessTests::initTestCase() @@ -66,16 +62,16 @@ ShellProcessTests::testProcessListSampleConfig() } } - CommandList cl( - CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) ); + CommandList cl( CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) ); QVERIFY( !cl.isEmpty() ); QCOMPARE( cl.count(), 3 ); - QCOMPARE( cl.at(0).timeout(), CalamaresUtils::CommandLine::TimeoutNotSet() ); - QCOMPARE( cl.at(2).timeout(), 3600s ); // slowloris + QCOMPARE( cl.at( 0 ).timeout(), CalamaresUtils::CommandLine::TimeoutNotSet() ); + QCOMPARE( cl.at( 2 ).timeout(), 3600s ); // slowloris } -void ShellProcessTests::testProcessListFromList() +void +ShellProcessTests::testProcessListFromList() { YAML::Node doc = YAML::Load( R"(--- script: @@ -83,8 +79,7 @@ script: - "ls /nonexistent" - "/bin/false" )" ); - CommandList cl( - CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) ); + CommandList cl( CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) ); QVERIFY( !cl.isEmpty() ); QCOMPARE( cl.count(), 3 ); @@ -95,52 +90,51 @@ script: - false - "ls /nonexistent" )" ); - CommandList cl1( - CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) ); + CommandList cl1( CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) ); QVERIFY( !cl1.isEmpty() ); QCOMPARE( cl1.count(), 2 ); // One element ignored } -void ShellProcessTests::testProcessListFromString() +void +ShellProcessTests::testProcessListFromString() { YAML::Node doc = YAML::Load( R"(--- script: "ls /tmp" )" ); - CommandList cl( - CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) ); + CommandList cl( CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) ); QVERIFY( !cl.isEmpty() ); QCOMPARE( cl.count(), 1 ); - QCOMPARE( cl.at(0).timeout(), 10s ); - QCOMPARE( cl.at(0).command(), QStringLiteral( "ls /tmp" ) ); + QCOMPARE( cl.at( 0 ).timeout(), 10s ); + QCOMPARE( cl.at( 0 ).command(), QStringLiteral( "ls /tmp" ) ); // Not a string doc = YAML::Load( R"(--- script: false )" ); - CommandList cl1( - CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) ); + CommandList cl1( CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) ); QVERIFY( cl1.isEmpty() ); QCOMPARE( cl1.count(), 0 ); } -void ShellProcessTests::testProcessFromObject() +void +ShellProcessTests::testProcessFromObject() { YAML::Node doc = YAML::Load( R"(--- script: command: "ls /tmp" timeout: 20 )" ); - CommandList cl( - CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) ); + CommandList cl( CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) ); QVERIFY( !cl.isEmpty() ); QCOMPARE( cl.count(), 1 ); - QCOMPARE( cl.at(0).timeout(), 20s ); - QCOMPARE( cl.at(0).command(), QStringLiteral( "ls /tmp" ) ); + QCOMPARE( cl.at( 0 ).timeout(), 20s ); + QCOMPARE( cl.at( 0 ).command(), QStringLiteral( "ls /tmp" ) ); } -void ShellProcessTests::testProcessListFromObject() +void +ShellProcessTests::testProcessListFromObject() { YAML::Node doc = YAML::Load( R"(--- script: @@ -148,34 +142,36 @@ script: timeout: 12 - "-/bin/false" )" ); - CommandList cl( - CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) ); + CommandList cl( CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ) ); QVERIFY( !cl.isEmpty() ); QCOMPARE( cl.count(), 2 ); - QCOMPARE( cl.at(0).timeout(), 12s ); - QCOMPARE( cl.at(0).command(), QStringLiteral( "ls /tmp" ) ); - QCOMPARE( cl.at(1).timeout(), CalamaresUtils::CommandLine::TimeoutNotSet() ); // not set + QCOMPARE( cl.at( 0 ).timeout(), 12s ); + QCOMPARE( cl.at( 0 ).command(), QStringLiteral( "ls /tmp" ) ); + QCOMPARE( cl.at( 1 ).timeout(), CalamaresUtils::CommandLine::TimeoutNotSet() ); // not set } -void ShellProcessTests::testRootSubstitution() +void +ShellProcessTests::testRootSubstitution() { YAML::Node doc = YAML::Load( R"(--- script: - "ls /tmp" )" ); QVariant plainScript = CalamaresUtils::yamlMapToVariant( doc ).toMap().value( "script" ); - QVariant rootScript = CalamaresUtils::yamlMapToVariant( - YAML::Load( R"(--- + QVariant rootScript = CalamaresUtils::yamlMapToVariant( YAML::Load( R"(--- script: - "ls @@ROOT@@" -)" ) ).toMap().value( "script" ); - QVariant userScript = CalamaresUtils::yamlMapToVariant( - YAML::Load( R"(--- +)" ) ) + .toMap() + .value( "script" ); + QVariant userScript = CalamaresUtils::yamlMapToVariant( YAML::Load( R"(--- script: - mktemp -d @@ROOT@@/calatestXXXXXXXX - "chown @@USER@@ @@ROOT@@/calatest*" - rm -rf @@ROOT@@/calatest* -)" ) ).toMap().value( "script" ); +)" ) ) + .toMap() + .value( "script" ); if ( !Calamares::JobQueue::instance() ) (void)new Calamares::JobQueue( nullptr ); @@ -188,29 +184,29 @@ script: qDebug() << "Expect WARNING, ERROR, WARNING"; // Doesn't use @@ROOT@@, so no failures - QVERIFY( bool(CommandList(plainScript, false, 10s ).run()) ); + QVERIFY( bool( CommandList( plainScript, false, 10s ).run() ) ); // Doesn't use @@ROOT@@, but does chroot, so fails - QVERIFY( !bool(CommandList(plainScript, true, 10s ).run()) ); + QVERIFY( !bool( CommandList( plainScript, true, 10s ).run() ) ); // Does use @@ROOT@@, which is not set, so fails - QVERIFY( !bool(CommandList(rootScript, false, 10s ).run()) ); + QVERIFY( !bool( CommandList( rootScript, false, 10s ).run() ) ); // .. fails for two reasons - QVERIFY( !bool(CommandList(rootScript, true, 10s ).run()) ); + QVERIFY( !bool( CommandList( rootScript, true, 10s ).run() ) ); gs->insert( "rootMountPoint", "/tmp" ); // Now that the root is set, two variants work .. still can't // chroot, unless the rootMountPoint contains a full system, // *and* we're allowed to chroot (ie. running tests as root). qDebug() << "Expect no output."; - QVERIFY( bool(CommandList(plainScript, false, 10s ).run()) ); - QVERIFY( bool(CommandList(rootScript, false, 10s ).run()) ); + QVERIFY( bool( CommandList( plainScript, false, 10s ).run() ) ); + QVERIFY( bool( CommandList( rootScript, false, 10s ).run() ) ); qDebug() << "Expect ERROR"; // But no user set yet - QVERIFY( !bool(CommandList(userScript, false, 10s ).run()) ); + QVERIFY( !bool( CommandList( userScript, false, 10s ).run() ) ); // Now play dangerous games with shell expansion gs->insert( "username", "`id -u`" ); - QVERIFY( bool(CommandList(userScript, false, 10s ).run()) ); + QVERIFY( bool( CommandList( userScript, false, 10s ).run() ) ); } From 8186d5730a332d2397ad1d3b9fe53bb1e653c989 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 1 Aug 2019 23:10:49 +0200 Subject: [PATCH 039/302] [contextualprocess] Apply current coding style --- .../ContextualProcessJob.cpp | 42 +++++++++++++------ .../contextualprocess/ContextualProcessJob.h | 4 +- src/modules/contextualprocess/Tests.cpp | 13 ++---- 3 files changed, 36 insertions(+), 23 deletions(-) diff --git a/src/modules/contextualprocess/ContextualProcessJob.cpp b/src/modules/contextualprocess/ContextualProcessJob.cpp index 5d6b20afc..1be4950c9 100644 --- a/src/modules/contextualprocess/ContextualProcessJob.cpp +++ b/src/modules/contextualprocess/ContextualProcessJob.cpp @@ -18,22 +18,22 @@ #include "ContextualProcessJob.h" -#include #include +#include #include #include "CalamaresVersion.h" -#include "JobQueue.h" #include "GlobalStorage.h" +#include "JobQueue.h" #include "utils/CommandList.h" #include "utils/Logger.h" #include "utils/Variant.h" -struct ValueCheck : public QPair +struct ValueCheck : public QPair< QString, CalamaresUtils::CommandList* > { ValueCheck( const QString& value, CalamaresUtils::CommandList* commands ) - : QPair(value, commands) + : QPair< QString, CalamaresUtils::CommandList* >( value, commands ) { } @@ -47,7 +47,7 @@ struct ValueCheck : public QPair QString value() const { return first; } CalamaresUtils::CommandList* commands() const { return second; } -} ; +}; struct ContextualProcessBinding { @@ -67,7 +67,9 @@ struct ContextualProcessBinding { checks.append( ValueCheck( value, commands ) ); if ( value == QString( "*" ) ) + { wildcard = commands; + } } Calamares::JobResult run( const QString& value ) const @@ -75,19 +77,23 @@ struct ContextualProcessBinding for ( const auto& c : checks ) { if ( value == c.value() ) + { return c.commands()->run(); + } } if ( wildcard ) + { return wildcard->run(); + } return Calamares::JobResult::ok(); } QString variable; - QList checks; - CalamaresUtils::CommandList* wildcard{ nullptr }; -} ; + QList< ValueCheck > checks; + CalamaresUtils::CommandList* wildcard { nullptr }; +}; ContextualProcessBinding::~ContextualProcessBinding() @@ -129,10 +135,14 @@ ContextualProcessJob::exec() { Calamares::JobResult r = binding->run( gs->value( binding->variable ).toString() ); if ( !r ) + { return r; + } } else + { cWarning() << "ContextualProcess checks for unknown variable" << binding->variable; + } } return Calamares::JobResult::ok(); } @@ -144,13 +154,17 @@ ContextualProcessJob::setConfigurationMap( const QVariantMap& configurationMap ) bool dontChroot = CalamaresUtils::getBool( configurationMap, "dontChroot", false ); int timeout = CalamaresUtils::getInteger( configurationMap, "timeout", 10 ); if ( timeout < 1 ) + { timeout = 10; + } for ( QVariantMap::const_iterator iter = configurationMap.cbegin(); iter != configurationMap.cend(); ++iter ) { QString variableName = iter.key(); if ( variableName.isEmpty() || ( variableName == "dontChroot" ) || ( variableName == "timeout" ) ) + { continue; + } if ( iter.value().type() != QVariant::Map ) { @@ -166,11 +180,13 @@ ContextualProcessJob::setConfigurationMap( const QVariantMap& configurationMap ) QString valueString = valueiter.key(); if ( variableName.isEmpty() ) { - cWarning() << moduleInstanceKey() << "variable" << variableName << "unrecognized value" << valueiter.key(); + cWarning() << moduleInstanceKey() << "variable" << variableName << "unrecognized value" + << valueiter.key(); continue; } - CalamaresUtils::CommandList* commands = new CalamaresUtils::CommandList( valueiter.value(), !dontChroot, std::chrono::seconds( timeout ) ); + CalamaresUtils::CommandList* commands + = new CalamaresUtils::CommandList( valueiter.value(), !dontChroot, std::chrono::seconds( timeout ) ); binding->append( valueString, commands ); } @@ -184,12 +200,14 @@ ContextualProcessJob::count() } int -ContextualProcessJob::count(const QString& variableName) +ContextualProcessJob::count( const QString& variableName ) { for ( const ContextualProcessBinding* binding : m_commands ) if ( binding->variable == variableName ) + { return binding->checks.count(); + } return -1; } -CALAMARES_PLUGIN_FACTORY_DEFINITION( ContextualProcessJobFactory, registerPlugin(); ) +CALAMARES_PLUGIN_FACTORY_DEFINITION( ContextualProcessJobFactory, registerPlugin< ContextualProcessJob >(); ) diff --git a/src/modules/contextualprocess/ContextualProcessJob.h b/src/modules/contextualprocess/ContextualProcessJob.h index fbc102058..2efbc5082 100644 --- a/src/modules/contextualprocess/ContextualProcessJob.h +++ b/src/modules/contextualprocess/ContextualProcessJob.h @@ -49,9 +49,9 @@ public: int count( const QString& variableName ); private: - QList m_commands; + QList< ContextualProcessBinding* > m_commands; }; CALAMARES_PLUGIN_FACTORY_DECLARATION( ContextualProcessJobFactory ) -#endif // CONTEXTUALPROCESSJOB_H +#endif // CONTEXTUALPROCESSJOB_H diff --git a/src/modules/contextualprocess/Tests.cpp b/src/modules/contextualprocess/Tests.cpp index 51319c220..f62726775 100644 --- a/src/modules/contextualprocess/Tests.cpp +++ b/src/modules/contextualprocess/Tests.cpp @@ -31,13 +31,9 @@ QTEST_GUILESS_MAIN( ContextualProcessTests ) using CommandList = CalamaresUtils::CommandList; -ContextualProcessTests::ContextualProcessTests() -{ -} +ContextualProcessTests::ContextualProcessTests() {} -ContextualProcessTests::~ContextualProcessTests() -{ -} +ContextualProcessTests::~ContextualProcessTests() {} void ContextualProcessTests::initTestCase() @@ -63,7 +59,6 @@ ContextualProcessTests::testProcessListSampleConfig() ContextualProcessJob job; job.setConfigurationMap( CalamaresUtils::yamlMapToVariant( doc ).toMap() ); - QCOMPARE(job.count(), 1); // Only "firmwareType" - QCOMPARE(job.count("firmwareType"), 4); + QCOMPARE( job.count(), 1 ); // Only "firmwareType" + QCOMPARE( job.count( "firmwareType" ), 4 ); } - From d76c33bd3aa7e7b7fa59118a590f3ccd1bc1213e Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 09:19:15 +0200 Subject: [PATCH 040/302] [tracking] Tidy code some more --- src/modules/tracking/TrackingJobs.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/modules/tracking/TrackingJobs.cpp b/src/modules/tracking/TrackingJobs.cpp index 26f0b67aa..bf71b541a 100644 --- a/src/modules/tracking/TrackingJobs.cpp +++ b/src/modules/tracking/TrackingJobs.cpp @@ -124,24 +124,32 @@ TrackingMachineNeonJob::prettyStatusMessage() const Calamares::JobResult TrackingMachineNeonJob::exec() { - int r = CalamaresUtils::System::instance()->targetEnvCall( "/bin/sh", - QString(), // Working dir - QString( - R"x(MACHINE_ID=`cat /etc/machine-id` + 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" ), +)x" ); + int r = CalamaresUtils::System::instance()->targetEnvCall( "/bin/sh", + QString(), // Working dir + script, std::chrono::seconds( 1 ) ); if ( r == 0 ) + { return Calamares::JobResult::ok(); + } else if ( r > 0 ) + { return Calamares::JobResult::error( tr( "Error in machine feedback configuration." ), tr( "Could not configure machine feedback correctly, script error %1." ).arg( r ) ); + } else + { return Calamares::JobResult::error( tr( "Error in machine feedback configuration." ), tr( "Could not configure machine feedback correctly, Calamares error %1." ).arg( r ) ); + } } From f1c133813cafe3d9f1e465624f7f3e19723db832 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 09:25:45 +0200 Subject: [PATCH 041/302] Changes: credits for recent PRs --- CHANGES | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGES b/CHANGES index a3c14296c..c84f245b0 100644 --- a/CHANGES +++ b/CHANGES @@ -6,13 +6,25 @@ website will have to do for older versions. # 3.2.12 (unreleased) # This release contains contributions from (alphabetically by first name): + - apt-ghetto - Bill Auger - embar ## Core ## + - Preliminary work to allow jobs to have a *weight* assigned to them + has been added. This will allow the progress bar to better reflect + progress by the amount of work done rather than purely by the + number of jobs. (Thanks to Bill Auger) + - Preliminary work has been added to post the installation log to a + pastebin for bug reporting. (Thanks to Bill Auger) + ## Modules ## + - *fstab* A new configuration key *efiMountOptions* has been added, to + allow setting filesystem options specifically for the EFI partition. + (Thanks to apt-ghetto) + # 3.2.11 (2019-07-06) # From dab841df0224ddf6b03a447cfe05b2a5edde9acc Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 09:27:54 +0200 Subject: [PATCH 042/302] [fstab] Tighten up the *efiMountOptions* documentation --- src/modules/fstab/fstab.conf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/fstab/fstab.conf b/src/modules/fstab/fstab.conf index 06a935e3a..b2f3de361 100644 --- a/src/modules/fstab/fstab.conf +++ b/src/modules/fstab/fstab.conf @@ -12,9 +12,9 @@ mountOptions: default: defaults,noatime btrfs: defaults,noatime,space_cache,autodefrag -# Mount options to use for the EFI System Partition. If not defined, it -# takes either the value of *vfat*, or if also missing, *default* from -# *mountOptions* +# Mount options to use for the EFI System Partition. If not defined, the +# *mountOptions* for *vfat* are used, or if that is not set either, +# *default* from *mountOptions*. efiMountOptions: umask=0077 # If a filesystem is on an SSD, add the following options. If a specific From f4034f629aa42b243acf1ee54c0908d09a031e46 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 09:32:31 +0200 Subject: [PATCH 043/302] CI: keep Esperanto in the "incomplete" list - Since QLocale does not support Esperanto, we can't effectively load it. --- ci/txstats.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ci/txstats.py b/ci/txstats.py index d29e7dc75..2edf1dd5b 100644 --- a/ci/txstats.py +++ b/ci/txstats.py @@ -56,6 +56,11 @@ def get_tx_stats(token): return 1 suppressed_languages = ( "es_ES", ) # In Transifex, but not used + # Some languages go into the "incomplete" list by definition, + # regardless of their completion status: this can have various reasons. + incomplete_languages = ( + "eo", # Not supported by QLocale + ) all_langs = [] @@ -66,6 +71,8 @@ def get_tx_stats(token): if lang_name in suppressed_languages: continue stats = languages[lang_name]["translated"]["percentage"] + if lang_name in incomplete_languages: + stats = 0.0 all_langs.append((stats, lang_name)) output_langs(all_langs, "complete", lambda s : s == 1.0) From d98788a40503fcf529e7ef3489b0648b71454c9d Mon Sep 17 00:00:00 2001 From: Calamares CI Date: Fri, 2 Aug 2019 09:35:59 +0200 Subject: [PATCH 044/302] i18n: [calamares] Automatic merge of Transifex translations --- lang/calamares_ast.ts | 24 ++++++++++++------------ lang/calamares_cs_CZ.ts | 8 ++++---- lang/calamares_ru.ts | 14 +++++++------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/lang/calamares_ast.ts b/lang/calamares_ast.ts index 75702a383..a9a310990 100644 --- a/lang/calamares_ast.ts +++ b/lang/calamares_ast.ts @@ -117,7 +117,7 @@ Set up - + Configuración @@ -243,7 +243,7 @@ Cancel setup without changing the system. - + Encaboxa la configuración ensin camudar el sistema. @@ -253,7 +253,7 @@ Setup Failed - + Falló la configuración @@ -283,12 +283,12 @@ &Set up now - + &Configurar agora &Set up - + &Configurar @@ -408,7 +408,7 @@ L'instalador va colar y van perdese tolos cambeos. %1 Setup Program - + Programa de configuración de %1 @@ -477,7 +477,7 @@ L'instalador va colar y van perdese tolos cambeos. %1 will be shrunk to %2MiB and a new %3MiB partition will be created for %4. - + %1 va redimensionase a %2MB y va crease una partición nueva de %3MB pa %4. @@ -1202,22 +1202,22 @@ L'instalador va colar y van perdese tolos cambeos. has at least %1 GiB available drive space - + tien polo menos %1 GiB d'espaciu disponible nel discu There is not enough drive space. At least %1 GiB is required. - + Nun hai espaciu abondu nel discu. Ríquense polo menos %1 GiB. has at least %1 GiB working memory - + tien polo menos %1 GiB memoria de trabayu The system does not have enough working memory. At least %1 GiB is required. - + El sistema nun tien abonda memoria de trabayu. Ríquense polo menos %1 GiB. @@ -2901,7 +2901,7 @@ Salida: This is an overview of what will happen once you start the setup procedure. - + Esto ye una previsualización de lo que va asoceder nel momentu qu'anicies el procesu de configuración. diff --git a/lang/calamares_cs_CZ.ts b/lang/calamares_cs_CZ.ts index beb4142fe..0b82ac35a 100644 --- a/lang/calamares_cs_CZ.ts +++ b/lang/calamares_cs_CZ.ts @@ -1536,7 +1536,7 @@ Instalační program bude ukončen a všechny změny ztraceny. No partitions are defined. - + Nejsou definovány žádné oddíly. @@ -1548,17 +1548,17 @@ Instalační program bude ukončen a všechny změny ztraceny. Root partition %1 is LUKS but no passphrase has been set. - + Kořenový oddíl %1 je LUKS, ale nebyla nastavena žádná heslová fráze. Could not create LUKS key file for root partition %1. - + Nedaří se vytvořit LUKS klíč pro kořenový oddíl %1. Could configure LUKS key file on partition %1. - + Nedaří se nastavit LUKS klíč pro oddíl %1.
diff --git a/lang/calamares_ru.ts b/lang/calamares_ru.ts index 4de6cc2aa..92533e925 100644 --- a/lang/calamares_ru.ts +++ b/lang/calamares_ru.ts @@ -99,7 +99,7 @@ Reload Stylesheet - + Перезагрузить таблицу стилей @@ -130,7 +130,7 @@ Job failed (%1) - + Задание не успешно (%1) @@ -220,7 +220,7 @@ System-requirements checking is complete. - + Проверка соответствия системным требованиям завершена. @@ -243,7 +243,7 @@ Cancel setup without changing the system. - + Отменить установку без изменения системы. @@ -524,7 +524,7 @@ The installer will quit and all changes will be lost. Reuse Swap - + Использовать существующий раздел подкачки @@ -2545,12 +2545,12 @@ Output: The filesystem %1 must be resized, but cannot. - + Необходимо, но не удаётся изменить размер файловой системы %1 The device %1 must be resized, but cannot - + Необходимо, но не удаётся изменить размер устройства %1 From 05daa225427f0edaafb89ada6ab8c604775f23fb Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 09:40:25 +0200 Subject: [PATCH 045/302] CMake: update language lists --- CMakeLists.txt | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cae89fc91..153def42a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -104,13 +104,15 @@ set( CALAMARES_DESCRIPTION_SUMMARY # checks for new languages and misspelled ones are done (that is, # copy these four lines to four backup lines, add "p", and then update # the original four lines with the current translations). -set( _tx_complete ca cs_CZ da de fr he hr hu ko lt pt_BR sq tr_TR - zh_TW ) -set( _tx_good ast en_GB es es_MX et fi_FI gl id it_IT ja nl pl - pt_PT ro ru sk zh_CN ) -set( _tx_ok ar bg el es_PR eu hi is mr nb sl sr sr@latin sv th - uk ) -set( _tx_incomplete be ca@valencia eo fa fr_CH gu kk kn lo mk ne_NP ur uz ) +# +# Total 60 languages +set( _tx_complete ca cs_CZ da de fi_FI fr he hi hr hu ja ko lt + pt_BR sq tr_TR zh_TW ) +set( _tx_good ast en_GB es es_MX et gl id it_IT nl pl pt_PT ru sk + zh_CN ) +set( _tx_ok ar bg el es_PR eu is mr nb ro sl sr sr@latin sv th uk ) +set( _tx_incomplete be ca@valencia eo fa fr_CH gu kk kn lo mk ne_NP + ur uz ) ### Required versions # From 735d5d2683454cc84cd77f57f0f92e7f517f9e6b Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 10:57:12 +0200 Subject: [PATCH 046/302] [packagechooser] Add stub of module Package chooser is a **low density** package selector -- unlike netinstall which offers a high density tree view -- for picking zero, one, or more items from a small collection of packages. This can be used, e.g., for "pick exactly one desktop environment", "pick zero or more text editors" which can then be installed by another module. The UI is big and shiny (rather than netinstall's text-based tree view) and isn't suitable for more than a dozen or so items. --- src/modules/packagechooser/CMakeLists.txt | 27 +++++ .../packagechooser/PackageChooserPage.cpp | 33 +++++ .../packagechooser/PackageChooserPage.h | 39 ++++++ .../packagechooser/PackageChooserViewStep.cpp | 113 ++++++++++++++++++ .../packagechooser/PackageChooserViewStep.h | 60 ++++++++++ src/modules/packagechooser/Tests.cpp | 38 ++++++ src/modules/packagechooser/Tests.h | 36 ++++++ src/modules/packagechooser/page_package.ui | 59 +++++++++ 8 files changed, 405 insertions(+) create mode 100644 src/modules/packagechooser/CMakeLists.txt create mode 100644 src/modules/packagechooser/PackageChooserPage.cpp create mode 100644 src/modules/packagechooser/PackageChooserPage.h create mode 100644 src/modules/packagechooser/PackageChooserViewStep.cpp create mode 100644 src/modules/packagechooser/PackageChooserViewStep.h create mode 100644 src/modules/packagechooser/Tests.cpp create mode 100644 src/modules/packagechooser/Tests.h create mode 100644 src/modules/packagechooser/page_package.ui diff --git a/src/modules/packagechooser/CMakeLists.txt b/src/modules/packagechooser/CMakeLists.txt new file mode 100644 index 000000000..0c739012a --- /dev/null +++ b/src/modules/packagechooser/CMakeLists.txt @@ -0,0 +1,27 @@ +find_package( Qt5 COMPONENTS Core Gui Widgets REQUIRED ) + +calamares_add_plugin( packagechooser + TYPE viewmodule + EXPORT_MACRO PLUGINDLLEXPORT_PRO + SOURCES + PackageChooserPage.cpp + PackageChooserViewStep.cpp + UI + page_package.ui + LINK_PRIVATE_LIBRARIES + calamaresui + SHARED_LIB +) + +if( ECM_FOUND AND BUILD_TESTING ) + ecm_add_test( + Tests.cpp + TEST_NAME + packagechooosertest + LINK_LIBRARIES + ${CALAMARES_LIBRARIES} + Qt5::Core + Qt5::Test + ) + calamares_automoc( packagechooosertest) +endif() diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp new file mode 100644 index 000000000..2f83e6728 --- /dev/null +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -0,0 +1,33 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 "PackageChooserPage.h" + +#include "ui_page_package.h" + +#include "utils/Logger.h" +#include "utils/Retranslator.h" + +#include + +PackageChooserPage::PackageChooserPage( QWidget* parent ) + : QWidget( parent ) + , ui( new Ui::PackageChooserPage ) +{ + ui->setupUi( this ); +} diff --git a/src/modules/packagechooser/PackageChooserPage.h b/src/modules/packagechooser/PackageChooserPage.h new file mode 100644 index 000000000..1bc46bef3 --- /dev/null +++ b/src/modules/packagechooser/PackageChooserPage.h @@ -0,0 +1,39 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 PACKAGECHOOSERPAGE_H +#define PACKAGECHOOSERPAGE_H + +#include + +namespace Ui +{ +class PackageChooserPage; +} + +class PackageChooserPage : public QWidget +{ + Q_OBJECT +public: + explicit PackageChooserPage( QWidget* parent = nullptr ); + +private: + Ui::PackageChooserPage* ui; +}; + +#endif // PACKAGECHOOSERPAGE_H diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp new file mode 100644 index 000000000..db45bea0b --- /dev/null +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -0,0 +1,113 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 "PackageChooserViewStep.h" + +#include "PackageChooserPage.h" + +#include "GlobalStorage.h" +#include "JobQueue.h" + +#include "utils/CalamaresUtilsSystem.h" +#include "utils/Logger.h" +#include "utils/Variant.h" + +#include +#include + +CALAMARES_PLUGIN_FACTORY_DEFINITION( PackageChooserViewStepFactory, registerPlugin< PackageChooserViewStep >(); ) + +PackageChooserViewStep::PackageChooserViewStep( QObject* parent ) + : Calamares::ViewStep( parent ) + , m_widget( nullptr ) +{ + emit nextStatusChanged( false ); +} + + +PackageChooserViewStep::~PackageChooserViewStep() +{ + if ( m_widget && m_widget->parent() == nullptr ) + { + m_widget->deleteLater(); + } +} + + +QString +PackageChooserViewStep::prettyName() const +{ + return tr( "Packages" ); +} + + +QWidget* +PackageChooserViewStep::widget() +{ + if ( !m_widget ) + { + m_widget = new PackageChooserPage( nullptr ); + } + return m_widget; +} + + +bool +PackageChooserViewStep::isNextEnabled() const +{ + return true; +} + + +bool +PackageChooserViewStep::isBackEnabled() const +{ + return true; +} + + +bool +PackageChooserViewStep::isAtBeginning() const +{ + return true; +} + + +bool +PackageChooserViewStep::isAtEnd() const +{ + return true; +} + + +void +PackageChooserViewStep::onLeave() +{ +} + +Calamares::JobList +PackageChooserViewStep::jobs() const +{ + Calamares::JobList l; + return l; +} + +void +PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap ) +{ +} diff --git a/src/modules/packagechooser/PackageChooserViewStep.h b/src/modules/packagechooser/PackageChooserViewStep.h new file mode 100644 index 000000000..a32d4caab --- /dev/null +++ b/src/modules/packagechooser/PackageChooserViewStep.h @@ -0,0 +1,60 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 PACKAGECHOOSERVIEWSTEP_H +#define PACKAGECHOOSERVIEWSTEP_H + +#include +#include +#include + +#include +#include +#include + +class PLUGINDLLEXPORT PackageChooserViewStep : public Calamares::ViewStep +{ + Q_OBJECT + +public: + explicit PackageChooserViewStep( QObject* parent = nullptr ); + virtual ~PackageChooserViewStep() override; + + QString prettyName() const override; + + QWidget* widget() override; + + bool isNextEnabled() const override; + bool isBackEnabled() const override; + + bool isAtBeginning() const override; + bool isAtEnd() const override; + + void onLeave() override; + + Calamares::JobList jobs() const override; + + void setConfigurationMap( const QVariantMap& configurationMap ) override; + +private: + QWidget* m_widget; +}; + +CALAMARES_PLUGIN_FACTORY_DECLARATION( PackageChooserViewStepFactory ) + +#endif // PACKAGECHOOSERVIEWSTEP_H diff --git a/src/modules/packagechooser/Tests.cpp b/src/modules/packagechooser/Tests.cpp new file mode 100644 index 000000000..c016f1808 --- /dev/null +++ b/src/modules/packagechooser/Tests.cpp @@ -0,0 +1,38 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 "Tests.h" + +#include + +QTEST_GUILESS_MAIN( PackageChooserTests ) + +PackageChooserTests::PackageChooserTests() {} + +PackageChooserTests::~PackageChooserTests() {} + +void +PackageChooserTests::initTestCase() +{ +} + +void +PackageChooserTests::testBogus() +{ + QVERIFY( true ); +} diff --git a/src/modules/packagechooser/Tests.h b/src/modules/packagechooser/Tests.h new file mode 100644 index 000000000..bc257f5a5 --- /dev/null +++ b/src/modules/packagechooser/Tests.h @@ -0,0 +1,36 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 PACKAGECHOOSERTESTS_H +#define PACKAGECHOOSERTESTS_H + +#include + +class PackageChooserTests : public QObject +{ + Q_OBJECT +public: + PackageChooserTests(); + ~PackageChooserTests() override; + +private Q_SLOTS: + void initTestCase(); + void testBogus(); +}; + +#endif diff --git a/src/modules/packagechooser/page_package.ui b/src/modules/packagechooser/page_package.ui new file mode 100644 index 000000000..18c2f81fd --- /dev/null +++ b/src/modules/packagechooser/page_package.ui @@ -0,0 +1,59 @@ + + + PackageChooserPage + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + 9 + 19 + 341 + 261 + + + + + + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + + + + + From 727290f75e9286e6819122295f5955c117f8406b Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 11:09:12 +0200 Subject: [PATCH 047/302] [packagechooser] Handle translation events (stub) --- src/modules/packagechooser/PackageChooserPage.cpp | 11 +++++++++++ src/modules/packagechooser/PackageChooserPage.h | 3 +++ 2 files changed, 14 insertions(+) diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index 2f83e6728..5524bd103 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -30,4 +30,15 @@ PackageChooserPage::PackageChooserPage( QWidget* parent ) , ui( new Ui::PackageChooserPage ) { ui->setupUi( this ); + CALAMARES_RETRANSLATE( + updateLabels(); + ) +} + +void +PackageChooserPage::updateLabels() +{ + ui->productName->setText( QString() ); + ui->productScreenshot->hide(); + ui->productDescription->setText( tr( "Please pick a product from the list." ) ); } diff --git a/src/modules/packagechooser/PackageChooserPage.h b/src/modules/packagechooser/PackageChooserPage.h index 1bc46bef3..02c46fc3e 100644 --- a/src/modules/packagechooser/PackageChooserPage.h +++ b/src/modules/packagechooser/PackageChooserPage.h @@ -32,6 +32,9 @@ class PackageChooserPage : public QWidget public: explicit PackageChooserPage( QWidget* parent = nullptr ); +public slots: + void updateLabels(); + private: Ui::PackageChooserPage* ui; }; From d1a85ba5ca5f333e1564d3a5f7a8e29127ccf8ff Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 13:05:46 +0200 Subject: [PATCH 048/302] [packagechooser] Add a model for the list to use - Model contents currently hard-coded --- src/modules/packagechooser/CMakeLists.txt | 1 + .../packagechooser/PackageChooserPage.cpp | 18 +++- .../packagechooser/PackageChooserPage.h | 4 + .../packagechooser/PackageChooserViewStep.cpp | 35 +++++++ .../packagechooser/PackageChooserViewStep.h | 14 ++- src/modules/packagechooser/PackageModel.cpp | 93 +++++++++++++++++++ src/modules/packagechooser/PackageModel.h | 62 +++++++++++++ 7 files changed, 220 insertions(+), 7 deletions(-) create mode 100644 src/modules/packagechooser/PackageModel.cpp create mode 100644 src/modules/packagechooser/PackageModel.h diff --git a/src/modules/packagechooser/CMakeLists.txt b/src/modules/packagechooser/CMakeLists.txt index 0c739012a..525921602 100644 --- a/src/modules/packagechooser/CMakeLists.txt +++ b/src/modules/packagechooser/CMakeLists.txt @@ -6,6 +6,7 @@ calamares_add_plugin( packagechooser SOURCES PackageChooserPage.cpp PackageChooserViewStep.cpp + PackageModel.cpp UI page_package.ui LINK_PRIVATE_LIBRARIES diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index 5524bd103..215adeeef 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -30,9 +30,7 @@ PackageChooserPage::PackageChooserPage( QWidget* parent ) , ui( new Ui::PackageChooserPage ) { ui->setupUi( this ); - CALAMARES_RETRANSLATE( - updateLabels(); - ) + CALAMARES_RETRANSLATE( updateLabels(); ) } void @@ -42,3 +40,17 @@ PackageChooserPage::updateLabels() ui->productScreenshot->hide(); ui->productDescription->setText( tr( "Please pick a product from the list." ) ); } + +void +PackageChooserPage::setModel( QAbstractItemModel* model ) +{ + ui->products->setModel( model ); +} + +void +PackageChooserPage::currentChanged( const QModelIndex& current ) +{ + updateLabels(); + cDebug() << "Current updated to" << current.row(); + cDebug() << ui->products->model()->data( current, Qt::DisplayRole ); +} diff --git a/src/modules/packagechooser/PackageChooserPage.h b/src/modules/packagechooser/PackageChooserPage.h index 02c46fc3e..db5540312 100644 --- a/src/modules/packagechooser/PackageChooserPage.h +++ b/src/modules/packagechooser/PackageChooserPage.h @@ -19,6 +19,7 @@ #ifndef PACKAGECHOOSERPAGE_H #define PACKAGECHOOSERPAGE_H +#include #include namespace Ui @@ -32,8 +33,11 @@ class PackageChooserPage : public QWidget public: explicit PackageChooserPage( QWidget* parent = nullptr ); + void setModel( QAbstractItemModel* model ); + public slots: void updateLabels(); + void currentChanged( const QModelIndex& current ); private: Ui::PackageChooserPage* ui; diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index db45bea0b..3ff2ac636 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -19,6 +19,7 @@ #include "PackageChooserViewStep.h" #include "PackageChooserPage.h" +#include "PackageModel.h" #include "GlobalStorage.h" #include "JobQueue.h" @@ -35,6 +36,7 @@ CALAMARES_PLUGIN_FACTORY_DEFINITION( PackageChooserViewStepFactory, registerPlug PackageChooserViewStep::PackageChooserViewStep( QObject* parent ) : Calamares::ViewStep( parent ) , m_widget( nullptr ) + , m_model( nullptr ) { emit nextStatusChanged( false ); } @@ -46,6 +48,7 @@ PackageChooserViewStep::~PackageChooserViewStep() { m_widget->deleteLater(); } + delete m_model; } @@ -62,6 +65,10 @@ PackageChooserViewStep::widget() if ( !m_widget ) { m_widget = new PackageChooserPage( nullptr ); + if ( m_model ) + { + hookupModel(); + } } return m_widget; } @@ -110,4 +117,32 @@ PackageChooserViewStep::jobs() const void PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { + // TODO: use the configurationMap + + if ( !m_model ) + { + + m_model = new PackageListModel( nullptr ); + m_model->addPackage( PackageItem { "kde", "kde", "Plasma", "Plasma Desktop" } ); + m_model->addPackage( + PackageItem { "gnome", "gnome", "GNOME", "GNU Networked Object Modeling Environment Desktop" } ); + + + if ( m_widget ) + { + hookupModel(); + } + } +} + +void +PackageChooserViewStep::hookupModel() +{ + if ( !m_model || !m_widget ) + { + cError() << "Can't hook up model until widget and model both exist."; + return; + } + + m_widget->setModel( m_model ); } diff --git a/src/modules/packagechooser/PackageChooserViewStep.h b/src/modules/packagechooser/PackageChooserViewStep.h index a32d4caab..56fbf5d3a 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.h +++ b/src/modules/packagechooser/PackageChooserViewStep.h @@ -19,14 +19,17 @@ #ifndef PACKAGECHOOSERVIEWSTEP_H #define PACKAGECHOOSERVIEWSTEP_H -#include -#include -#include +#include "PluginDllMacro.h" +#include "utils/PluginFactory.h" +#include "viewpages/ViewStep.h" #include #include #include +class PackageChooserPage; +class PackageListModel; + class PLUGINDLLEXPORT PackageChooserViewStep : public Calamares::ViewStep { Q_OBJECT @@ -52,7 +55,10 @@ public: void setConfigurationMap( const QVariantMap& configurationMap ) override; private: - QWidget* m_widget; + void hookupModel(); + + PackageChooserPage* m_widget; + PackageListModel* m_model; }; CALAMARES_PLUGIN_FACTORY_DECLARATION( PackageChooserViewStepFactory ) diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp new file mode 100644 index 000000000..1f6346666 --- /dev/null +++ b/src/modules/packagechooser/PackageModel.cpp @@ -0,0 +1,93 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 "PackageModel.h" + +#include "utils/Logger.h" + +PackageItem +PackageItem::fromAppStream( const QString& filename ) +{ + // TODO: implement this + return PackageItem {}; +} + +PackageItem::PackageItem() {} + +PackageItem::PackageItem( const QString& a_id, + const QString& a_package, + const QString& a_name, + const QString& a_description ) + : id( a_id ) + , package( a_package ) + , name( a_name ) + , description( a_description ) +{ +} + + +PackageListModel::PackageListModel( QObject* parent ) + : QAbstractListModel( parent ) +{ +} + +PackageListModel::PackageListModel( PackageList&& items, QObject* parent ) + : QAbstractListModel( parent ) + , m_packages( std::move( items ) ) +{ +} + +PackageListModel::~PackageListModel() {} + +void +PackageListModel::addPackage( PackageItem&& p ) +{ + int c = m_packages.count(); + beginInsertRows( QModelIndex(), c, c ); + m_packages.append( p ); + endInsertRows(); +} + +int +PackageListModel::rowCount( const QModelIndex& index ) const +{ + // For lists, valid indexes have zero children; only the root index has them + return index.isValid() ? 0 : m_packages.count(); +} + +QVariant +PackageListModel::data( const QModelIndex& index, int role ) const +{ + cDebug() << "Data" << m_packages.count() << index.isValid() << ( index.isValid() ? index.row() : -1 ); + if ( !index.isValid() ) + { + return QVariant(); + } + int row = index.row(); + if ( row >= m_packages.count() || row < 0 ) + { + return QVariant(); + } + + if ( role == Qt::DisplayRole ) + { + return m_packages[ row ].name; + } + + return QVariant(); +} diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h new file mode 100644 index 000000000..c00e55c0a --- /dev/null +++ b/src/modules/packagechooser/PackageModel.h @@ -0,0 +1,62 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 PACKAGEMODEL_H +#define PACKAGEMODEL_H + +#include +#include +#include + +struct PackageItem +{ + QString id; + // TODO: may need more than one + QString package; + // TODO: name and description are localized + QString name; + QString description; + // TODO: may be more than one + // QPixmap screenshot; + + PackageItem(); + PackageItem( const QString& id, const QString& package, const QString& name, const QString& description ); + + // TODO: implement this + PackageItem fromAppStream( const QString& filename ); +}; + +using PackageList = QVector< PackageItem >; + +class PackageListModel : public QAbstractListModel +{ +public: + PackageListModel( PackageList&& items, QObject* parent ); + PackageListModel( QObject* parent ); + virtual ~PackageListModel(); + + void addPackage( PackageItem&& p ); + + int rowCount( const QModelIndex& index ) const override; + QVariant data( const QModelIndex& index, int role ) const override; + +private: + PackageList m_packages; +}; + +#endif From f8d159dfa49dbd820ed3a3945e0d46da4e953a61 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 15:32:14 +0200 Subject: [PATCH 049/302] [packagechooser] Massage layout a bit --- src/modules/packagechooser/page_package.ui | 91 ++++++++++++---------- 1 file changed, 49 insertions(+), 42 deletions(-) diff --git a/src/modules/packagechooser/page_package.ui b/src/modules/packagechooser/page_package.ui index 18c2f81fd..1ba032ed2 100644 --- a/src/modules/packagechooser/page_package.ui +++ b/src/modules/packagechooser/page_package.ui @@ -1,58 +1,65 @@ PackageChooserPage - + 0 0 400 - 300 + 500 + + + 0 + 1 + + Form - - - - 9 - 19 - 341 - 261 - - - - - - - - - - - - TextLabel - - - - - - - TextLabel - - - - - - - TextLabel - - - - - - - + + + + + + + + 0 + 1 + + + + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + + From dc5cdbb38cad5206b03893beba169506529f507c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 16:07:47 +0200 Subject: [PATCH 050/302] [packagechooser] Update other parts of the window on selection --- .../packagechooser/PackageChooserPage.cpp | 44 ++++++++++++++----- .../packagechooser/PackageChooserPage.h | 5 ++- src/modules/packagechooser/PackageModel.cpp | 1 - src/modules/packagechooser/PackageModel.h | 9 +++- 4 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index 215adeeef..a474e7536 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -28,29 +28,51 @@ PackageChooserPage::PackageChooserPage( QWidget* parent ) : QWidget( parent ) , ui( new Ui::PackageChooserPage ) + , m_introduction( QString(), + QString(), + tr( "Package Selection" ), + tr( "Please pick a product from the list. The selected product will be installed." ) ) { ui->setupUi( this ); CALAMARES_RETRANSLATE( updateLabels(); ) } +void +PackageChooserPage::currentChanged( const QModelIndex& index ) +{ + if ( !index.isValid() || !ui->products->selectionModel()->hasSelection() ) + { + ui->productName->setText( m_introduction.name ); + ui->productScreenshot->setPixmap( m_introduction.screenshot ); + ui->productDescription->setText( m_introduction.description ); + } + else + { + ui->productName->setText( QString::number( index.row() ) ); + ui->productScreenshot->hide(); + ui->productDescription->setText( "derp" ); + } +} + void PackageChooserPage::updateLabels() { - ui->productName->setText( QString() ); - ui->productScreenshot->hide(); - ui->productDescription->setText( tr( "Please pick a product from the list." ) ); + if ( ui && ui->products && ui->products->selectionModel() ) + { + currentChanged( ui->products->selectionModel()->currentIndex() ); + } + else + { + currentChanged( QModelIndex() ); + } } void PackageChooserPage::setModel( QAbstractItemModel* model ) { ui->products->setModel( model ); -} - -void -PackageChooserPage::currentChanged( const QModelIndex& current ) -{ - updateLabels(); - cDebug() << "Current updated to" << current.row(); - cDebug() << ui->products->model()->data( current, Qt::DisplayRole ); + connect( ui->products->selectionModel(), + &QItemSelectionModel::selectionChanged, + this, + &PackageChooserPage::updateLabels ); } diff --git a/src/modules/packagechooser/PackageChooserPage.h b/src/modules/packagechooser/PackageChooserPage.h index db5540312..031abad69 100644 --- a/src/modules/packagechooser/PackageChooserPage.h +++ b/src/modules/packagechooser/PackageChooserPage.h @@ -19,6 +19,8 @@ #ifndef PACKAGECHOOSERPAGE_H #define PACKAGECHOOSERPAGE_H +#include "PackageModel.h" + #include #include @@ -36,11 +38,12 @@ public: void setModel( QAbstractItemModel* model ); public slots: + void currentChanged( const QModelIndex& index ); void updateLabels(); - void currentChanged( const QModelIndex& current ); private: Ui::PackageChooserPage* ui; + PackageItem m_introduction; }; #endif // PACKAGECHOOSERPAGE_H diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index 1f6346666..86e18aa88 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -73,7 +73,6 @@ PackageListModel::rowCount( const QModelIndex& index ) const QVariant PackageListModel::data( const QModelIndex& index, int role ) const { - cDebug() << "Data" << m_packages.count() << index.isValid() << ( index.isValid() ? index.row() : -1 ); if ( !index.isValid() ) { return QVariant(); diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index c00e55c0a..67715e197 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -21,6 +21,7 @@ #include #include +#include #include struct PackageItem @@ -32,9 +33,15 @@ struct PackageItem QString name; QString description; // TODO: may be more than one - // QPixmap screenshot; + QPixmap screenshot; + /// @brief Create blank PackageItem PackageItem(); + /** @brief Creates a PackageItem from given strings + * + * This constructor sets all the text members, + * but leaves the screenshot blank. Set that separately. + */ PackageItem( const QString& id, const QString& package, const QString& name, const QString& description ); // TODO: implement this From a32dcdad869d1544e46d6e7651d2768967e2983d Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 16:25:26 +0200 Subject: [PATCH 051/302] [packagechooser] Support multiple selection modes --- .../packagechooser/PackageChooserPage.cpp | 12 ++++++- .../packagechooser/PackageChooserPage.h | 2 +- .../packagechooser/PackageChooserViewStep.cpp | 32 +++++++++++++++++-- .../packagechooser/PackageChooserViewStep.h | 3 ++ src/modules/packagechooser/PackageModel.h | 8 +++++ 5 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index a474e7536..307b1b861 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -25,7 +25,7 @@ #include -PackageChooserPage::PackageChooserPage( QWidget* parent ) +PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent ) : QWidget( parent ) , ui( new Ui::PackageChooserPage ) , m_introduction( QString(), @@ -35,6 +35,16 @@ PackageChooserPage::PackageChooserPage( QWidget* parent ) { ui->setupUi( this ); CALAMARES_RETRANSLATE( updateLabels(); ) + + switch( mode ) + { + case PackageChooserMode::Optional: + case PackageChooserMode::Exclusive: + ui->products->setSelectionMode( QAbstractItemView::SingleSelection ); + case PackageChooserMode::Multiple: + case PackageChooserMode::RequiredMultiple: + ui->products->setSelectionMode( QAbstractItemView::ExtendedSelection ); + } } void diff --git a/src/modules/packagechooser/PackageChooserPage.h b/src/modules/packagechooser/PackageChooserPage.h index 031abad69..483fd5d0a 100644 --- a/src/modules/packagechooser/PackageChooserPage.h +++ b/src/modules/packagechooser/PackageChooserPage.h @@ -33,7 +33,7 @@ class PackageChooserPage : public QWidget { Q_OBJECT public: - explicit PackageChooserPage( QWidget* parent = nullptr ); + explicit PackageChooserPage( PackageChooserMode mode, QWidget* parent = nullptr ); void setModel( QAbstractItemModel* model ); diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 3ff2ac636..2a5cc8073 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -37,6 +37,7 @@ PackageChooserViewStep::PackageChooserViewStep( QObject* parent ) : Calamares::ViewStep( parent ) , m_widget( nullptr ) , m_model( nullptr ) + , m_mode( PackageChooserMode::Optional ) { emit nextStatusChanged( false ); } @@ -64,7 +65,7 @@ PackageChooserViewStep::widget() { if ( !m_widget ) { - m_widget = new PackageChooserPage( nullptr ); + m_widget = new PackageChooserPage( m_mode, nullptr ); if ( m_model ) { hookupModel(); @@ -77,7 +78,34 @@ PackageChooserViewStep::widget() bool PackageChooserViewStep::isNextEnabled() const { - return true; + if ( !m_model ) + { + return false; + } + + if ( !m_widget ) + { + // No way to have changed anything + return true; + } + + switch( m_mode ) + { + case PackageChooserMode::Optional: + // zero or one + return false; + case PackageChooserMode::Exclusive: + // exactly one + return false; + case PackageChooserMode::Multiple: + // zero or more + return true; + case PackageChooserMode::RequiredMultiple: + // one or more + return false; + } + + NOTREACHED return true; } diff --git a/src/modules/packagechooser/PackageChooserViewStep.h b/src/modules/packagechooser/PackageChooserViewStep.h index 56fbf5d3a..ed33c3e46 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.h +++ b/src/modules/packagechooser/PackageChooserViewStep.h @@ -23,6 +23,8 @@ #include "utils/PluginFactory.h" #include "viewpages/ViewStep.h" +#include "PackageModel.h" + #include #include #include @@ -59,6 +61,7 @@ private: PackageChooserPage* m_widget; PackageListModel* m_model; + PackageChooserMode m_mode; }; CALAMARES_PLUGIN_FACTORY_DECLARATION( PackageChooserViewStepFactory ) diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index 67715e197..6d150802f 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -24,6 +24,14 @@ #include #include +enum class PackageChooserMode +{ + Optional, // zero or one + Exclusive, // exactly one + Multiple, // zero or more + RequiredMultiple // one or more +}; + struct PackageItem { QString id; From 86e2e6242f999c79650d60d7d9cddffe5f666ec9 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 16:26:10 +0200 Subject: [PATCH 052/302] [packagechooser] Warn about weird calling orders --- src/modules/packagechooser/PackageChooserViewStep.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 2a5cc8073..705958849 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -70,6 +70,10 @@ PackageChooserViewStep::widget() { hookupModel(); } + else + { + cWarning() << "PackageChooser Widget created before model."; + } } return m_widget; } From 2272d2ab430d866e21c4cd6291a212fbea56a2ed Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 16:43:10 +0200 Subject: [PATCH 053/302] [packagechooser] Add selection modes - Introduce different selection modes (most don't work yet) - Use model data in the main widget --- .../packagechooser/PackageChooserPage.cpp | 22 +++++++++------- .../packagechooser/PackageChooserViewStep.cpp | 26 +++++++++---------- src/modules/packagechooser/PackageModel.cpp | 10 ++++++- src/modules/packagechooser/PackageModel.h | 9 ++++++- 4 files changed, 42 insertions(+), 25 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index 307b1b861..174f7efe1 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -36,14 +36,14 @@ PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent ui->setupUi( this ); CALAMARES_RETRANSLATE( updateLabels(); ) - switch( mode ) + switch ( mode ) { - case PackageChooserMode::Optional: - case PackageChooserMode::Exclusive: - ui->products->setSelectionMode( QAbstractItemView::SingleSelection ); - case PackageChooserMode::Multiple: - case PackageChooserMode::RequiredMultiple: - ui->products->setSelectionMode( QAbstractItemView::ExtendedSelection ); + case PackageChooserMode::Optional: + case PackageChooserMode::Exclusive: + ui->products->setSelectionMode( QAbstractItemView::SingleSelection ); + case PackageChooserMode::Multiple: + case PackageChooserMode::RequiredMultiple: + ui->products->setSelectionMode( QAbstractItemView::ExtendedSelection ); } } @@ -58,9 +58,11 @@ PackageChooserPage::currentChanged( const QModelIndex& index ) } else { - ui->productName->setText( QString::number( index.row() ) ); - ui->productScreenshot->hide(); - ui->productDescription->setText( "derp" ); + const auto* model = ui->products->model(); + + ui->productName->setText( model->data( index, PackageListModel::NameRole ).toString() ); + ui->productScreenshot->setPixmap( model->data( index, PackageListModel::ScreenshotRole ).value< QPixmap >() ); + ui->productDescription->setText( model->data( index, PackageListModel::DescriptionRole ).toString() ); } } diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 705958849..e125cdba4 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -93,20 +93,20 @@ PackageChooserViewStep::isNextEnabled() const return true; } - switch( m_mode ) + switch ( m_mode ) { - case PackageChooserMode::Optional: - // zero or one - return false; - case PackageChooserMode::Exclusive: - // exactly one - return false; - case PackageChooserMode::Multiple: - // zero or more - return true; - case PackageChooserMode::RequiredMultiple: - // one or more - return false; + case PackageChooserMode::Optional: + // zero or one + return false; + case PackageChooserMode::Exclusive: + // exactly one + return false; + case PackageChooserMode::Multiple: + // zero or more + return true; + case PackageChooserMode::RequiredMultiple: + // one or more + return false; } NOTREACHED return true; diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index 86e18aa88..fc19fda47 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -83,10 +83,18 @@ PackageListModel::data( const QModelIndex& index, int role ) const return QVariant(); } - if ( role == Qt::DisplayRole ) + if ( role == Qt::DisplayRole /* Also PackageNameRole */ ) { return m_packages[ row ].name; } + else if ( role == DescriptionRole ) + { + return m_packages[ row ].description; + } + else if ( role == ScreenshotRole ) + { + return m_packages[ row ].screenshot; + } return QVariant(); } diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index 6d150802f..61e2864a9 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -27,7 +27,7 @@ enum class PackageChooserMode { Optional, // zero or one - Exclusive, // exactly one + Exclusive, // exactly one Multiple, // zero or more RequiredMultiple // one or more }; @@ -70,6 +70,13 @@ public: int rowCount( const QModelIndex& index ) const override; QVariant data( const QModelIndex& index, int role ) const override; + enum Roles : int + { + NameRole = Qt::DisplayRole, + DescriptionRole = Qt::UserRole, + ScreenshotRole + }; + private: PackageList m_packages; }; From 7609546d8bebd96d037a1e8eb77c0dc779ca746d Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 17:02:02 +0200 Subject: [PATCH 054/302] [packagechooser] Add screenshots for example --- src/modules/packagechooser/CMakeLists.txt | 2 ++ .../packagechooser/PackageChooserPage.cpp | 3 +++ src/modules/packagechooser/images/gnome.png | Bin 0 -> 5739 bytes src/modules/packagechooser/images/kde.png | Bin 0 -> 4678 bytes .../packagechooser/images/no-selection.png | Bin 0 -> 4618 bytes src/modules/packagechooser/packagechooser.qrc | 7 +++++++ 6 files changed, 12 insertions(+) create mode 100644 src/modules/packagechooser/images/gnome.png create mode 100644 src/modules/packagechooser/images/kde.png create mode 100644 src/modules/packagechooser/images/no-selection.png create mode 100644 src/modules/packagechooser/packagechooser.qrc diff --git a/src/modules/packagechooser/CMakeLists.txt b/src/modules/packagechooser/CMakeLists.txt index 525921602..483092800 100644 --- a/src/modules/packagechooser/CMakeLists.txt +++ b/src/modules/packagechooser/CMakeLists.txt @@ -7,6 +7,8 @@ calamares_add_plugin( packagechooser PackageChooserPage.cpp PackageChooserViewStep.cpp PackageModel.cpp + RESOURCES + packagechooser.qrc UI page_package.ui LINK_PRIVATE_LIBRARIES diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index 174f7efe1..23d3b837b 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -33,6 +33,9 @@ PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent tr( "Package Selection" ), tr( "Please pick a product from the list. The selected product will be installed." ) ) { + m_introduction.screenshot = QPixmap( QStringLiteral( ":/images/no-selection.png" ) ); + cDebug() << m_introduction.screenshot; + ui->setupUi( this ); CALAMARES_RETRANSLATE( updateLabels(); ) diff --git a/src/modules/packagechooser/images/gnome.png b/src/modules/packagechooser/images/gnome.png new file mode 100644 index 0000000000000000000000000000000000000000..f9f3901e14aeafc94babdf08bb5ffeb99af836a7 GIT binary patch literal 5739 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 J3*eT){{=a!jIsa# literal 0 HcmV?d00001 diff --git a/src/modules/packagechooser/images/kde.png b/src/modules/packagechooser/images/kde.png new file mode 100644 index 0000000000000000000000000000000000000000..02f3e70ea21282afa79d367f05d602c33cb5ddd3 GIT binary patch literal 4678 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 literal 0 HcmV?d00001 diff --git a/src/modules/packagechooser/images/no-selection.png b/src/modules/packagechooser/images/no-selection.png new file mode 100644 index 0000000000000000000000000000000000000000..f9dbbbac45d0b03667f66be54664fdc5dce71983 GIT binary patch literal 4618 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 literal 0 HcmV?d00001 diff --git a/src/modules/packagechooser/packagechooser.qrc b/src/modules/packagechooser/packagechooser.qrc new file mode 100644 index 000000000..9212c2f93 --- /dev/null +++ b/src/modules/packagechooser/packagechooser.qrc @@ -0,0 +1,7 @@ + + + images/no-selection.png + images/kde.png + images/gnome.png + + From 86d8db6bbf92e77981532d9409a685b953711fe3 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 17:06:03 +0200 Subject: [PATCH 055/302] [packagechooser] Enforce selection mode on the next-button --- .../packagechooser/PackageChooserPage.cpp | 7 +++++++ .../packagechooser/PackageChooserPage.h | 5 +++++ .../packagechooser/PackageChooserViewStep.cpp | 18 +++++++++--------- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index 23d3b837b..f0f7cb04c 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -80,6 +80,7 @@ PackageChooserPage::updateLabels() { currentChanged( QModelIndex() ); } + emit selectionChanged(); } void @@ -91,3 +92,9 @@ PackageChooserPage::setModel( QAbstractItemModel* model ) this, &PackageChooserPage::updateLabels ); } + +bool +PackageChooserPage::hasSelection() const +{ + return ui && ui->products && ui->products->selectionModel() && ui->products->selectionModel()->hasSelection(); +} diff --git a/src/modules/packagechooser/PackageChooserPage.h b/src/modules/packagechooser/PackageChooserPage.h index 483fd5d0a..8f9fde11f 100644 --- a/src/modules/packagechooser/PackageChooserPage.h +++ b/src/modules/packagechooser/PackageChooserPage.h @@ -37,10 +37,15 @@ public: void setModel( QAbstractItemModel* model ); + bool hasSelection() const; + public slots: void currentChanged( const QModelIndex& index ); void updateLabels(); +signals: + void selectionChanged(); + private: Ui::PackageChooserPage* ui; PackageItem m_introduction; diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index e125cdba4..1379f5dd6 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -37,7 +37,7 @@ PackageChooserViewStep::PackageChooserViewStep( QObject* parent ) : Calamares::ViewStep( parent ) , m_widget( nullptr ) , m_model( nullptr ) - , m_mode( PackageChooserMode::Optional ) + , m_mode( PackageChooserMode::Exclusive ) { emit nextStatusChanged( false ); } @@ -66,6 +66,10 @@ PackageChooserViewStep::widget() if ( !m_widget ) { m_widget = new PackageChooserPage( m_mode, nullptr ); + connect( m_widget, &PackageChooserPage::selectionChanged, [=]() { + emit nextStatusChanged( this->isNextEnabled() ); + } ); + if ( m_model ) { hookupModel(); @@ -96,17 +100,13 @@ PackageChooserViewStep::isNextEnabled() const switch ( m_mode ) { case PackageChooserMode::Optional: - // zero or one - return false; - case PackageChooserMode::Exclusive: - // exactly one - return false; case PackageChooserMode::Multiple: - // zero or more + // zero or one OR zero or more return true; + case PackageChooserMode::Exclusive: case PackageChooserMode::RequiredMultiple: - // one or more - return false; + // exactly one OR one or more + return m_widget->hasSelection(); } NOTREACHED return true; From ab7374628b9eed73650c0b6260b155499e6fe2cd Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 17:17:53 +0200 Subject: [PATCH 056/302] [packagechooser] Use sample screenshots --- .../packagechooser/PackageChooserViewStep.cpp | 4 ++-- src/modules/packagechooser/PackageModel.cpp | 13 +++++++++++++ src/modules/packagechooser/PackageModel.h | 6 ++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 1379f5dd6..9b3c174da 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -155,9 +155,9 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap { m_model = new PackageListModel( nullptr ); - m_model->addPackage( PackageItem { "kde", "kde", "Plasma", "Plasma Desktop" } ); + m_model->addPackage( PackageItem { "kde", "kde", "Plasma", "Plasma Desktop", ":/images/kde.png" } ); m_model->addPackage( - PackageItem { "gnome", "gnome", "GNOME", "GNU Networked Object Modeling Environment Desktop" } ); + PackageItem { "gnome", "gnome", "GNOME", "GNU Networked Object Modeling Environment Desktop", ":/images/gnome.png" } ); if ( m_widget ) diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index fc19fda47..7798b33bd 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -40,6 +40,19 @@ PackageItem::PackageItem( const QString& a_id, { } +PackageItem::PackageItem( const QString& a_id, + const QString& a_package, + const QString& a_name, + const QString& a_description, + const QString& screenshotPath ) + : id( a_id ) + , package( a_package ) + , name( a_name ) + , description( a_description ) + , screenshot( screenshotPath ) +{ +} + PackageListModel::PackageListModel( QObject* parent ) : QAbstractListModel( parent ) diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index 61e2864a9..7db668df4 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -52,6 +52,12 @@ struct PackageItem */ PackageItem( const QString& id, const QString& package, const QString& name, const QString& description ); + PackageItem( const QString& id, + const QString& package, + const QString& name, + const QString& description, + const QString& screenshotPath ); + // TODO: implement this PackageItem fromAppStream( const QString& filename ); }; From 9d026862a87748d3caeeabd88be92c8c981e10e6 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 23:20:45 +0200 Subject: [PATCH 057/302] [packagechooser] Provide names for selection mode --- src/modules/packagechooser/PackageModel.cpp | 20 ++++++++++++++++++++ src/modules/packagechooser/PackageModel.h | 4 ++++ 2 files changed, 24 insertions(+) diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index 7798b33bd..3546d9e42 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -20,6 +20,26 @@ #include "utils/Logger.h" +const NamedEnumTable< PackageChooserMode >& +roleNames() +{ + static const NamedEnumTable< PackageChooserMode > names { + { "optional", PackageChooserMode::Optional }, + { "exclusive", PackageChooserMode::Exclusive }, + { "multiple", PackageChooserMode::Multiple }, + { "requiredmultiple", + PackageChooserMode::RequiredMultiple }, + // and a bunch of aliases + { "zero-or-one", PackageChooserMode::Optional }, + { "radio", PackageChooserMode::Exclusive }, + { "one", PackageChooserMode::Exclusive }, + { "set", PackageChooserMode::Multiple }, + { "zero-or-more", PackageChooserMode::Multiple }, + { "required", PackageChooserMode::RequiredMultiple }, + { "one-or-more", PackageChooserMode::RequiredMultiple } }; + return names; +} + PackageItem PackageItem::fromAppStream( const QString& filename ) { diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index 7db668df4..ed5ac4b24 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -19,6 +19,8 @@ #ifndef PACKAGEMODEL_H #define PACKAGEMODEL_H +#include "utils/NamedEnum.h" + #include #include #include @@ -32,6 +34,8 @@ enum class PackageChooserMode RequiredMultiple // one or more }; +const NamedEnumTable< PackageChooserMode >& roleNames(); + struct PackageItem { QString id; From fb3204262c596343a1bea200fc7af0d8555c3b44 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 23:24:35 +0200 Subject: [PATCH 058/302] [packagechooser] Remove unneeded forward declaration --- src/modules/packagechooser/PackageChooserViewStep.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/modules/packagechooser/PackageChooserViewStep.h b/src/modules/packagechooser/PackageChooserViewStep.h index ed33c3e46..3947298ba 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.h +++ b/src/modules/packagechooser/PackageChooserViewStep.h @@ -30,7 +30,6 @@ #include class PackageChooserPage; -class PackageListModel; class PLUGINDLLEXPORT PackageChooserViewStep : public Calamares::ViewStep { From 5cabeee80da841c6a1a79af33f08b381c73f70a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Sat, 3 Aug 2019 08:28:20 +0200 Subject: [PATCH 059/302] [officechooser] initial commit --- src/modules/officechooser/CMakeLists.txt | 30 +++ .../officechooser/PackageChooserPage.cpp | 101 ++++++++++ .../officechooser/PackageChooserPage.h | 54 ++++++ .../officechooser/PackageChooserViewStep.cpp | 181 ++++++++++++++++++ .../officechooser/PackageChooserViewStep.h | 69 +++++++ src/modules/officechooser/PackageModel.cpp | 113 +++++++++++ src/modules/officechooser/PackageModel.h | 90 +++++++++ src/modules/officechooser/Tests.cpp | 38 ++++ src/modules/officechooser/Tests.h | 36 ++++ .../officechooser/images/FreeOffice.jpg | Bin 0 -> 66350 bytes .../officechooser/images/LibreOffice.jpg | Bin 0 -> 46877 bytes .../officechooser/images/choose-office.jpg | Bin 0 -> 55210 bytes src/modules/officechooser/packagechooser.qrc | 7 + src/modules/officechooser/page_package.ui | 66 +++++++ 14 files changed, 785 insertions(+) create mode 100644 src/modules/officechooser/CMakeLists.txt create mode 100644 src/modules/officechooser/PackageChooserPage.cpp create mode 100644 src/modules/officechooser/PackageChooserPage.h create mode 100644 src/modules/officechooser/PackageChooserViewStep.cpp create mode 100644 src/modules/officechooser/PackageChooserViewStep.h create mode 100644 src/modules/officechooser/PackageModel.cpp create mode 100644 src/modules/officechooser/PackageModel.h create mode 100644 src/modules/officechooser/Tests.cpp create mode 100644 src/modules/officechooser/Tests.h create mode 100644 src/modules/officechooser/images/FreeOffice.jpg create mode 100644 src/modules/officechooser/images/LibreOffice.jpg create mode 100644 src/modules/officechooser/images/choose-office.jpg create mode 100644 src/modules/officechooser/packagechooser.qrc create mode 100644 src/modules/officechooser/page_package.ui diff --git a/src/modules/officechooser/CMakeLists.txt b/src/modules/officechooser/CMakeLists.txt new file mode 100644 index 000000000..a632f6750 --- /dev/null +++ b/src/modules/officechooser/CMakeLists.txt @@ -0,0 +1,30 @@ +find_package( Qt5 COMPONENTS Core Gui Widgets REQUIRED ) + +calamares_add_plugin( officechooser + TYPE viewmodule + EXPORT_MACRO PLUGINDLLEXPORT_PRO + SOURCES + PackageChooserPage.cpp + PackageChooserViewStep.cpp + PackageModel.cpp + RESOURCES + packagechooser.qrc + UI + page_package.ui + LINK_PRIVATE_LIBRARIES + calamaresui + SHARED_LIB +) + +if( ECM_FOUND AND BUILD_TESTING ) + ecm_add_test( + Tests.cpp + TEST_NAME + packagechooosertest + LINK_LIBRARIES + ${CALAMARES_LIBRARIES} + Qt5::Core + Qt5::Test + ) + calamares_automoc( packagechooosertest) +endif() diff --git a/src/modules/officechooser/PackageChooserPage.cpp b/src/modules/officechooser/PackageChooserPage.cpp new file mode 100644 index 000000000..98b569bce --- /dev/null +++ b/src/modules/officechooser/PackageChooserPage.cpp @@ -0,0 +1,101 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, Adriaan de Groot + * Copyright 2019, Philip Müller + * + * 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 "PackageChooserPage.h" + +#include "ui_page_package.h" + +#include "utils/Logger.h" +#include "utils/Retranslator.h" + +#include + +PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent ) + : QWidget( parent ) + , ui( new Ui::PackageChooserPage ) + , m_introduction( QString(), + QString(), + tr( "Office Selection" ), + tr( "Please pick a office suite from the list. The selected product will be installed." ) ) +{ + m_introduction.screenshot = QPixmap( QStringLiteral( ":/images/choose-office.jpg" ) ); + cDebug() << m_introduction.screenshot; + + ui->setupUi( this ); + CALAMARES_RETRANSLATE( updateLabels(); ) + + switch ( mode ) + { + case PackageChooserMode::Optional: + case PackageChooserMode::Exclusive: + ui->products->setSelectionMode( QAbstractItemView::SingleSelection ); + case PackageChooserMode::Multiple: + case PackageChooserMode::RequiredMultiple: + ui->products->setSelectionMode( QAbstractItemView::ExtendedSelection ); + } +} + +void +PackageChooserPage::currentChanged( const QModelIndex& index ) +{ + if ( !index.isValid() || !ui->products->selectionModel()->hasSelection() ) + { + ui->productName->setText( m_introduction.name ); + ui->productScreenshot->setPixmap( m_introduction.screenshot ); + ui->productDescription->setText( m_introduction.description ); + } + else + { + const auto* model = ui->products->model(); + + ui->productName->setText( model->data( index, PackageListModel::NameRole ).toString() ); + ui->productScreenshot->setPixmap( model->data( index, PackageListModel::ScreenshotRole ).value< QPixmap >() ); + ui->productDescription->setText( model->data( index, PackageListModel::DescriptionRole ).toString() ); + } +} + +void +PackageChooserPage::updateLabels() +{ + if ( ui && ui->products && ui->products->selectionModel() ) + { + currentChanged( ui->products->selectionModel()->currentIndex() ); + } + else + { + currentChanged( QModelIndex() ); + } + emit selectionChanged(); +} + +void +PackageChooserPage::setModel( QAbstractItemModel* model ) +{ + ui->products->setModel( model ); + connect( ui->products->selectionModel(), + &QItemSelectionModel::selectionChanged, + this, + &PackageChooserPage::updateLabels ); +} + +bool +PackageChooserPage::hasSelection() const +{ + return ui && ui->products && ui->products->selectionModel() && ui->products->selectionModel()->hasSelection(); +} diff --git a/src/modules/officechooser/PackageChooserPage.h b/src/modules/officechooser/PackageChooserPage.h new file mode 100644 index 000000000..8f9fde11f --- /dev/null +++ b/src/modules/officechooser/PackageChooserPage.h @@ -0,0 +1,54 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 PACKAGECHOOSERPAGE_H +#define PACKAGECHOOSERPAGE_H + +#include "PackageModel.h" + +#include +#include + +namespace Ui +{ +class PackageChooserPage; +} + +class PackageChooserPage : public QWidget +{ + Q_OBJECT +public: + explicit PackageChooserPage( PackageChooserMode mode, QWidget* parent = nullptr ); + + void setModel( QAbstractItemModel* model ); + + bool hasSelection() const; + +public slots: + void currentChanged( const QModelIndex& index ); + void updateLabels(); + +signals: + void selectionChanged(); + +private: + Ui::PackageChooserPage* ui; + PackageItem m_introduction; +}; + +#endif // PACKAGECHOOSERPAGE_H diff --git a/src/modules/officechooser/PackageChooserViewStep.cpp b/src/modules/officechooser/PackageChooserViewStep.cpp new file mode 100644 index 000000000..ab7a15c86 --- /dev/null +++ b/src/modules/officechooser/PackageChooserViewStep.cpp @@ -0,0 +1,181 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, Adriaan de Groot + * Copyright 2019, Philip Müller + * + * 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 "PackageChooserViewStep.h" + +#include "PackageChooserPage.h" +#include "PackageModel.h" + +#include "GlobalStorage.h" +#include "JobQueue.h" + +#include "utils/CalamaresUtilsSystem.h" +#include "utils/Logger.h" +#include "utils/Variant.h" + +#include +#include + +CALAMARES_PLUGIN_FACTORY_DEFINITION( PackageChooserViewStepFactory, registerPlugin< PackageChooserViewStep >(); ) + +PackageChooserViewStep::PackageChooserViewStep( QObject* parent ) + : Calamares::ViewStep( parent ) + , m_widget( nullptr ) + , m_model( nullptr ) + , m_mode( PackageChooserMode::Exclusive ) +{ + emit nextStatusChanged( false ); +} + + +PackageChooserViewStep::~PackageChooserViewStep() +{ + if ( m_widget && m_widget->parent() == nullptr ) + { + m_widget->deleteLater(); + } + delete m_model; +} + + +QString +PackageChooserViewStep::prettyName() const +{ + return tr( "Office Suite" ); +} + + +QWidget* +PackageChooserViewStep::widget() +{ + if ( !m_widget ) + { + m_widget = new PackageChooserPage( m_mode, nullptr ); + connect( m_widget, &PackageChooserPage::selectionChanged, [=]() { + emit nextStatusChanged( this->isNextEnabled() ); + } ); + + if ( m_model ) + { + hookupModel(); + } + else + { + cWarning() << "PackageChooser Widget created before model."; + } + } + return m_widget; +} + + +bool +PackageChooserViewStep::isNextEnabled() const +{ + if ( !m_model ) + { + return false; + } + + if ( !m_widget ) + { + // No way to have changed anything + return true; + } + + switch ( m_mode ) + { + case PackageChooserMode::Optional: + case PackageChooserMode::Multiple: + // zero or one OR zero or more + return true; + case PackageChooserMode::Exclusive: + case PackageChooserMode::RequiredMultiple: + // exactly one OR one or more + return m_widget->hasSelection(); + } + + NOTREACHED return true; +} + + +bool +PackageChooserViewStep::isBackEnabled() const +{ + return true; +} + + +bool +PackageChooserViewStep::isAtBeginning() const +{ + return true; +} + + +bool +PackageChooserViewStep::isAtEnd() const +{ + return true; +} + + +void +PackageChooserViewStep::onLeave() +{ +} + +Calamares::JobList +PackageChooserViewStep::jobs() const +{ + Calamares::JobList l; + return l; +} + +void +PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap ) +{ + // TODO: use the configurationMap + + if ( !m_model ) + { + + m_model = new PackageListModel( nullptr ); + m_model->addPackage( PackageItem { "libreoffice-still", "libreoffice-still", "LibreOffice", "LibreOffice is a powerful and free office suite, used by millions of people around the world.", ":/images/LibreOffice.jpg" } ); + m_model->addPackage( + PackageItem { "freeoffice", "freeoffice", "FreeOffice", "FreeOffice is a complete Office suite with a word processor, a spreadsheet application and a presentation program – all compatible with their counterparts in Microsoft Office.", ":/images/FreeOffice.jpg" } ); + + + if ( m_widget ) + { + hookupModel(); + } + } +} + +void +PackageChooserViewStep::hookupModel() +{ + if ( !m_model || !m_widget ) + { + cError() << "Can't hook up model until widget and model both exist."; + return; + } + + m_widget->setModel( m_model ); +} diff --git a/src/modules/officechooser/PackageChooserViewStep.h b/src/modules/officechooser/PackageChooserViewStep.h new file mode 100644 index 000000000..ed33c3e46 --- /dev/null +++ b/src/modules/officechooser/PackageChooserViewStep.h @@ -0,0 +1,69 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 PACKAGECHOOSERVIEWSTEP_H +#define PACKAGECHOOSERVIEWSTEP_H + +#include "PluginDllMacro.h" +#include "utils/PluginFactory.h" +#include "viewpages/ViewStep.h" + +#include "PackageModel.h" + +#include +#include +#include + +class PackageChooserPage; +class PackageListModel; + +class PLUGINDLLEXPORT PackageChooserViewStep : public Calamares::ViewStep +{ + Q_OBJECT + +public: + explicit PackageChooserViewStep( QObject* parent = nullptr ); + virtual ~PackageChooserViewStep() override; + + QString prettyName() const override; + + QWidget* widget() override; + + bool isNextEnabled() const override; + bool isBackEnabled() const override; + + bool isAtBeginning() const override; + bool isAtEnd() const override; + + void onLeave() override; + + Calamares::JobList jobs() const override; + + void setConfigurationMap( const QVariantMap& configurationMap ) override; + +private: + void hookupModel(); + + PackageChooserPage* m_widget; + PackageListModel* m_model; + PackageChooserMode m_mode; +}; + +CALAMARES_PLUGIN_FACTORY_DECLARATION( PackageChooserViewStepFactory ) + +#endif // PACKAGECHOOSERVIEWSTEP_H diff --git a/src/modules/officechooser/PackageModel.cpp b/src/modules/officechooser/PackageModel.cpp new file mode 100644 index 000000000..7798b33bd --- /dev/null +++ b/src/modules/officechooser/PackageModel.cpp @@ -0,0 +1,113 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 "PackageModel.h" + +#include "utils/Logger.h" + +PackageItem +PackageItem::fromAppStream( const QString& filename ) +{ + // TODO: implement this + return PackageItem {}; +} + +PackageItem::PackageItem() {} + +PackageItem::PackageItem( const QString& a_id, + const QString& a_package, + const QString& a_name, + const QString& a_description ) + : id( a_id ) + , package( a_package ) + , name( a_name ) + , description( a_description ) +{ +} + +PackageItem::PackageItem( const QString& a_id, + const QString& a_package, + const QString& a_name, + const QString& a_description, + const QString& screenshotPath ) + : id( a_id ) + , package( a_package ) + , name( a_name ) + , description( a_description ) + , screenshot( screenshotPath ) +{ +} + + +PackageListModel::PackageListModel( QObject* parent ) + : QAbstractListModel( parent ) +{ +} + +PackageListModel::PackageListModel( PackageList&& items, QObject* parent ) + : QAbstractListModel( parent ) + , m_packages( std::move( items ) ) +{ +} + +PackageListModel::~PackageListModel() {} + +void +PackageListModel::addPackage( PackageItem&& p ) +{ + int c = m_packages.count(); + beginInsertRows( QModelIndex(), c, c ); + m_packages.append( p ); + endInsertRows(); +} + +int +PackageListModel::rowCount( const QModelIndex& index ) const +{ + // For lists, valid indexes have zero children; only the root index has them + return index.isValid() ? 0 : m_packages.count(); +} + +QVariant +PackageListModel::data( const QModelIndex& index, int role ) const +{ + if ( !index.isValid() ) + { + return QVariant(); + } + int row = index.row(); + if ( row >= m_packages.count() || row < 0 ) + { + return QVariant(); + } + + if ( role == Qt::DisplayRole /* Also PackageNameRole */ ) + { + return m_packages[ row ].name; + } + else if ( role == DescriptionRole ) + { + return m_packages[ row ].description; + } + else if ( role == ScreenshotRole ) + { + return m_packages[ row ].screenshot; + } + + return QVariant(); +} diff --git a/src/modules/officechooser/PackageModel.h b/src/modules/officechooser/PackageModel.h new file mode 100644 index 000000000..7db668df4 --- /dev/null +++ b/src/modules/officechooser/PackageModel.h @@ -0,0 +1,90 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 PACKAGEMODEL_H +#define PACKAGEMODEL_H + +#include +#include +#include +#include + +enum class PackageChooserMode +{ + Optional, // zero or one + Exclusive, // exactly one + Multiple, // zero or more + RequiredMultiple // one or more +}; + +struct PackageItem +{ + QString id; + // TODO: may need more than one + QString package; + // TODO: name and description are localized + QString name; + QString description; + // TODO: may be more than one + QPixmap screenshot; + + /// @brief Create blank PackageItem + PackageItem(); + /** @brief Creates a PackageItem from given strings + * + * This constructor sets all the text members, + * but leaves the screenshot blank. Set that separately. + */ + PackageItem( const QString& id, const QString& package, const QString& name, const QString& description ); + + PackageItem( const QString& id, + const QString& package, + const QString& name, + const QString& description, + const QString& screenshotPath ); + + // TODO: implement this + PackageItem fromAppStream( const QString& filename ); +}; + +using PackageList = QVector< PackageItem >; + +class PackageListModel : public QAbstractListModel +{ +public: + PackageListModel( PackageList&& items, QObject* parent ); + PackageListModel( QObject* parent ); + virtual ~PackageListModel(); + + void addPackage( PackageItem&& p ); + + int rowCount( const QModelIndex& index ) const override; + QVariant data( const QModelIndex& index, int role ) const override; + + enum Roles : int + { + NameRole = Qt::DisplayRole, + DescriptionRole = Qt::UserRole, + ScreenshotRole + }; + +private: + PackageList m_packages; +}; + +#endif diff --git a/src/modules/officechooser/Tests.cpp b/src/modules/officechooser/Tests.cpp new file mode 100644 index 000000000..c016f1808 --- /dev/null +++ b/src/modules/officechooser/Tests.cpp @@ -0,0 +1,38 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 "Tests.h" + +#include + +QTEST_GUILESS_MAIN( PackageChooserTests ) + +PackageChooserTests::PackageChooserTests() {} + +PackageChooserTests::~PackageChooserTests() {} + +void +PackageChooserTests::initTestCase() +{ +} + +void +PackageChooserTests::testBogus() +{ + QVERIFY( true ); +} diff --git a/src/modules/officechooser/Tests.h b/src/modules/officechooser/Tests.h new file mode 100644 index 000000000..bc257f5a5 --- /dev/null +++ b/src/modules/officechooser/Tests.h @@ -0,0 +1,36 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 PACKAGECHOOSERTESTS_H +#define PACKAGECHOOSERTESTS_H + +#include + +class PackageChooserTests : public QObject +{ + Q_OBJECT +public: + PackageChooserTests(); + ~PackageChooserTests() override; + +private Q_SLOTS: + void initTestCase(); + void testBogus(); +}; + +#endif diff --git a/src/modules/officechooser/images/FreeOffice.jpg b/src/modules/officechooser/images/FreeOffice.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a4337d2c2a8d477690694a941764d9b1adac208c GIT binary patch literal 66350 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

^T78p)c& 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 HDu4gk7p>5h literal 0 HcmV?d00001 diff --git a/src/modules/officechooser/images/LibreOffice.jpg b/src/modules/officechooser/images/LibreOffice.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bc4472f4dc72e07e07fd4c74823364584d1918b7 GIT binary patch literal 46877 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 XLa9Wvp+vI!7&=&{&V}6#lQjR?$c()s literal 0 HcmV?d00001 diff --git a/src/modules/officechooser/images/choose-office.jpg b/src/modules/officechooser/images/choose-office.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b960e0f6347afbc72b2b204120dea6aeac2f59dd GIT binary patch literal 55210 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%0AO2Z|InMe$j(#C`Ml>Lh`E`b3 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 b^8(_J + + images/choose-office.jpg + images/LibreOffice.jpg + images/FreeOffice.jpg + + diff --git a/src/modules/officechooser/page_package.ui b/src/modules/officechooser/page_package.ui new file mode 100644 index 000000000..1ba032ed2 --- /dev/null +++ b/src/modules/officechooser/page_package.ui @@ -0,0 +1,66 @@ + + + PackageChooserPage + + + + 0 + 0 + 400 + 500 + + + + + 0 + 1 + + + + Form + + + + + + + + + 0 + 1 + + + + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + + + + + + From 258eb3643241b86b144827c36d1cf06499963089 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Sat, 3 Aug 2019 08:47:04 +0200 Subject: [PATCH 060/302] [officechooser] update text --- src/modules/officechooser/PackageChooserViewStep.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/officechooser/PackageChooserViewStep.cpp b/src/modules/officechooser/PackageChooserViewStep.cpp index ab7a15c86..252fe79df 100644 --- a/src/modules/officechooser/PackageChooserViewStep.cpp +++ b/src/modules/officechooser/PackageChooserViewStep.cpp @@ -156,9 +156,9 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap { m_model = new PackageListModel( nullptr ); - m_model->addPackage( PackageItem { "libreoffice-still", "libreoffice-still", "LibreOffice", "LibreOffice is a powerful and free office suite, used by millions of people around the world.", ":/images/LibreOffice.jpg" } ); + m_model->addPackage( PackageItem { "libreoffice-still", "libreoffice-still", "LibreOffice - the standard Linux office suite", "LibreOffice is a powerful and free office suite, used by millions of people around the world.", ":/images/LibreOffice.jpg" } ); m_model->addPackage( - PackageItem { "freeoffice", "freeoffice", "FreeOffice", "FreeOffice is a complete Office suite with a word processor, a spreadsheet application and a presentation program – all compatible with their counterparts in Microsoft Office.", ":/images/FreeOffice.jpg" } ); + PackageItem { "freeoffice", "freeoffice", "FreeOffice - a complete office suite for high MS Office compability!", "FreeOffice is a complete office suite with a word processor, a spreadsheet application and a presentation program.", ":/images/FreeOffice.jpg" } ); if ( m_widget ) From 3f20295760efe648a36ebd772128f40832c5c116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Sat, 3 Aug 2019 09:18:06 +0200 Subject: [PATCH 061/302] [officechooser] update UI and text --- .../officechooser/PackageChooserViewStep.cpp | 4 ++-- src/modules/officechooser/page_package.ui | 23 +++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/modules/officechooser/PackageChooserViewStep.cpp b/src/modules/officechooser/PackageChooserViewStep.cpp index 252fe79df..41576b320 100644 --- a/src/modules/officechooser/PackageChooserViewStep.cpp +++ b/src/modules/officechooser/PackageChooserViewStep.cpp @@ -156,9 +156,9 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap { m_model = new PackageListModel( nullptr ); - m_model->addPackage( PackageItem { "libreoffice-still", "libreoffice-still", "LibreOffice - the standard Linux office suite", "LibreOffice is a powerful and free office suite, used by millions of people around the world.", ":/images/LibreOffice.jpg" } ); + m_model->addPackage( PackageItem { "libreoffice-still", "libreoffice-still", "LibreOffice", "LibreOffice is a powerful and free office suite, used by millions of people around the world. ts clean interface and feature-rich tools help you unleash your creativity and enhance your productivity.", ":/images/LibreOffice.jpg" } ); m_model->addPackage( - PackageItem { "freeoffice", "freeoffice", "FreeOffice - a complete office suite for high MS Office compability!", "FreeOffice is a complete office suite with a word processor, a spreadsheet application and a presentation program.", ":/images/FreeOffice.jpg" } ); + PackageItem { "freeoffice", "freeoffice", "FreeOffice", "FreeOffice 2018 is a full-featured Office suite with word processing, spreadsheet and presentation software. It is seamlessly compatible with Microsoft Office. (Note: You need to register the product for free longterm usage)", ":/images/FreeOffice.jpg" } ); if ( m_widget ) diff --git a/src/modules/officechooser/page_package.ui b/src/modules/officechooser/page_package.ui index 1ba032ed2..e54f778b5 100644 --- a/src/modules/officechooser/page_package.ui +++ b/src/modules/officechooser/page_package.ui @@ -36,9 +36,23 @@ + + + 14 + + TextLabel + + Qt::AutoText + + + Qt::AlignCenter + + + true + @@ -46,6 +60,9 @@ TextLabel + + Qt::AlignCenter + @@ -53,6 +70,12 @@ TextLabel + + Qt::AlignCenter + + + true + From 042852218f53dbf491a68c75f9e727d3a66e2f2d Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 3 Aug 2019 14:52:38 +0200 Subject: [PATCH 062/302] [license] Apply current coding style --- src/modules/license/LicensePage.cpp | 80 +++++++++++++------------ src/modules/license/LicensePage.h | 4 +- src/modules/license/LicenseViewStep.cpp | 18 +++--- src/modules/license/LicenseViewStep.h | 4 +- src/modules/license/LicenseWidget.cpp | 65 ++++++++++---------- src/modules/license/LicenseWidget.h | 4 +- 6 files changed, 89 insertions(+), 86 deletions(-) diff --git a/src/modules/license/LicensePage.cpp b/src/modules/license/LicensePage.cpp index 3c241e467..2cc025f83 100644 --- a/src/modules/license/LicensePage.cpp +++ b/src/modules/license/LicensePage.cpp @@ -21,11 +21,11 @@ #include "LicensePage.h" -#include "ui_LicensePage.h" #include "LicenseWidget.h" +#include "ui_LicensePage.h" -#include "JobQueue.h" #include "GlobalStorage.h" +#include "JobQueue.h" #include "ViewManager.h" #include "utils/CalamaresUtilsGui.h" @@ -36,10 +36,10 @@ #include #include +#include #include #include #include -#include #include #include @@ -47,11 +47,11 @@ const NamedEnumTable< LicenseEntry::Type >& LicenseEntry::typeNames() { - static const NamedEnumTable< LicenseEntry::Type > names{ - { QStringLiteral( "software" ), LicenseEntry::Type::Software}, + static const NamedEnumTable< LicenseEntry::Type > names { + { QStringLiteral( "software" ), LicenseEntry::Type::Software }, { QStringLiteral( "driver" ), LicenseEntry::Type::Driver }, { QStringLiteral( "gpudriver" ), LicenseEntry::Type::GpuDriver }, - { QStringLiteral( "browserplugin" ), LicenseEntry::Type::BrowserPlugin}, + { QStringLiteral( "browserplugin" ), LicenseEntry::Type::BrowserPlugin }, { QStringLiteral( "codec" ), LicenseEntry::Type::Codec }, { QStringLiteral( "package" ), LicenseEntry::Type::Package } }; @@ -59,10 +59,12 @@ LicenseEntry::typeNames() return names; } -LicenseEntry::LicenseEntry(const QVariantMap& conf) +LicenseEntry::LicenseEntry( const QVariantMap& conf ) { if ( !conf.contains( "id" ) || !conf.contains( "name" ) || !conf.contains( "url" ) ) + { return; + } m_id = conf[ "id" ].toString(); m_prettyName = conf[ "name" ].toString(); @@ -75,7 +77,9 @@ LicenseEntry::LicenseEntry(const QVariantMap& conf) QString typeString = conf.value( "type", "software" ).toString(); m_type = typeNames().find( typeString, ok ); if ( !ok ) + { cWarning() << "License entry" << m_id << "has unknown type" << typeString << "(using 'software')"; + } } bool @@ -85,7 +89,7 @@ LicenseEntry::isLocal() const } -LicensePage::LicensePage(QWidget *parent) +LicensePage::LicensePage( QWidget* parent ) : QWidget( parent ) , m_isNextEnabled( false ) , m_allLicensesOptional( false ) @@ -119,9 +123,7 @@ LicensePage::LicensePage(QWidget *parent) connect( ui->acceptCheckBox, &QCheckBox::toggled, this, &LicensePage::checkAcceptance ); - CALAMARES_RETRANSLATE( - ui->acceptCheckBox->setText( tr( "I accept the terms and conditions above." ) ); - ) + CALAMARES_RETRANSLATE( ui->acceptCheckBox->setText( tr( "I accept the terms and conditions above." ) ); ) } @@ -132,41 +134,40 @@ LicensePage::setEntries( const QList< LicenseEntry >& entriesList ) m_entries.clear(); m_entries.reserve( entriesList.count() ); - const bool required = std::any_of( entriesList.cbegin(), entriesList.cend(), []( const LicenseEntry& e ){ return e.m_required; }); + const bool required + = std::any_of( entriesList.cbegin(), entriesList.cend(), []( const LicenseEntry& e ) { return e.m_required; } ); if ( entriesList.isEmpty() ) + { m_allLicensesOptional = true; + } else + { m_allLicensesOptional = !required; + } checkAcceptance( false ); - CALAMARES_RETRANSLATE( - if ( required ) - { - ui->mainText->setText( tr( "

License Agreement

" - "This setup procedure will install proprietary " - "software that is subject to licensing terms." ) ); - ui->additionalText->setText( tr( "Please review the End User License " - "Agreements (EULAs) above.
" - "If you do not agree with the terms, the setup procedure cannot continue." ) ); - } - else - { - ui->mainText->setText( tr( "

License Agreement

" - "This setup procedure can install proprietary " - "software that is subject to licensing terms " - "in order to provide additional features and enhance the user " - "experience." ) ); - ui->additionalText->setText( tr( "Please review the End User License " - "Agreements (EULAs) above.
" - "If you do not agree with the terms, proprietary software will not " - "be installed, and open source alternatives will be used instead." ) ); - } - ui->retranslateUi( this ); + CALAMARES_RETRANSLATE( if ( required ) { + ui->mainText->setText( tr( "

License Agreement

" + "This setup procedure will install proprietary " + "software that is subject to licensing terms." ) ); + ui->additionalText->setText( tr( "Please review the End User License " + "Agreements (EULAs) above.
" + "If you do not agree with the terms, the setup procedure cannot continue." ) ); + } else { + ui->mainText->setText( tr( "

License Agreement

" + "This setup procedure can install proprietary " + "software that is subject to licensing terms " + "in order to provide additional features and enhance the user " + "experience." ) ); + ui->additionalText->setText( tr( "Please review the End User License " + "Agreements (EULAs) above.
" + "If you do not agree with the terms, proprietary software will not " + "be installed, and open source alternatives will be used instead." ) ); + } ui->retranslateUi( this ); - for ( const auto& w : m_entries ) - w->retranslateUi(); - ) + for ( const auto& w + : m_entries ) w->retranslateUi(); ) for ( const LicenseEntry& entry : entriesList ) { @@ -190,7 +191,8 @@ LicensePage::updateGlobalStorage( bool v ) Calamares::JobQueue::instance()->globalStorage()->insert( "licenseAgree", v ); } -void LicensePage::checkAcceptance( bool checked ) +void +LicensePage::checkAcceptance( bool checked ) { updateGlobalStorage( checked ); diff --git a/src/modules/license/LicensePage.h b/src/modules/license/LicensePage.h index e595f7ad8..bd9543937 100644 --- a/src/modules/license/LicensePage.h +++ b/src/modules/license/LicensePage.h @@ -24,8 +24,8 @@ #include "utils/NamedEnum.h" -#include #include +#include namespace Ui { @@ -101,4 +101,4 @@ private: QList< LicenseWidget* > m_entries; }; -#endif //LICENSEPAGE_H +#endif //LICENSEPAGE_H diff --git a/src/modules/license/LicenseViewStep.cpp b/src/modules/license/LicenseViewStep.cpp index f5f4b6e2b..89cddf27f 100644 --- a/src/modules/license/LicenseViewStep.cpp +++ b/src/modules/license/LicenseViewStep.cpp @@ -19,29 +19,30 @@ #include "LicenseViewStep.h" -#include "LicensePage.h" -#include "JobQueue.h" #include "GlobalStorage.h" +#include "JobQueue.h" +#include "LicensePage.h" #include "utils/Logger.h" #include -CALAMARES_PLUGIN_FACTORY_DEFINITION( LicenseViewStepFactory, registerPlugin(); ) +CALAMARES_PLUGIN_FACTORY_DEFINITION( LicenseViewStepFactory, registerPlugin< LicenseViewStep >(); ) LicenseViewStep::LicenseViewStep( QObject* parent ) : Calamares::ViewStep( parent ) , m_widget( new LicensePage ) { emit nextStatusChanged( false ); - connect( m_widget, &LicensePage::nextStatusChanged, - this, &LicenseViewStep::nextStatusChanged ); + connect( m_widget, &LicensePage::nextStatusChanged, this, &LicenseViewStep::nextStatusChanged ); } LicenseViewStep::~LicenseViewStep() { if ( m_widget && m_widget->parent() == nullptr ) + { m_widget->deleteLater(); + } } @@ -97,18 +98,21 @@ void LicenseViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { QList< LicenseEntry > entriesList; - if ( configurationMap.contains( "entries" ) && - configurationMap.value( "entries" ).type() == QVariant::List ) + if ( configurationMap.contains( "entries" ) && configurationMap.value( "entries" ).type() == QVariant::List ) { const auto entries = configurationMap.value( "entries" ).toList(); for ( const QVariant& entryV : entries ) { if ( entryV.type() != QVariant::Map ) + { continue; + } LicenseEntry entry( entryV.toMap() ); if ( entry.isValid() ) + { entriesList.append( entry ); + } } } diff --git a/src/modules/license/LicenseViewStep.h b/src/modules/license/LicenseViewStep.h index a4fabc8e1..957110f3d 100644 --- a/src/modules/license/LicenseViewStep.h +++ b/src/modules/license/LicenseViewStep.h @@ -20,9 +20,9 @@ #ifndef LICENSEPAGEPLUGIN_H #define LICENSEPAGEPLUGIN_H +#include #include #include -#include #include #include @@ -58,4 +58,4 @@ private: CALAMARES_PLUGIN_FACTORY_DECLARATION( LicenseViewStepFactory ) -#endif // LICENSEPAGEPLUGIN_H +#endif // LICENSEPAGEPLUGIN_H diff --git a/src/modules/license/LicenseWidget.cpp b/src/modules/license/LicenseWidget.cpp index 238d57b07..25509be95 100644 --- a/src/modules/license/LicenseWidget.cpp +++ b/src/modules/license/LicenseWidget.cpp @@ -34,10 +34,12 @@ static QString loadLocalFile( const QUrl& u ) { if ( !u.isLocalFile() ) + { return QString(); + } QFile file( u.path() ); - if ( !file.open(QIODevice::ReadOnly | QIODevice::Text) ) + if ( !file.open( QIODevice::ReadOnly | QIODevice::Text ) ) { cWarning() << "Could not load license file" << u.path(); return QString(); @@ -108,11 +110,10 @@ LicenseWidget::LicenseWidget( LicenseEntry entry, QWidget* parent ) retranslateUi(); } -LicenseWidget::~LicenseWidget() -{ -} +LicenseWidget::~LicenseWidget() {} -void LicenseWidget::retranslateUi() +void +LicenseWidget::retranslateUi() { QString productDescription; switch ( m_entry.m_type ) @@ -120,40 +121,40 @@ void LicenseWidget::retranslateUi() case LicenseEntry::Type::Driver: //: %1 is an untranslatable product name, example: Creative Audigy driver productDescription = tr( "%1 driver
" - "by %2" ) - .arg( m_entry.m_prettyName ) - .arg( m_entry.m_prettyVendor ); + "by %2" ) + .arg( m_entry.m_prettyName ) + .arg( m_entry.m_prettyVendor ); break; case LicenseEntry::Type::GpuDriver: //: %1 is usually a vendor name, example: Nvidia graphics driver productDescription = tr( "%1 graphics driver
" - "by %2" ) - .arg( m_entry.m_prettyName ) - .arg( m_entry.m_prettyVendor ); + "by %2" ) + .arg( m_entry.m_prettyName ) + .arg( m_entry.m_prettyVendor ); break; case LicenseEntry::Type::BrowserPlugin: productDescription = tr( "%1 browser plugin
" - "by %2" ) - .arg( m_entry.m_prettyName ) - .arg( m_entry.m_prettyVendor ); + "by %2" ) + .arg( m_entry.m_prettyName ) + .arg( m_entry.m_prettyVendor ); break; case LicenseEntry::Type::Codec: productDescription = tr( "%1 codec
" - "by %2" ) - .arg( m_entry.m_prettyName ) - .arg( m_entry.m_prettyVendor ); + "by %2" ) + .arg( m_entry.m_prettyName ) + .arg( m_entry.m_prettyVendor ); break; case LicenseEntry::Type::Package: productDescription = tr( "%1 package
" - "by %2" ) - .arg( m_entry.m_prettyName ) - .arg( m_entry.m_prettyVendor ); + "by %2" ) + .arg( m_entry.m_prettyName ) + .arg( m_entry.m_prettyVendor ); break; case LicenseEntry::Type::Software: productDescription = tr( "%1
" - "by %2" ) - .arg( m_entry.m_prettyName ) - .arg( m_entry.m_prettyVendor ); + "by %2" ) + .arg( m_entry.m_prettyName ) + .arg( m_entry.m_prettyVendor ); } m_label->setText( productDescription ); updateExpandToolTip(); @@ -173,7 +174,9 @@ LicenseWidget::expandClicked() // Show/hide based on the new arrow direction. if ( m_fullText ) + { m_fullText->setHidden( m_expandLicenseButton->arrowType() == Qt::UpArrow ); + } updateExpandToolTip(); } @@ -186,21 +189,15 @@ LicenseWidget::updateExpandToolTip() { const bool isNowCollapsed = m_expandLicenseButton->arrowType() == Qt::UpArrow; - m_expandLicenseButton->setToolTip( - isNowCollapsed - ? tr( "Shows the complete license text" ) - : tr( "Hide license text" ) - ) ; - m_viewLicenseLabel->setText( - isNowCollapsed - ? tr( "Show license agreement" ) - : tr( "Hide license agreement" ) ); + m_expandLicenseButton->setToolTip( isNowCollapsed ? tr( "Shows the complete license text" ) + : tr( "Hide license text" ) ); + m_viewLicenseLabel->setText( isNowCollapsed ? tr( "Show license agreement" ) : tr( "Hide license agreement" ) ); } else { m_expandLicenseButton->setToolTip( tr( "Opens the license agreement in a browser window." ) ); - m_viewLicenseLabel->setText( tr( "View license agreement" ) - .arg( m_entry.m_url.toString() ) ); + m_viewLicenseLabel->setText( + tr( "View license agreement" ).arg( m_entry.m_url.toString() ) ); } } diff --git a/src/modules/license/LicenseWidget.h b/src/modules/license/LicenseWidget.h index c43233da4..e11d7a746 100644 --- a/src/modules/license/LicenseWidget.h +++ b/src/modules/license/LicenseWidget.h @@ -39,7 +39,7 @@ public: private: void expandClicked(); // "slot" to toggle show/hide of local license text - void viewClicked(); // "slot" to open link + void viewClicked(); // "slot" to open link void updateExpandToolTip(); LicenseEntry m_entry; @@ -47,5 +47,5 @@ private: QLabel* m_viewLicenseLabel; QToolButton* m_expandLicenseButton; QLabel* m_fullText; -} ; +}; #endif From 76077743afdd838739cdf80cacf4c2ce26c3f54c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 3 Aug 2019 15:45:00 +0200 Subject: [PATCH 063/302] [packagechooser] Add configuration setting for selection mode - Add a *mode* key to the configuration file - Change some names around to be more consistent (not user-visible) --- .../packagechooser/PackageChooserViewStep.cpp | 10 ++++++++++ src/modules/packagechooser/PackageModel.cpp | 17 ++++++++--------- src/modules/packagechooser/PackageModel.h | 4 ++-- src/modules/packagechooser/packagechooser.conf | 9 +++++++++ 4 files changed, 29 insertions(+), 11 deletions(-) create mode 100644 src/modules/packagechooser/packagechooser.conf diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 9b3c174da..09fa488aa 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -150,6 +150,16 @@ void PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { // TODO: use the configurationMap + QString mode = CalamaresUtils::getString( configurationMap, "mode" ); + bool ok = false; + if ( !mode.isEmpty() ) + { + m_mode = roleNames().find( mode, ok ); + } + if ( !ok ) + { + m_mode = PackageChooserMode::Required; + } if ( !m_model ) { diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index 3546d9e42..484b4de3b 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -25,17 +25,16 @@ roleNames() { static const NamedEnumTable< PackageChooserMode > names { { "optional", PackageChooserMode::Optional }, - { "exclusive", PackageChooserMode::Exclusive }, - { "multiple", PackageChooserMode::Multiple }, - { "requiredmultiple", - PackageChooserMode::RequiredMultiple }, + { "required", PackageChooserMode::Required }, + { "optionalmultiple", PackageChooserMode::OptionalMultiple }, + { "requiredmultiple", PackageChooserMode::RequiredMultiple }, // and a bunch of aliases { "zero-or-one", PackageChooserMode::Optional }, - { "radio", PackageChooserMode::Exclusive }, - { "one", PackageChooserMode::Exclusive }, - { "set", PackageChooserMode::Multiple }, - { "zero-or-more", PackageChooserMode::Multiple }, - { "required", PackageChooserMode::RequiredMultiple }, + { "radio", PackageChooserMode::Required }, + { "one", PackageChooserMode::Required }, + { "set", PackageChooserMode::OptionalMultiple }, + { "zero-or-more", PackageChooserMode::OptionalMultiple }, + { "multiple", PackageChooserMode::RequiredMultiple }, { "one-or-more", PackageChooserMode::RequiredMultiple } }; return names; } diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index ed5ac4b24..76e43ef44 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -29,8 +29,8 @@ enum class PackageChooserMode { Optional, // zero or one - Exclusive, // exactly one - Multiple, // zero or more + Required, // exactly one + OptionalMultiple, // zero or more RequiredMultiple // one or more }; diff --git a/src/modules/packagechooser/packagechooser.conf b/src/modules/packagechooser/packagechooser.conf new file mode 100644 index 000000000..f08d07895 --- /dev/null +++ b/src/modules/packagechooser/packagechooser.conf @@ -0,0 +1,9 @@ +# Configuration for the low-density software chooser +--- +# Software selection mode, to set whether the software packages +# can be chosen singly, or multiply. +# +# Possible modes are "optional", "required" (for zero or one) +# or "optionalmultiple", "requiredmultiple" (for zero-or-more +# or one-or-more). +mode: required From 2fd2e90bf02ecf1704d1795ccde3057cac1e0eca Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 3 Aug 2019 21:29:28 +0200 Subject: [PATCH 064/302] [calamares] Always run module tester with verbose logging --- src/calamares/testmain.cpp | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/src/calamares/testmain.cpp b/src/calamares/testmain.cpp index 5671a591e..bf03d771d 100644 --- a/src/calamares/testmain.cpp +++ b/src/calamares/testmain.cpp @@ -51,13 +51,14 @@ struct ModuleConfig QString m_jobConfig; QString m_globalConfig; QString m_language; + QString m_branding; }; static ModuleConfig handle_args( QCoreApplication& a ) { QCommandLineOption debugLevelOption( - QStringLiteral( "D" ), "Verbose output for debugging purposes (0-8).", "level" ); + QStringLiteral( "D" ), "Verbose output for debugging purposes (0-8), ignored.", "level" ); QCommandLineOption globalOption( QStringList() << QStringLiteral( "g" ) << QStringLiteral( "global " ), QStringLiteral( "Global settings document" ), "global.yaml" ); @@ -82,21 +83,7 @@ handle_args( QCoreApplication& a ) parser.process( a ); - if ( parser.isSet( debugLevelOption ) ) - { - bool ok = true; - unsigned int l = parser.value( debugLevelOption ).toUInt( &ok ); - unsigned int dlevel = 0; - if ( !ok ) - { - dlevel = Logger::LOGVERBOSE; - } - else - { - dlevel = l; - } - Logger::setupLogLevel( dlevel ); - } + Logger::setupLogLevel( Logger::LOGVERBOSE ); const QStringList args = parser.positionalArguments(); if ( args.isEmpty() ) From f53aaa8bf3af14902495ce2a376c388d41c35726 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 3 Aug 2019 21:52:15 +0200 Subject: [PATCH 065/302] [calamares] Fix module loader for ViewModules - The ViewManager needs branding information, which wasn't initialized -- leading to crashes. Add -b option to give a specific branding, and default to something take makes sense when testing modules from the build directory. - Allows the module to load; doesn't show the UI though. --- src/calamares/testmain.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/calamares/testmain.cpp b/src/calamares/testmain.cpp index bf03d771d..17a05d6de 100644 --- a/src/calamares/testmain.cpp +++ b/src/calamares/testmain.cpp @@ -26,6 +26,7 @@ #include "utils/Logger.h" #include "utils/Yaml.h" +#include "Branding.h" #include "GlobalStorage.h" #include "Job.h" #include "JobQueue.h" @@ -68,6 +69,10 @@ handle_args( QCoreApplication& a ) QCommandLineOption langOption( QStringList() << QStringLiteral( "l" ) << QStringLiteral( "language" ), QStringLiteral( "Language (global)" ), "languagecode" ); + QCommandLineOption brandOption( QStringList() << QStringLiteral( "b" ) << QStringLiteral( "branding" ), + QStringLiteral( "Branding directory" ), + "path/to/branding.desc", + "src/branding/default/branding.desc" ); QCommandLineParser parser; parser.setApplicationDescription( "Calamares module tester" ); @@ -78,6 +83,7 @@ handle_args( QCoreApplication& a ) parser.addOption( globalOption ); parser.addOption( jobOption ); parser.addOption( langOption ); + parser.addOption( brandOption ); parser.addPositionalArgument( "module", "Path or name of module to run." ); parser.addPositionalArgument( "job.yaml", "Path of job settings document to use.", "[job.yaml]" ); @@ -104,7 +110,11 @@ handle_args( QCoreApplication& a ) jobSettings = args.at( 1 ); } - return ModuleConfig { args.first(), jobSettings, parser.value( globalOption ), parser.value( langOption ) }; + return ModuleConfig { args.first(), + jobSettings, + parser.value( globalOption ), + parser.value( langOption ), + parser.value( brandOption ) }; } } @@ -211,6 +221,7 @@ main( int argc, char* argv[] ) if ( m->type() == Calamares::Module::Type::View ) { aw = new QApplication( argc, argv ); + (void)new Calamares::Branding( module.m_branding ); (void)Calamares::ViewManager::instance( nullptr ); } From e8f342c0a526f3fdeaa9f84a82048b21808e17d7 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 3 Aug 2019 22:22:21 +0200 Subject: [PATCH 066/302] [calamares] Add test-loader option for UI --- src/calamares/testmain.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/calamares/testmain.cpp b/src/calamares/testmain.cpp index 17a05d6de..bdd271c81 100644 --- a/src/calamares/testmain.cpp +++ b/src/calamares/testmain.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include @@ -53,6 +54,7 @@ struct ModuleConfig QString m_globalConfig; QString m_language; QString m_branding; + bool m_ui; }; static ModuleConfig @@ -73,6 +75,8 @@ handle_args( QCoreApplication& a ) QStringLiteral( "Branding directory" ), "path/to/branding.desc", "src/branding/default/branding.desc" ); + QCommandLineOption uiOption( QStringList() << QStringLiteral( "U" ) << QStringLiteral( "ui" ), + QStringLiteral( "Enable UI" ) ); QCommandLineParser parser; parser.setApplicationDescription( "Calamares module tester" ); @@ -84,6 +88,7 @@ handle_args( QCoreApplication& a ) parser.addOption( jobOption ); parser.addOption( langOption ); parser.addOption( brandOption ); + parser.addOption( uiOption ); parser.addPositionalArgument( "module", "Path or name of module to run." ); parser.addPositionalArgument( "job.yaml", "Path of job settings document to use.", "[job.yaml]" ); @@ -114,7 +119,8 @@ handle_args( QCoreApplication& a ) jobSettings, parser.value( globalOption ), parser.value( langOption ), - parser.value( brandOption ) }; + parser.value( brandOption ), + parser.isSet( uiOption ) }; } } @@ -221,8 +227,9 @@ main( int argc, char* argv[] ) if ( m->type() == Calamares::Module::Type::View ) { aw = new QApplication( argc, argv ); + QMainWindow* mw = module.m_ui ? new QMainWindow() : nullptr; (void)new Calamares::Branding( module.m_branding ); - (void)Calamares::ViewManager::instance( nullptr ); + (void)Calamares::ViewManager::instance( mw ); } if ( !m->isLoaded() ) From f2fb49ce2664320730c3ebdcaa705631c92c8f45 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 3 Aug 2019 22:27:06 +0200 Subject: [PATCH 067/302] [calamares] Fix test-loader runtime - Some view steps expect the module manager to be there, avoid startup warnings by creating one. --- src/calamares/testmain.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/calamares/testmain.cpp b/src/calamares/testmain.cpp index bdd271c81..57f466e65 100644 --- a/src/calamares/testmain.cpp +++ b/src/calamares/testmain.cpp @@ -33,6 +33,8 @@ #include "Settings.h" #include "ViewManager.h" +#include "modulesystem/ModuleManager.h" + #include #include #include @@ -229,6 +231,7 @@ main( int argc, char* argv[] ) aw = new QApplication( argc, argv ); QMainWindow* mw = module.m_ui ? new QMainWindow() : nullptr; (void)new Calamares::Branding( module.m_branding ); + (void)new Calamares::ModuleManager( QStringList(), nullptr ); (void)Calamares::ViewManager::instance( mw ); } From ff6c6a360b1058c243c9a3f3561b7909a5e19c3d Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 3 Aug 2019 23:06:39 +0200 Subject: [PATCH 068/302] [calamares] Make UI work for test-loader - Need to create just one QApplication (subclass) with the right parameters for the UI to work. - If the UI is enabled and it's a View module, then show the widget rather than running the jobs. --- src/calamares/testmain.cpp | 49 ++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/src/calamares/testmain.cpp b/src/calamares/testmain.cpp index 57f466e65..885915041 100644 --- a/src/calamares/testmain.cpp +++ b/src/calamares/testmain.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -96,8 +97,6 @@ handle_args( QCoreApplication& a ) parser.process( a ); - Logger::setupLogLevel( Logger::LOGVERBOSE ); - const QStringList args = parser.positionalArguments(); if ( args.isEmpty() ) { @@ -189,13 +188,38 @@ load_module( const ModuleConfig& moduleConfig ) return module; } +/** @brief Create the right kind of QApplication + * + * Does primitive parsing of argv[] to find the --ui option and returns + * a UI-enabled application if it does. + * + * @p argc must be a reference (to main's argc) because the QCoreApplication + * constructors take a reference as well, and that would otherwise be a + * reference to a temporary. + */ +QCoreApplication* +createApplication( int& argc, char* argv[] ) +{ + for ( int i = 1; i < argc; ++i ) + { + if ( !qstrcmp( argv[ i ], "--ui" ) || !qstrcmp( argv[ i ], "-U" ) ) + { + auto* aw = new QApplication( argc, argv ); + aw->setQuitOnLastWindowClosed( true ); + return aw; + } + } + return new QCoreApplication( argc, argv ); +} + int main( int argc, char* argv[] ) { - QCoreApplication a( argc, argv ); - QApplication* aw = nullptr; + QCoreApplication* aw = createApplication( argc, argv ); - ModuleConfig module = handle_args( a ); + Logger::setupLogLevel( Logger::LOGVERBOSE ); + + ModuleConfig module = handle_args( *aw ); if ( module.moduleName().isEmpty() ) { return 1; @@ -203,6 +227,7 @@ main( int argc, char* argv[] ) std::unique_ptr< Calamares::Settings > settings_p( new Calamares::Settings( QString(), true ) ); std::unique_ptr< Calamares::JobQueue > jobqueue_p( new Calamares::JobQueue( nullptr ) ); + QMainWindow* mw = nullptr; auto gs = jobqueue_p->globalStorage(); if ( !module.globalConfigFile().isEmpty() ) @@ -228,8 +253,8 @@ main( int argc, char* argv[] ) cDebug() << " .. got" << m->name() << m->typeString() << m->interfaceString(); if ( m->type() == Calamares::Module::Type::View ) { - aw = new QApplication( argc, argv ); - QMainWindow* mw = module.m_ui ? new QMainWindow() : nullptr; + mw = module.m_ui ? new QMainWindow() : nullptr; + (void)new Calamares::Branding( module.m_branding ); (void)new Calamares::ModuleManager( QStringList(), nullptr ); (void)Calamares::ViewManager::instance( mw ); @@ -246,6 +271,16 @@ main( int argc, char* argv[] ) return 1; } + if ( mw ) + { + QWidget* w = Calamares::ViewManager::instance()->currentStep()->widget(); + w->setParent( mw ); + mw->setCentralWidget( w ); + w->show(); + mw->show(); + return aw->exec(); + } + using TR = Logger::DebugRow< const char*, const QString >; cDebug() << "Module metadata" << TR( "name", m->name() ) << TR( "type", m->typeString() ) From 87d7b2a5c072966422f19985a450449420ecdd31 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 3 Aug 2019 23:24:30 +0200 Subject: [PATCH 069/302] [packagechooser] Allow setting an ID for the module's GS key --- src/modules/packagechooser/PackageChooserViewStep.cpp | 6 ++++-- src/modules/packagechooser/PackageChooserViewStep.h | 3 +++ src/modules/packagechooser/packagechooser.conf | 9 +++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 09fa488aa..a8dd0e8d0 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -149,7 +149,6 @@ PackageChooserViewStep::jobs() const void PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { - // TODO: use the configurationMap QString mode = CalamaresUtils::getString( configurationMap, "mode" ); bool ok = false; if ( !mode.isEmpty() ) @@ -160,7 +159,10 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap { m_mode = PackageChooserMode::Required; } - + + m_id = CalamaresUtils::getString( configurationMap, "id" ); + + // TODO: replace this hard-coded model if ( !m_model ) { diff --git a/src/modules/packagechooser/PackageChooserViewStep.h b/src/modules/packagechooser/PackageChooserViewStep.h index 3947298ba..e410e547b 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.h +++ b/src/modules/packagechooser/PackageChooserViewStep.h @@ -60,7 +60,10 @@ private: PackageChooserPage* m_widget; PackageListModel* m_model; + + // Configuration PackageChooserMode m_mode; + QString m_id; }; CALAMARES_PLUGIN_FACTORY_DECLARATION( PackageChooserViewStepFactory ) diff --git a/src/modules/packagechooser/packagechooser.conf b/src/modules/packagechooser/packagechooser.conf index f08d07895..fd100ab27 100644 --- a/src/modules/packagechooser/packagechooser.conf +++ b/src/modules/packagechooser/packagechooser.conf @@ -1,5 +1,14 @@ # Configuration for the low-density software chooser --- +# The packagechooser writes a GlobalStorage value for the choice that +# has been made. The key is *packagechooser_*. If *id* is set here, +# it is substituted into the key name. If it is not set, the module's +# instance name is used; see the *instances* section of `settings.conf`. +# If there is just one packagechooser module, and no *id* is set, +# resulting GS key is probably *packagechooser_packagechooser*. +# +# id: "" + # Software selection mode, to set whether the software packages # can be chosen singly, or multiply. # From b711c791bdb9cc4f660a0cd3546391c4dd16eba0 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 3 Aug 2019 23:28:55 +0200 Subject: [PATCH 070/302] [packagechooser] Fix build, tidy code --- src/modules/packagechooser/PackageChooserPage.cpp | 4 ++-- .../packagechooser/PackageChooserViewStep.cpp | 14 +++++++------- .../packagechooser/PackageChooserViewStep.h | 2 +- src/modules/packagechooser/PackageModel.cpp | 3 ++- src/modules/packagechooser/PackageModel.h | 2 +- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index f0f7cb04c..d267e4885 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -42,9 +42,9 @@ PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent switch ( mode ) { case PackageChooserMode::Optional: - case PackageChooserMode::Exclusive: + case PackageChooserMode::Required: ui->products->setSelectionMode( QAbstractItemView::SingleSelection ); - case PackageChooserMode::Multiple: + case PackageChooserMode::OptionalMultiple: case PackageChooserMode::RequiredMultiple: ui->products->setSelectionMode( QAbstractItemView::ExtendedSelection ); } diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index a8dd0e8d0..47b6f84d0 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -37,7 +37,7 @@ PackageChooserViewStep::PackageChooserViewStep( QObject* parent ) : Calamares::ViewStep( parent ) , m_widget( nullptr ) , m_model( nullptr ) - , m_mode( PackageChooserMode::Exclusive ) + , m_mode( PackageChooserMode::Required ) { emit nextStatusChanged( false ); } @@ -100,10 +100,10 @@ PackageChooserViewStep::isNextEnabled() const switch ( m_mode ) { case PackageChooserMode::Optional: - case PackageChooserMode::Multiple: + case PackageChooserMode::OptionalMultiple: // zero or one OR zero or more return true; - case PackageChooserMode::Exclusive: + case PackageChooserMode::Required: case PackageChooserMode::RequiredMultiple: // exactly one OR one or more return m_widget->hasSelection(); @@ -159,17 +159,17 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap { m_mode = PackageChooserMode::Required; } - + m_id = CalamaresUtils::getString( configurationMap, "id" ); - + // TODO: replace this hard-coded model if ( !m_model ) { m_model = new PackageListModel( nullptr ); m_model->addPackage( PackageItem { "kde", "kde", "Plasma", "Plasma Desktop", ":/images/kde.png" } ); - m_model->addPackage( - PackageItem { "gnome", "gnome", "GNOME", "GNU Networked Object Modeling Environment Desktop", ":/images/gnome.png" } ); + m_model->addPackage( PackageItem { + "gnome", "gnome", "GNOME", "GNU Networked Object Modeling Environment Desktop", ":/images/gnome.png" } ); if ( m_widget ) diff --git a/src/modules/packagechooser/PackageChooserViewStep.h b/src/modules/packagechooser/PackageChooserViewStep.h index e410e547b..55ed2d4d5 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.h +++ b/src/modules/packagechooser/PackageChooserViewStep.h @@ -60,7 +60,7 @@ private: PackageChooserPage* m_widget; PackageListModel* m_model; - + // Configuration PackageChooserMode m_mode; QString m_id; diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index 484b4de3b..eb783259b 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -35,7 +35,8 @@ roleNames() { "set", PackageChooserMode::OptionalMultiple }, { "zero-or-more", PackageChooserMode::OptionalMultiple }, { "multiple", PackageChooserMode::RequiredMultiple }, - { "one-or-more", PackageChooserMode::RequiredMultiple } }; + { "one-or-more", PackageChooserMode::RequiredMultiple } + }; return names; } diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index 76e43ef44..dfb922e59 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -73,7 +73,7 @@ class PackageListModel : public QAbstractListModel public: PackageListModel( PackageList&& items, QObject* parent ); PackageListModel( QObject* parent ); - virtual ~PackageListModel(); + virtual ~PackageListModel() override; void addPackage( PackageItem&& p ); From c59ffc77652231f67bc0ba93240532927b1b321c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 3 Aug 2019 23:33:34 +0200 Subject: [PATCH 071/302] [packagechooser] Set default ID as documented --- src/modules/packagechooser/PackageChooserViewStep.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 47b6f84d0..9edfa9416 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -161,6 +161,12 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap } m_id = CalamaresUtils::getString( configurationMap, "id" ); + if ( m_id.isEmpty() ) + { + // Not set, so use the instance id + // TODO: use a stronger type than QString for structured IDs + m_id = moduleInstanceKey().split( '@' ).last(); + } // TODO: replace this hard-coded model if ( !m_model ) From 140c0db7a48b89af9e7a6b4c36a7a0ee0ae9467c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 3 Aug 2019 23:51:00 +0200 Subject: [PATCH 072/302] [packagechooser] Set GlobalStorage packagechooser_ --- .../packagechooser/PackageChooserPage.cpp | 21 +++++++++++++++++++ .../packagechooser/PackageChooserPage.h | 6 ++++++ .../packagechooser/PackageChooserViewStep.cpp | 9 ++++++++ src/modules/packagechooser/PackageModel.cpp | 4 ++++ src/modules/packagechooser/PackageModel.h | 3 ++- .../packagechooser/packagechooser.conf | 3 +++ 6 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index d267e4885..265ce3b53 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -98,3 +98,24 @@ PackageChooserPage::hasSelection() const { return ui && ui->products && ui->products->selectionModel() && ui->products->selectionModel()->hasSelection(); } + +QStringList +PackageChooserPage::selectedPackageIds() const +{ + if ( !( ui && ui->products && ui->products->selectionModel() ) ) + { + return QStringList(); + } + + const auto* model = ui->products->model(); + QStringList ids; + for ( const auto& index : ui->products->selectionModel()->selectedIndexes() ) + { + QString pid = model->data( index, PackageListModel::IdRole ).toString(); + if ( !pid.isEmpty() ) + { + ids.append( pid ); + } + } + return ids; +} diff --git a/src/modules/packagechooser/PackageChooserPage.h b/src/modules/packagechooser/PackageChooserPage.h index 8f9fde11f..401de903b 100644 --- a/src/modules/packagechooser/PackageChooserPage.h +++ b/src/modules/packagechooser/PackageChooserPage.h @@ -37,7 +37,13 @@ public: void setModel( QAbstractItemModel* model ); + /// @brief Is anything selected? bool hasSelection() const; + /** @brief Get the list of selected ids + * + * This list may be empty (if none is selected). + */ + QStringList selectedPackageIds() const; public slots: void currentChanged( const QModelIndex& index ); diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 9edfa9416..9d32884c7 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -137,6 +137,15 @@ PackageChooserViewStep::isAtEnd() const void PackageChooserViewStep::onLeave() { + QString key = QStringLiteral( "packagechooser_%1" ).arg( m_id ); + QString value; + if ( m_widget->hasSelection() ) + { + value = m_widget->selectedPackageIds().join( ',' ); + } + Calamares::JobQueue::instance()->globalStorage()->insert( key, value ); + + cDebug() << "PackageChooser" << key << "selected" << value; } Calamares::JobList diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index eb783259b..aa8dd39fc 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -128,6 +128,10 @@ PackageListModel::data( const QModelIndex& index, int role ) const { return m_packages[ row ].screenshot; } + else if ( role == IdRole ) + { + return m_packages[ row ].id; + } return QVariant(); } diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index dfb922e59..7f8fff8ec 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -84,7 +84,8 @@ public: { NameRole = Qt::DisplayRole, DescriptionRole = Qt::UserRole, - ScreenshotRole + ScreenshotRole, + IdRole }; private: diff --git a/src/modules/packagechooser/packagechooser.conf b/src/modules/packagechooser/packagechooser.conf index fd100ab27..b4e48c995 100644 --- a/src/modules/packagechooser/packagechooser.conf +++ b/src/modules/packagechooser/packagechooser.conf @@ -7,6 +7,9 @@ # If there is just one packagechooser module, and no *id* is set, # resulting GS key is probably *packagechooser_packagechooser*. # +# The GS value is a comma-separated list of the IDs of the selected +# packages, or an empty string if none is selected. +# # id: "" # Software selection mode, to set whether the software packages From 047a300a5181a03dd11c1a3b6862f3301236f301 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 3 Aug 2019 23:55:29 +0200 Subject: [PATCH 073/302] [packagechooser] Remove unneeded debug --- src/modules/packagechooser/PackageChooserPage.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index 265ce3b53..63307d095 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -34,7 +34,6 @@ PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent tr( "Please pick a product from the list. The selected product will be installed." ) ) { m_introduction.screenshot = QPixmap( QStringLiteral( ":/images/no-selection.png" ) ); - cDebug() << m_introduction.screenshot; ui->setupUi( this ); CALAMARES_RETRANSLATE( updateLabels(); ) From d5275d5e10cac56db5f3f573a5ecf54b681850e4 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 4 Aug 2019 00:08:41 +0200 Subject: [PATCH 074/302] [packagechooser] Allow the model to set the introductory text --- .../packagechooser/PackageChooserPage.cpp | 20 +++++++++++++++++++ .../packagechooser/PackageChooserViewStep.cpp | 11 ++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index 63307d095..60becf64f 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -86,6 +86,26 @@ void PackageChooserPage::setModel( QAbstractItemModel* model ) { ui->products->setModel( model ); + + // Check if any of the items in the model is the "none" option. + // If so, copy its values into the introduction / none item. + for ( int r = 0; r < model->rowCount(); ++r ) + { + auto index = model->index( r, 0 ); + if ( index.isValid() ) + { + QVariant v = model->data( index, PackageListModel::IdRole ); + if ( v.isValid() && v.toString().isEmpty() ) + { + m_introduction.name = model->data( index, PackageListModel::NameRole ).toString(); + m_introduction.description = model->data( index, PackageListModel::DescriptionRole ).toString(); + m_introduction.screenshot = model->data( index, PackageListModel::ScreenshotRole ).value< QPixmap >(); + currentChanged( QModelIndex() ); + break; + } + } + } + connect( ui->products->selectionModel(), &QItemSelectionModel::selectionChanged, this, diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 9d32884c7..8515d03a9 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -144,7 +144,7 @@ PackageChooserViewStep::onLeave() value = m_widget->selectedPackageIds().join( ',' ); } Calamares::JobQueue::instance()->globalStorage()->insert( key, value ); - + cDebug() << "PackageChooser" << key << "selected" << value; } @@ -180,8 +180,15 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap // TODO: replace this hard-coded model if ( !m_model ) { - m_model = new PackageListModel( nullptr ); + m_model->addPackage( PackageItem { QString(), + QString(), + "No Desktop", + "Please pick a desktop environment from the list. " + "If you don't want to install a desktop, that's fine, " + "your system will start up in text-only mode and you can " + "install a desktop environment later.", + ":/images/no-selection.png" } ); m_model->addPackage( PackageItem { "kde", "kde", "Plasma", "Plasma Desktop", ":/images/kde.png" } ); m_model->addPackage( PackageItem { "gnome", "gnome", "GNOME", "GNU Networked Object Modeling Environment Desktop", ":/images/gnome.png" } ); From adb939b2e82617003b16a81d0622d1bd45192843 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 4 Aug 2019 00:11:50 +0200 Subject: [PATCH 075/302] [packagechooser] Word-wrap package descriptions --- src/modules/packagechooser/page_package.ui | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/modules/packagechooser/page_package.ui b/src/modules/packagechooser/page_package.ui index 1ba032ed2..17a960549 100644 --- a/src/modules/packagechooser/page_package.ui +++ b/src/modules/packagechooser/page_package.ui @@ -53,6 +53,12 @@ TextLabel + + true + + + true +
From 19f24a61bfb39f29c7fdcea4787060773af3d017 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Sun, 4 Aug 2019 07:23:33 +0200 Subject: [PATCH 076/302] [officechooser] sync with upstream --- .../officechooser/PackageChooserPage.cpp | 50 +++++++++++++-- .../officechooser/PackageChooserPage.h | 6 ++ .../officechooser/PackageChooserViewStep.cpp | 63 ++++++++++++++++--- .../officechooser/PackageChooserViewStep.h | 4 +- src/modules/officechooser/PackageModel.cpp | 24 +++++++ src/modules/officechooser/PackageModel.h | 13 ++-- src/modules/officechooser/page_package.ui | 14 +---- 7 files changed, 143 insertions(+), 31 deletions(-) diff --git a/src/modules/officechooser/PackageChooserPage.cpp b/src/modules/officechooser/PackageChooserPage.cpp index 98b569bce..2b8449592 100644 --- a/src/modules/officechooser/PackageChooserPage.cpp +++ b/src/modules/officechooser/PackageChooserPage.cpp @@ -1,7 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2019, Adriaan de Groot - * Copyright 2019, Philip Müller + * Copyright 2019, Philip MÜller * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,11 +31,10 @@ PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent , ui( new Ui::PackageChooserPage ) , m_introduction( QString(), QString(), - tr( "Office Selection" ), + tr( "Office Suite" ), tr( "Please pick a office suite from the list. The selected product will be installed." ) ) { m_introduction.screenshot = QPixmap( QStringLiteral( ":/images/choose-office.jpg" ) ); - cDebug() << m_introduction.screenshot; ui->setupUi( this ); CALAMARES_RETRANSLATE( updateLabels(); ) @@ -43,9 +42,9 @@ PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent switch ( mode ) { case PackageChooserMode::Optional: - case PackageChooserMode::Exclusive: + case PackageChooserMode::Required: ui->products->setSelectionMode( QAbstractItemView::SingleSelection ); - case PackageChooserMode::Multiple: + case PackageChooserMode::OptionalMultiple: case PackageChooserMode::RequiredMultiple: ui->products->setSelectionMode( QAbstractItemView::ExtendedSelection ); } @@ -88,6 +87,26 @@ void PackageChooserPage::setModel( QAbstractItemModel* model ) { ui->products->setModel( model ); + + // Check if any of the items in the model is the "none" option. + // If so, copy its values into the introduction / none item. + for ( int r = 0; r < model->rowCount(); ++r ) + { + auto index = model->index( r, 0 ); + if ( index.isValid() ) + { + QVariant v = model->data( index, PackageListModel::IdRole ); + if ( v.isValid() && v.toString().isEmpty() ) + { + m_introduction.name = model->data( index, PackageListModel::NameRole ).toString(); + m_introduction.description = model->data( index, PackageListModel::DescriptionRole ).toString(); + m_introduction.screenshot = model->data( index, PackageListModel::ScreenshotRole ).value< QPixmap >(); + currentChanged( QModelIndex() ); + break; + } + } + } + connect( ui->products->selectionModel(), &QItemSelectionModel::selectionChanged, this, @@ -99,3 +118,24 @@ PackageChooserPage::hasSelection() const { return ui && ui->products && ui->products->selectionModel() && ui->products->selectionModel()->hasSelection(); } + +QStringList +PackageChooserPage::selectedPackageIds() const +{ + if ( !( ui && ui->products && ui->products->selectionModel() ) ) + { + return QStringList(); + } + + const auto* model = ui->products->model(); + QStringList ids; + for ( const auto& index : ui->products->selectionModel()->selectedIndexes() ) + { + QString pid = model->data( index, PackageListModel::IdRole ).toString(); + if ( !pid.isEmpty() ) + { + ids.append( pid ); + } + } + return ids; +} diff --git a/src/modules/officechooser/PackageChooserPage.h b/src/modules/officechooser/PackageChooserPage.h index 8f9fde11f..401de903b 100644 --- a/src/modules/officechooser/PackageChooserPage.h +++ b/src/modules/officechooser/PackageChooserPage.h @@ -37,7 +37,13 @@ public: void setModel( QAbstractItemModel* model ); + /// @brief Is anything selected? bool hasSelection() const; + /** @brief Get the list of selected ids + * + * This list may be empty (if none is selected). + */ + QStringList selectedPackageIds() const; public slots: void currentChanged( const QModelIndex& index ); diff --git a/src/modules/officechooser/PackageChooserViewStep.cpp b/src/modules/officechooser/PackageChooserViewStep.cpp index 41576b320..925d57f4c 100644 --- a/src/modules/officechooser/PackageChooserViewStep.cpp +++ b/src/modules/officechooser/PackageChooserViewStep.cpp @@ -1,7 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2019, Adriaan de Groot - * Copyright 2019, Philip Müller + * Copyright 2019, Philip MÜller * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,7 +38,7 @@ PackageChooserViewStep::PackageChooserViewStep( QObject* parent ) : Calamares::ViewStep( parent ) , m_widget( nullptr ) , m_model( nullptr ) - , m_mode( PackageChooserMode::Exclusive ) + , m_mode( PackageChooserMode::Required ) { emit nextStatusChanged( false ); } @@ -77,7 +77,7 @@ PackageChooserViewStep::widget() } else { - cWarning() << "PackageChooser Widget created before model."; + cWarning() << "OfficeChooser Widget created before model."; } } return m_widget; @@ -101,10 +101,10 @@ PackageChooserViewStep::isNextEnabled() const switch ( m_mode ) { case PackageChooserMode::Optional: - case PackageChooserMode::Multiple: + case PackageChooserMode::OptionalMultiple: // zero or one OR zero or more return true; - case PackageChooserMode::Exclusive: + case PackageChooserMode::Required: case PackageChooserMode::RequiredMultiple: // exactly one OR one or more return m_widget->hasSelection(); @@ -138,6 +138,15 @@ PackageChooserViewStep::isAtEnd() const void PackageChooserViewStep::onLeave() { + QString key = QStringLiteral( "packagechooser_%1" ).arg( m_id ); + QString value; + if ( m_widget->hasSelection() ) + { + value = m_widget->selectedPackageIds().join( ',' ); + } + Calamares::JobQueue::instance()->globalStorage()->insert( key, value ); + + cDebug() << "OfficeChooser" << key << "selected" << value; } Calamares::JobList @@ -150,16 +159,50 @@ PackageChooserViewStep::jobs() const void PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { - // TODO: use the configurationMap + QString mode = CalamaresUtils::getString( configurationMap, "mode" ); + bool ok = false; + if ( !mode.isEmpty() ) + { + m_mode = roleNames().find( mode, ok ); + } + if ( !ok ) + { + m_mode = PackageChooserMode::Required; + } + m_id = CalamaresUtils::getString( configurationMap, "id" ); + if ( m_id.isEmpty() ) + { + // Not set, so use the instance id + // TODO: use a stronger type than QString for structured IDs + m_id = moduleInstanceKey().split( '@' ).last(); + } + + // TODO: replace this hard-coded model if ( !m_model ) { - m_model = new PackageListModel( nullptr ); - m_model->addPackage( PackageItem { "libreoffice-still", "libreoffice-still", "LibreOffice", "LibreOffice is a powerful and free office suite, used by millions of people around the world. ts clean interface and feature-rich tools help you unleash your creativity and enhance your productivity.", ":/images/LibreOffice.jpg" } ); - m_model->addPackage( - PackageItem { "freeoffice", "freeoffice", "FreeOffice", "FreeOffice 2018 is a full-featured Office suite with word processing, spreadsheet and presentation software. It is seamlessly compatible with Microsoft Office. (Note: You need to register the product for free longterm usage)", ":/images/FreeOffice.jpg" } ); + m_model->addPackage( PackageItem { QString(), + QString(), + "No Office Suite", + "Please pick a Office Suite from the list. " + "If you don't want to install a Office Suite, that's fine, " + "you can install one later as needed.", + ":/images/choose-office.jpg" } ); + m_model->addPackage( PackageItem { "libreoffice-still", + "libreoffice-still", + "LibreOffice", + "LibreOffice is a powerful and free office suite, used by millions of people around the world. " + "Its clean interface and feature-rich tools help you unleash your creativity and enhance your productivity.", + ":/images/LibreOffice.jpg" } ); + m_model->addPackage( PackageItem { "freeoffice", + "freeoffice", + "FreeOffice", + "FreeOffice 2018 is a full-featured Office suite with word processing, " + "spreadsheet and presentation software. It is seamlessly compatible with Microsoft Office. " + "(Note: You need to register the product for free longterm usage)", + ":/images/FreeOffice.jpg" } ); if ( m_widget ) { diff --git a/src/modules/officechooser/PackageChooserViewStep.h b/src/modules/officechooser/PackageChooserViewStep.h index ed33c3e46..55ed2d4d5 100644 --- a/src/modules/officechooser/PackageChooserViewStep.h +++ b/src/modules/officechooser/PackageChooserViewStep.h @@ -30,7 +30,6 @@ #include class PackageChooserPage; -class PackageListModel; class PLUGINDLLEXPORT PackageChooserViewStep : public Calamares::ViewStep { @@ -61,7 +60,10 @@ private: PackageChooserPage* m_widget; PackageListModel* m_model; + + // Configuration PackageChooserMode m_mode; + QString m_id; }; CALAMARES_PLUGIN_FACTORY_DECLARATION( PackageChooserViewStepFactory ) diff --git a/src/modules/officechooser/PackageModel.cpp b/src/modules/officechooser/PackageModel.cpp index 7798b33bd..aa8dd39fc 100644 --- a/src/modules/officechooser/PackageModel.cpp +++ b/src/modules/officechooser/PackageModel.cpp @@ -20,6 +20,26 @@ #include "utils/Logger.h" +const NamedEnumTable< PackageChooserMode >& +roleNames() +{ + static const NamedEnumTable< PackageChooserMode > names { + { "optional", PackageChooserMode::Optional }, + { "required", PackageChooserMode::Required }, + { "optionalmultiple", PackageChooserMode::OptionalMultiple }, + { "requiredmultiple", PackageChooserMode::RequiredMultiple }, + // and a bunch of aliases + { "zero-or-one", PackageChooserMode::Optional }, + { "radio", PackageChooserMode::Required }, + { "one", PackageChooserMode::Required }, + { "set", PackageChooserMode::OptionalMultiple }, + { "zero-or-more", PackageChooserMode::OptionalMultiple }, + { "multiple", PackageChooserMode::RequiredMultiple }, + { "one-or-more", PackageChooserMode::RequiredMultiple } + }; + return names; +} + PackageItem PackageItem::fromAppStream( const QString& filename ) { @@ -108,6 +128,10 @@ PackageListModel::data( const QModelIndex& index, int role ) const { return m_packages[ row ].screenshot; } + else if ( role == IdRole ) + { + return m_packages[ row ].id; + } return QVariant(); } diff --git a/src/modules/officechooser/PackageModel.h b/src/modules/officechooser/PackageModel.h index 7db668df4..7f8fff8ec 100644 --- a/src/modules/officechooser/PackageModel.h +++ b/src/modules/officechooser/PackageModel.h @@ -19,6 +19,8 @@ #ifndef PACKAGEMODEL_H #define PACKAGEMODEL_H +#include "utils/NamedEnum.h" + #include #include #include @@ -27,11 +29,13 @@ enum class PackageChooserMode { Optional, // zero or one - Exclusive, // exactly one - Multiple, // zero or more + Required, // exactly one + OptionalMultiple, // zero or more RequiredMultiple // one or more }; +const NamedEnumTable< PackageChooserMode >& roleNames(); + struct PackageItem { QString id; @@ -69,7 +73,7 @@ class PackageListModel : public QAbstractListModel public: PackageListModel( PackageList&& items, QObject* parent ); PackageListModel( QObject* parent ); - virtual ~PackageListModel(); + virtual ~PackageListModel() override; void addPackage( PackageItem&& p ); @@ -80,7 +84,8 @@ public: { NameRole = Qt::DisplayRole, DescriptionRole = Qt::UserRole, - ScreenshotRole + ScreenshotRole, + IdRole }; private: diff --git a/src/modules/officechooser/page_package.ui b/src/modules/officechooser/page_package.ui index e54f778b5..ea85acff3 100644 --- a/src/modules/officechooser/page_package.ui +++ b/src/modules/officechooser/page_package.ui @@ -36,23 +36,12 @@ - - - 14 - - TextLabel - - Qt::AutoText - Qt::AlignCenter - - true - @@ -76,6 +65,9 @@ true + + true + From a7feb620d1bf977ac69b477b62446fc3cebefb7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Sun, 4 Aug 2019 07:28:56 +0200 Subject: [PATCH 077/302] [officechooser] add conf --- src/modules/officechooser/officechooser.conf | 21 ++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/modules/officechooser/officechooser.conf diff --git a/src/modules/officechooser/officechooser.conf b/src/modules/officechooser/officechooser.conf new file mode 100644 index 000000000..b4e48c995 --- /dev/null +++ b/src/modules/officechooser/officechooser.conf @@ -0,0 +1,21 @@ +# Configuration for the low-density software chooser +--- +# The packagechooser writes a GlobalStorage value for the choice that +# has been made. The key is *packagechooser_*. If *id* is set here, +# it is substituted into the key name. If it is not set, the module's +# instance name is used; see the *instances* section of `settings.conf`. +# If there is just one packagechooser module, and no *id* is set, +# resulting GS key is probably *packagechooser_packagechooser*. +# +# The GS value is a comma-separated list of the IDs of the selected +# packages, or an empty string if none is selected. +# +# id: "" + +# Software selection mode, to set whether the software packages +# can be chosen singly, or multiply. +# +# Possible modes are "optional", "required" (for zero or one) +# or "optionalmultiple", "requiredmultiple" (for zero-or-more +# or one-or-more). +mode: required From 26c1f01b874a88aa02e179eb8d74e37e0ed6f087 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Sun, 4 Aug 2019 08:17:29 +0200 Subject: [PATCH 078/302] [officechooser] fix typos --- src/modules/officechooser/PackageChooserPage.cpp | 2 +- src/modules/officechooser/PackageChooserViewStep.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/officechooser/PackageChooserPage.cpp b/src/modules/officechooser/PackageChooserPage.cpp index 2b8449592..c3d1ba3d0 100644 --- a/src/modules/officechooser/PackageChooserPage.cpp +++ b/src/modules/officechooser/PackageChooserPage.cpp @@ -32,7 +32,7 @@ PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent , m_introduction( QString(), QString(), tr( "Office Suite" ), - tr( "Please pick a office suite from the list. The selected product will be installed." ) ) + tr( "Please pick an office suite from the list. The selected product will be installed." ) ) { m_introduction.screenshot = QPixmap( QStringLiteral( ":/images/choose-office.jpg" ) ); diff --git a/src/modules/officechooser/PackageChooserViewStep.cpp b/src/modules/officechooser/PackageChooserViewStep.cpp index 925d57f4c..faafa9951 100644 --- a/src/modules/officechooser/PackageChooserViewStep.cpp +++ b/src/modules/officechooser/PackageChooserViewStep.cpp @@ -185,8 +185,8 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap m_model->addPackage( PackageItem { QString(), QString(), "No Office Suite", - "Please pick a Office Suite from the list. " - "If you don't want to install a Office Suite, that's fine, " + "Please pick an office suite from the list. " + "If you don't want to install an office suite, that's fine, " "you can install one later as needed.", ":/images/choose-office.jpg" } ); m_model->addPackage( PackageItem { "libreoffice-still", From d0531c8beb408e0298bb4a551b5cfe760841aa24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Sun, 4 Aug 2019 08:57:33 +0200 Subject: [PATCH 079/302] [postcfg] add temp some code for officechooser module --- src/modules/postcfg/main.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/modules/postcfg/main.py b/src/modules/postcfg/main.py index 00a03afa3..46bcb0cd7 100644 --- a/src/modules/postcfg/main.py +++ b/src/modules/postcfg/main.py @@ -3,7 +3,7 @@ # # === This file is part of Calamares - === # -# Copyright 2014 - 2018, Philip Müller +# Copyright 2014 - 2019, Philip Müller # Copyright 2016, Artoo # # Calamares is free software: you can redistribute it and/or modify @@ -62,6 +62,12 @@ class ConfigController: if exists(join(self.root, path)): target_env_call(['pacman', '-R', '--noconfirm', pkg]) + def umount(self, mp): + call(["umount", "-l", join(self.root, mp)]) + + def mount(self, mp): + call(["mount", "-Br", "/" + mp, join(self.root, mp)]) + def run(self): self.init_keyring() self.populate_keyring() @@ -105,6 +111,19 @@ class ConfigController: if exists(join(self.root, "usr/bin/grub-set-bootflag")): target_env_call(["grub-editenv", "-", "set", "menu_auto_hide=1", "boot_success=1"]) + # Install Office Suite if selected (WIP) + office_package = libcalamares.globalstorage.value("packagechooser_officechooser") + if not office_package: + libcalamares.utils.warning("no office suite selected, {!s}".format(office_package)) + else: + # For PoC we added the Office Packages to mhwd-live overlay in 18.1-rc7 + cmd = ["pacman", "-S", office_package, "--config", "/opt/pacman-mhwd.conf" ] + self.mount("opt") + self.mount("etc/resolv.conf") + target_env_call(cmd) + self.umount("opt") + self.umount("etc/resolv.conf") + return None From 147e6fb580290bd8eb47b0b47388298a2fb9b2c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Sun, 4 Aug 2019 09:02:32 +0200 Subject: [PATCH 080/302] [postcfg] add noconfirm for pacman cmd in officechooser --- src/modules/postcfg/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/postcfg/main.py b/src/modules/postcfg/main.py index 46bcb0cd7..e3812e90b 100644 --- a/src/modules/postcfg/main.py +++ b/src/modules/postcfg/main.py @@ -117,7 +117,7 @@ class ConfigController: libcalamares.utils.warning("no office suite selected, {!s}".format(office_package)) else: # For PoC we added the Office Packages to mhwd-live overlay in 18.1-rc7 - cmd = ["pacman", "-S", office_package, "--config", "/opt/pacman-mhwd.conf" ] + cmd = ["pacman", "-S", office_package, "--noconfirm", "--config", "/opt/pacman-mhwd.conf" ] self.mount("opt") self.mount("etc/resolv.conf") target_env_call(cmd) From 0da1cce6604f87cc5363e662536e56bdb80c5897 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Sun, 4 Aug 2019 09:30:48 +0200 Subject: [PATCH 081/302] [postcfg] make sure call is from subprocess --- src/modules/postcfg/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/postcfg/main.py b/src/modules/postcfg/main.py index e3812e90b..d847df73f 100644 --- a/src/modules/postcfg/main.py +++ b/src/modules/postcfg/main.py @@ -63,10 +63,10 @@ class ConfigController: target_env_call(['pacman', '-R', '--noconfirm', pkg]) def umount(self, mp): - call(["umount", "-l", join(self.root, mp)]) + subprocess.call(["umount", "-l", join(self.root, mp)]) def mount(self, mp): - call(["mount", "-Br", "/" + mp, join(self.root, mp)]) + subprocess.call(["mount", "-Br", "/" + mp, join(self.root, mp)]) def run(self): self.init_keyring() From beeda24423e53469bc918b02a475641247e4227f Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 4 Aug 2019 08:52:33 -0400 Subject: [PATCH 082/302] [libcalamaresui] Fix build of the PythonQt bindings - Change to std::chrono::seconds wasn't tried against the (optional) PythonQt bindings, leading to build failure. Reported by Phil (Manjaro). FIXES #1210 --- src/libcalamaresui/viewpages/PythonQtUtilsWrapper.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcalamaresui/viewpages/PythonQtUtilsWrapper.cpp b/src/libcalamaresui/viewpages/PythonQtUtilsWrapper.cpp index efb3da2a1..69027d018 100644 --- a/src/libcalamaresui/viewpages/PythonQtUtilsWrapper.cpp +++ b/src/libcalamaresui/viewpages/PythonQtUtilsWrapper.cpp @@ -57,7 +57,7 @@ Utils::target_env_call( const QString& command, int timeout ) const { return CalamaresUtils::System::instance()-> - targetEnvCall( command, QString(), stdin, timeout ); + targetEnvCall( command, QString(), stdin, std::chrono::seconds( timeout > 0 ? timeout : 0 ) ); } @@ -67,7 +67,7 @@ Utils::target_env_call( const QStringList& args, int timeout ) const { return CalamaresUtils::System::instance()-> - targetEnvCall( args, QString(), stdin, timeout ); + targetEnvCall( args, QString(), stdin, std::chrono::seconds( timeout > 0 ? timeout : 0 ) ); } @@ -102,7 +102,7 @@ Utils::check_target_env_output( const QString& command, output, QString(), stdin, - timeout ); + std::chrono::seconds( timeout > 0 ? timeout : 0 ) ); _handle_check_target_env_call_error( ec, command ); return output; } @@ -119,7 +119,7 @@ Utils::check_target_env_output( const QStringList& args, output, QString(), stdin, - timeout ); + std::chrono::seconds( timeout > 0 ? timeout : 0 ) ); _handle_check_target_env_call_error( ec, args.join( ' ' ) ); return output; } From 791f9cbccbef3fcbf5433329a313e7b4c28bbaab Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 4 Aug 2019 16:00:55 +0200 Subject: [PATCH 083/302] [packagechooser] Read packages model from config - add key *items* which will be used to fill up the model for software products. TODO: needs translation support --- .../packagechooser/PackageChooserViewStep.cpp | 55 ++++++++++++++++++- .../packagechooser/PackageChooserViewStep.h | 1 + .../packagechooser/packagechooser.conf | 35 ++++++++++++ 3 files changed, 89 insertions(+), 2 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 8515d03a9..4d9ab4f5f 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -177,6 +177,15 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap m_id = moduleInstanceKey().split( '@' ).last(); } + bool first_time = !m_model; + + ok = false; + QVariantMap items = CalamaresUtils::getSubMap( configurationMap, "items", ok ); + if ( ok ) + { + fillModel( items ); + } + // TODO: replace this hard-coded model if ( !m_model ) { @@ -192,12 +201,54 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap m_model->addPackage( PackageItem { "kde", "kde", "Plasma", "Plasma Desktop", ":/images/kde.png" } ); m_model->addPackage( PackageItem { "gnome", "gnome", "GNOME", "GNU Networked Object Modeling Environment Desktop", ":/images/gnome.png" } ); + } + if ( first_time && m_widget && m_model ) + { + hookupModel(); + } +} - if ( m_widget ) +void +PackageChooserViewStep::fillModel( const QVariantMap& items ) +{ + if ( !m_model ) + { + m_model = new PackageListModel( nullptr ); + } + + cDebug() << "Loading PackageChooser model items from config"; + for ( auto item_it = items.constKeyValueBegin(); item_it != items.constKeyValueEnd(); ++item_it ) + { + QString id = ( *item_it ).first; + + QVariantMap item_map = ( *item_it ).second.toMap(); + if ( item_map.isEmpty() ) { - hookupModel(); + cWarning() << "PackageChooser item" << id << "is not valid."; + continue; } + + QString package = CalamaresUtils::getString( item_map, "package" ); + QString name = CalamaresUtils::getString( item_map, "name" ); + QString description = CalamaresUtils::getString( item_map, "description" ); + QString screenshot = CalamaresUtils::getString( item_map, "screenshot" ); + + if ( name.isEmpty() ) + { + cWarning() << "PackageChooser item" << id << "has an empty name."; + continue; + } + if ( description.isEmpty() ) + { + description = tr( "No description provided." ); + } + if ( screenshot.isEmpty() ) + { + screenshot = QStringLiteral( ":/images/no-selection.png" ); + } + + m_model->addPackage( PackageItem { id, package, name, description, screenshot } ); } } diff --git a/src/modules/packagechooser/PackageChooserViewStep.h b/src/modules/packagechooser/PackageChooserViewStep.h index 55ed2d4d5..4d5cc346f 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.h +++ b/src/modules/packagechooser/PackageChooserViewStep.h @@ -56,6 +56,7 @@ public: void setConfigurationMap( const QVariantMap& configurationMap ) override; private: + void fillModel( const QVariantMap& items ); void hookupModel(); PackageChooserPage* m_widget; diff --git a/src/modules/packagechooser/packagechooser.conf b/src/modules/packagechooser/packagechooser.conf index b4e48c995..f4bab476c 100644 --- a/src/modules/packagechooser/packagechooser.conf +++ b/src/modules/packagechooser/packagechooser.conf @@ -19,3 +19,38 @@ # or "optionalmultiple", "requiredmultiple" (for zero-or-more # or one-or-more). mode: required + +# Items to display in the chooser. In general, this should be a +# pretty short list to avoid overwhelming the UI. +# +# Each item has a key, which is used as its ID (used in setting +# the value of *packagechooser_*). The following fields +# are mandatory: +# +# - *package* Package name for the product. While mandatory, this is +# not actually used anywhere. +# - *name* Human-readable, but untranslated, name of the product. +# - *description* Human-readable, but untranslated, description. +# - *screenshot* Path to a single screenshot of the product. May be +# a filesystem path or a QRC path (e.g. ":/images/no-selection.png"). +# +# Use the empty string "" as ID / key for the "no selection" item if +# you want to customize the display of that item as well. +items: + "": + package: "" + name: "No Desktop" + description: "Please pick a desktop environment from the list. If you don't want to install a desktop, that's fine, your system will start up in text-only mode and you can install a desktop environment later." + screenshot: ":/images/no-selection.png" + kde: + package: kde + name: Plasma Desktop + description: "KDE Plasma Desktop, simple by default, a clean work area for real-world usage which intends to stay out of your way. Plasma is powerful when needed, enabling the user to create the workflow that makes them more effective to complete their tasks." + screenshot: ":/images/kde.png" + gnome: + package: gnome + name: GNOME + description: GNU Networked Object Modeling Environment Desktop + screenshot: ":/images/gnome.png" + + From 9a52430e74d8b8b9b763725e01f150d97b378c87 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 4 Aug 2019 20:04:32 +0200 Subject: [PATCH 084/302] [packagechooser] Too many 'o's in test name --- src/modules/packagechooser/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/packagechooser/CMakeLists.txt b/src/modules/packagechooser/CMakeLists.txt index 483092800..4663ccce7 100644 --- a/src/modules/packagechooser/CMakeLists.txt +++ b/src/modules/packagechooser/CMakeLists.txt @@ -20,11 +20,11 @@ if( ECM_FOUND AND BUILD_TESTING ) ecm_add_test( Tests.cpp TEST_NAME - packagechooosertest + packagechoosertest LINK_LIBRARIES ${CALAMARES_LIBRARIES} Qt5::Core Qt5::Test ) - calamares_automoc( packagechooosertest) + calamares_automoc( packagechoosertest) endif() From b16354133da0f5873f7eee25d1e1aeec297d2483 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 4 Aug 2019 20:19:56 +0200 Subject: [PATCH 085/302] [packagechooser] Switch to a list form - Using id's as keys in a map orders them indeterminately -- in practice, alphabetically by key. Switch to a list form so that the products stick to the order they have in the config file (which means distro's can list "preferred" versions at top). --- .../packagechooser/PackageChooserViewStep.cpp | 32 +++++++++------ .../packagechooser/PackageChooserViewStep.h | 2 +- .../packagechooser/packagechooser.conf | 40 ++++++++++--------- 3 files changed, 43 insertions(+), 31 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 4d9ab4f5f..4476eb9e6 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -178,12 +178,9 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap } bool first_time = !m_model; - - ok = false; - QVariantMap items = CalamaresUtils::getSubMap( configurationMap, "items", ok ); - if ( ok ) + if ( configurationMap.contains( "items" ) ) { - fillModel( items ); + fillModel( configurationMap.value( "items" ).toList() ); } // TODO: replace this hard-coded model @@ -210,31 +207,42 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap } void -PackageChooserViewStep::fillModel( const QVariantMap& items ) +PackageChooserViewStep::fillModel( const QVariantList& items ) { if ( !m_model ) { m_model = new PackageListModel( nullptr ); } - cDebug() << "Loading PackageChooser model items from config"; - for ( auto item_it = items.constKeyValueBegin(); item_it != items.constKeyValueEnd(); ++item_it ) + if ( items.isEmpty() ) { - QString id = ( *item_it ).first; + cWarning() << "No *items* for PackageChooser module."; + return; + } - QVariantMap item_map = ( *item_it ).second.toMap(); + cDebug() << "Loading PackageChooser model items from config"; + int item_index = 0; + for ( const auto& item_it : items ) + { + ++item_index; + QVariantMap item_map = item_it.toMap(); if ( item_map.isEmpty() ) { - cWarning() << "PackageChooser item" << id << "is not valid."; + cWarning() << "PackageChooser entry" << item_index << "is not valid."; continue; } + QString id = CalamaresUtils::getString( item_map, "id" ); QString package = CalamaresUtils::getString( item_map, "package" ); QString name = CalamaresUtils::getString( item_map, "name" ); QString description = CalamaresUtils::getString( item_map, "description" ); QString screenshot = CalamaresUtils::getString( item_map, "screenshot" ); - if ( name.isEmpty() ) + if ( name.isEmpty() && id.isEmpty() ) + { + name = tr( "No product" ); + } + else if ( name.isEmpty() ) { cWarning() << "PackageChooser item" << id << "has an empty name."; continue; diff --git a/src/modules/packagechooser/PackageChooserViewStep.h b/src/modules/packagechooser/PackageChooserViewStep.h index 4d5cc346f..e3ffc1d5b 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.h +++ b/src/modules/packagechooser/PackageChooserViewStep.h @@ -56,7 +56,7 @@ public: void setConfigurationMap( const QVariantMap& configurationMap ) override; private: - void fillModel( const QVariantMap& items ); + void fillModel( const QVariantList& items ); void hookupModel(); PackageChooserPage* m_widget; diff --git a/src/modules/packagechooser/packagechooser.conf b/src/modules/packagechooser/packagechooser.conf index f4bab476c..391e1f325 100644 --- a/src/modules/packagechooser/packagechooser.conf +++ b/src/modules/packagechooser/packagechooser.conf @@ -21,12 +21,16 @@ mode: required # Items to display in the chooser. In general, this should be a -# pretty short list to avoid overwhelming the UI. +# pretty short list to avoid overwhelming the UI. This is a list +# of objects, and the items are displayed in list order. # -# Each item has a key, which is used as its ID (used in setting -# the value of *packagechooser_*). The following fields +# Each item has an id, which is used in setting # the value of +# *packagechooser_*). The following fields # are mandatory: # +# - *id* ID for the product. The ID "" is special, and is used for +# "no package selected". Only include this if the mode allows +# selecting none. # - *package* Package name for the product. While mandatory, this is # not actually used anywhere. # - *name* Human-readable, but untranslated, name of the product. @@ -37,20 +41,20 @@ mode: required # Use the empty string "" as ID / key for the "no selection" item if # you want to customize the display of that item as well. items: - "": - package: "" - name: "No Desktop" - description: "Please pick a desktop environment from the list. If you don't want to install a desktop, that's fine, your system will start up in text-only mode and you can install a desktop environment later." - screenshot: ":/images/no-selection.png" - kde: - package: kde - name: Plasma Desktop - description: "KDE Plasma Desktop, simple by default, a clean work area for real-world usage which intends to stay out of your way. Plasma is powerful when needed, enabling the user to create the workflow that makes them more effective to complete their tasks." - screenshot: ":/images/kde.png" - gnome: - package: gnome - name: GNOME - description: GNU Networked Object Modeling Environment Desktop - screenshot: ":/images/gnome.png" + - id: "" + package: "" + name: "No Desktop" + description: "Please pick a desktop environment from the list. If you don't want to install a desktop, that's fine, your system will start up in text-only mode and you can install a desktop environment later." + screenshot: ":/images/no-selection.png" + - id: kde + package: kde + name: Plasma Desktop + description: "KDE Plasma Desktop, DERP" + screenshot: ":/images/kde.png" + - id: gnome + package: gnome + name: GNOME + description: GNU Networked Object Modeling Environment Desktop + screenshot: ":/images/gnome.png" From 2556ba9d558e94612c11426e04b924ba47d9c837 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 4 Aug 2019 21:45:44 +0200 Subject: [PATCH 086/302] CI: set style for macro continuations --- .clang-format | 1 + 1 file changed, 1 insertion(+) diff --git a/.clang-format b/.clang-format index 997ad379b..d76498a3e 100644 --- a/.clang-format +++ b/.clang-format @@ -2,6 +2,7 @@ BasedOnStyle: WebKit AlignAfterOpenBracket: Align +AlignEscapedNewlines: Left AllowAllParametersOfDeclarationOnNextLine: 'false' AllowShortFunctionsOnASingleLine: Inline AllowShortIfStatementsOnASingleLine: 'false' From b7f54a3866dac05e4945bb77ad9ede648c63de10 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 4 Aug 2019 21:30:38 +0200 Subject: [PATCH 087/302] [libcalamares] Don't break string tables by reformatting --- src/libcalamares/utils/String.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libcalamares/utils/String.cpp b/src/libcalamares/utils/String.cpp index a39ebd8c7..f577aee17 100644 --- a/src/libcalamares/utils/String.cpp +++ b/src/libcalamares/utils/String.cpp @@ -31,6 +31,11 @@ namespace CalamaresUtils QString removeDiacritics( const QString& string ) { + // *INDENT-OFF* + // clang-format off + // Map these extended-Latin characters to ASCII; keep the + // layout so that one line in *diacriticLetters* corresponds + // to one line of replacements in *noDiacriticLetters*. static const QString diacriticLetters = QString::fromUtf8( "ŠŒŽšœžŸ¥µÀ" "ÁÂÃÄÅÆÇÈÉÊ" @@ -65,6 +70,8 @@ removeDiacritics( const QString& string ) "r", "A", "a", "E", "e", "L", "l", "N", "n", "S", "s", "Z", "z", "Z", "z" }; + // clang-format on + // *INDENT-ON* QString output; for ( const QChar &c : string ) From 29b9a21f5911a2585114da41bab9c9bbc4e650d2 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 4 Aug 2019 22:01:01 +0200 Subject: [PATCH 088/302] [libcalamares] Don't format files copied from KCoreAddons --- src/libcalamares/utils/PluginFactory.cpp | 5 ++++- src/libcalamares/utils/PluginFactory.h | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/libcalamares/utils/PluginFactory.cpp b/src/libcalamares/utils/PluginFactory.cpp index 124af16f4..878182ea4 100644 --- a/src/libcalamares/utils/PluginFactory.cpp +++ b/src/libcalamares/utils/PluginFactory.cpp @@ -24,8 +24,11 @@ #include "PluginFactory.h" #include "PluginFactory_p.h" -#include #include +#include + +// *INDENT-OFF* +// clang-format off Q_GLOBAL_STATIC( QObjectCleanupHandler, factorycleanup ) diff --git a/src/libcalamares/utils/PluginFactory.h b/src/libcalamares/utils/PluginFactory.h index 1ab485779..f2481f10d 100644 --- a/src/libcalamares/utils/PluginFactory.h +++ b/src/libcalamares/utils/PluginFactory.h @@ -27,8 +27,11 @@ #include "DllMacro.h" #include -#include #include +#include + +// *INDENT-OFF* +// clang-format off namespace Calamares { From b8a74657f4ce84a96328da27068a440518cc3ccb Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 4 Aug 2019 21:22:54 +0200 Subject: [PATCH 089/302] [libcalamares] Apply current coding style to libcalamares/utils/ - String.cpp needs special handling since part of it should remain unchanged, the formatting is "special" there. --- .../utils/CalamaresUtilsSystem.cpp | 154 +++++---- src/libcalamares/utils/CalamaresUtilsSystem.h | 73 +++-- src/libcalamares/utils/CommandList.cpp | 52 ++- src/libcalamares/utils/CommandList.h | 36 +-- src/libcalamares/utils/Dirs.cpp | 18 +- src/libcalamares/utils/Dirs.h | 64 ++-- src/libcalamares/utils/Logger.cpp | 78 ++--- src/libcalamares/utils/Logger.h | 298 +++++++++--------- src/libcalamares/utils/NamedEnum.h | 25 +- src/libcalamares/utils/NamedSuffix.h | 8 +- src/libcalamares/utils/PluginFactory_p.h | 13 +- src/libcalamares/utils/Retranslator.cpp | 33 +- src/libcalamares/utils/Retranslator.h | 28 +- src/libcalamares/utils/String.cpp | 16 +- src/libcalamares/utils/String.h | 28 +- src/libcalamares/utils/Units.h | 60 ++-- src/libcalamares/utils/Variant.cpp | 14 +- src/libcalamares/utils/Variant.h | 54 ++-- src/libcalamares/utils/Yaml.cpp | 63 ++-- src/libcalamares/utils/Yaml.h | 4 +- 20 files changed, 623 insertions(+), 496 deletions(-) diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.cpp b/src/libcalamares/utils/CalamaresUtilsSystem.cpp index 894c434be..6221c1f15 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.cpp +++ b/src/libcalamares/utils/CalamaresUtilsSystem.cpp @@ -19,10 +19,10 @@ #include "CalamaresUtilsSystem.h" -#include "utils/Logger.h" #include "GlobalStorage.h" #include "JobQueue.h" #include "Settings.h" +#include "utils/Logger.h" #include #include @@ -34,8 +34,8 @@ #endif #ifdef Q_OS_FREEBSD -#include #include +#include #endif /** @brief When logging commands, don't log everything. @@ -48,12 +48,12 @@ struct RedactedList { RedactedList( const QStringList& l ) - : list(l) + : list( l ) { } const QStringList& list; -} ; +}; QDebug& operator<<( QDebug& s, const RedactedList& l ) @@ -63,12 +63,18 @@ operator<<( QDebug& s, const RedactedList& l ) { for ( const auto& item : l.list ) if ( item.startsWith( "$6$" ) ) + { s << ""; + } else + { s << item; + } } else + { s << l.list; + } return s; } @@ -92,8 +98,7 @@ System::System( bool doChroot, QObject* parent ) } -System::~System() -{} +System::~System() {} System* @@ -111,18 +116,22 @@ System::instance() int System::mount( const QString& devicePath, - const QString& mountPoint, - const QString& filesystemName, - const QString& options ) + const QString& mountPoint, + const QString& filesystemName, + const QString& options ) { if ( devicePath.isEmpty() || mountPoint.isEmpty() ) { if ( devicePath.isEmpty() ) + { cWarning() << "Can't mount an empty device."; + } if ( mountPoint.isEmpty() ) + { cWarning() << "Can't mount on an empty mountpoint."; + } - return static_cast(ProcessResult::Code::NoWorkingDirectory); + return static_cast< int >( ProcessResult::Code::NoWorkingDirectory ); } QDir mountPointDir( mountPoint ); @@ -132,7 +141,7 @@ System::mount( const QString& devicePath, if ( !ok ) { cWarning() << "Could not create mountpoint" << mountPoint; - return static_cast(ProcessResult::Code::NoWorkingDirectory); + return static_cast< int >( ProcessResult::Code::NoWorkingDirectory ); } } @@ -140,28 +149,31 @@ System::mount( const QString& devicePath, QStringList args = { devicePath, mountPoint }; if ( !filesystemName.isEmpty() ) + { args << "-t" << filesystemName; + } if ( !options.isEmpty() ) + { args << "-o" << options; + } return QProcess::execute( program, args ); } ProcessResult -System::runCommand( - System::RunLocation location, - const QStringList& args, - const QString& workingPath, - const QString& stdInput, - std::chrono::seconds timeoutSec ) +System::runCommand( System::RunLocation location, + const QStringList& args, + const QString& workingPath, + const QString& stdInput, + std::chrono::seconds timeoutSec ) { QString output; - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; + Calamares::GlobalStorage* gs + = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; - if ( ( location == System::RunLocation::RunInTarget ) && - ( !gs || !gs->contains( "rootMountPoint" ) ) ) + if ( ( location == System::RunLocation::RunInTarget ) && ( !gs || !gs->contains( "rootMountPoint" ) ) ) { cWarning() << "No rootMountPoint in global storage"; return ProcessResult::Code::NoWorkingDirectory; @@ -197,7 +209,9 @@ System::runCommand( if ( !workingPath.isEmpty() ) { if ( QDir( workingPath ).exists() ) + { process.setWorkingDirectory( QDir( workingPath ).absolutePath() ); + } else { cWarning() << "Invalid working directory:" << workingPath; @@ -219,10 +233,10 @@ System::runCommand( } process.closeWriteChannel(); - if ( !process.waitForFinished( timeoutSec > std::chrono::seconds::zero() ? ( std::chrono::milliseconds( timeoutSec ).count() ) : -1 ) ) + if ( !process.waitForFinished( + timeoutSec > std::chrono::seconds::zero() ? ( std::chrono::milliseconds( timeoutSec ).count() ) : -1 ) ) { - cWarning().noquote().nospace() << "Timed out. Output so far:\n" << - process.readAllStandardOutput(); + cWarning().noquote().nospace() << "Timed out. Output so far:\n" << process.readAllStandardOutput(); return ProcessResult::Code::TimedOut; } @@ -242,7 +256,7 @@ System::runCommand( cDebug() << "Target cmd:" << RedactedList( args ); cDebug().noquote().nospace() << "Target output:\n" << output; } - return ProcessResult(r, output); + return ProcessResult( r, output ); } QString @@ -252,7 +266,8 @@ System::targetPath( const QString& path ) const if ( doChroot() ) { - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; + Calamares::GlobalStorage* gs + = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; if ( !gs || !gs->contains( "rootMountPoint" ) ) { @@ -309,28 +324,32 @@ System::createTargetFile( const QString& path, const QByteArray& contents ) cons } -QPair +QPair< quint64, float > System::getTotalMemoryB() const { #ifdef Q_OS_LINUX struct sysinfo i; int r = sysinfo( &i ); - if (r) - return qMakePair(0, 0.0); + if ( r ) + { + return qMakePair( 0, 0.0 ); + } - return qMakePair(quint64( i.mem_unit ) * quint64( i.totalram ), 1.1); + return qMakePair( quint64( i.mem_unit ) * quint64( i.totalram ), 1.1 ); #elif defined( Q_OS_FREEBSD ) unsigned long memsize; - size_t s = sizeof(memsize); + size_t s = sizeof( memsize ); - int r = sysctlbyname("vm.kmem_size", &memsize, &s, NULL, 0); - if (r) - return qMakePair(0, 0.0); + int r = sysctlbyname( "vm.kmem_size", &memsize, &s, NULL, 0 ); + if ( r ) + { + return qMakePair( 0, 0.0 ); + } - return qMakePair(memsize, 1.01); + return qMakePair( memsize, 1.01 ); #else - return qMakePair(0, 0.0); // Unsupported + return qMakePair( 0, 0.0 ); // Unsupported #endif } @@ -341,14 +360,14 @@ System::getCpuDescription() const QString model; #ifdef Q_OS_LINUX - QFile file("/proc/cpuinfo"); - if ( file.open(QIODevice::ReadOnly | QIODevice::Text) ) + QFile file( "/proc/cpuinfo" ); + if ( file.open( QIODevice::ReadOnly | QIODevice::Text ) ) while ( !file.atEnd() ) { QByteArray line = file.readLine(); - if ( line.startsWith( "model name" ) && (line.indexOf( ':' ) > 0) ) + if ( line.startsWith( "model name" ) && ( line.indexOf( ':' ) > 0 ) ) { - model = QString::fromLatin1( line.right(line.length() - line.indexOf( ':' ) ) ); + model = QString::fromLatin1( line.right( line.length() - line.indexOf( ':' ) ) ); break; } } @@ -376,40 +395,45 @@ ProcessResult::explainProcess( int ec, const QString& command, const QString& ou using Calamares::JobResult; if ( ec == 0 ) + { return JobResult::ok(); + } QString outputMessage = output.isEmpty() - ? QCoreApplication::translate( "ProcessResult", "\nThere was no output from the command.") - : (QCoreApplication::translate( "ProcessResult", "\nOutput:\n") + output); + ? QCoreApplication::translate( "ProcessResult", "\nThere was no output from the command." ) + : ( QCoreApplication::translate( "ProcessResult", "\nOutput:\n" ) + output ); - if ( ec == static_cast(ProcessResult::Code::Crashed) ) //Crash! - return JobResult::error( QCoreApplication::translate( "ProcessResult", "External command crashed." ), - QCoreApplication::translate( "ProcessResult", "Command %1 crashed." ) - .arg( command ) - + outputMessage ); + if ( ec == static_cast< int >( ProcessResult::Code::Crashed ) ) //Crash! + return JobResult::error( + QCoreApplication::translate( "ProcessResult", "External command crashed." ), + QCoreApplication::translate( "ProcessResult", "Command %1 crashed." ).arg( command ) + + outputMessage ); - if ( ec == static_cast(ProcessResult::Code::FailedToStart) ) - return JobResult::error( QCoreApplication::translate( "ProcessResult", "External command failed to start." ), - QCoreApplication::translate( "ProcessResult", "Command %1 failed to start." ) - .arg( command ) ); + if ( ec == static_cast< int >( ProcessResult::Code::FailedToStart ) ) + return JobResult::error( + QCoreApplication::translate( "ProcessResult", "External command failed to start." ), + QCoreApplication::translate( "ProcessResult", "Command %1 failed to start." ).arg( command ) ); - if ( ec == static_cast(ProcessResult::Code::NoWorkingDirectory) ) - return JobResult::error( QCoreApplication::translate( "ProcessResult", "Internal error when starting command." ), - QCoreApplication::translate( "ProcessResult", "Bad parameters for process job call." ) ); + if ( ec == static_cast< int >( ProcessResult::Code::NoWorkingDirectory ) ) + return JobResult::error( + QCoreApplication::translate( "ProcessResult", "Internal error when starting command." ), + QCoreApplication::translate( "ProcessResult", "Bad parameters for process job call." ) ); - if ( ec == static_cast(ProcessResult::Code::TimedOut) ) - return JobResult::error( QCoreApplication::translate( "ProcessResult", "External command failed to finish." ), - QCoreApplication::translate( "ProcessResult", "Command %1 failed to finish in %2 seconds." ) - .arg( command ) - .arg( timeout.count() ) - + outputMessage ); + if ( ec == static_cast< int >( ProcessResult::Code::TimedOut ) ) + return JobResult::error( + QCoreApplication::translate( "ProcessResult", "External command failed to finish." ), + QCoreApplication::translate( "ProcessResult", "Command %1 failed to finish in %2 seconds." ) + .arg( command ) + .arg( timeout.count() ) + + outputMessage ); //Any other exit code - return JobResult::error( QCoreApplication::translate( "ProcessResult", "External command finished with errors." ), - QCoreApplication::translate( "ProcessResult", "Command %1 finished with exit code %2." ) - .arg( command ) - .arg( ec ) - + outputMessage ); + return JobResult::error( + QCoreApplication::translate( "ProcessResult", "External command finished with errors." ), + QCoreApplication::translate( "ProcessResult", "Command %1 finished with exit code %2." ) + .arg( command ) + .arg( ec ) + + outputMessage ); } -} // namespace +} // namespace CalamaresUtils diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.h b/src/libcalamares/utils/CalamaresUtilsSystem.h index 5b10f7d1a..8265f0fdb 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.h +++ b/src/libcalamares/utils/CalamaresUtilsSystem.h @@ -36,15 +36,21 @@ class ProcessResult : public QPair< int, QString > public: enum class Code : int { - Crashed = -1, // Must match special return values from QProcess + Crashed = -1, // Must match special return values from QProcess FailedToStart = -2, // Must match special return values from QProcess NoWorkingDirectory = -3, TimedOut = -4 - } ; + }; /** @brief Implicit one-argument constructor has no output, only a return code */ - ProcessResult( Code r ) : QPair< int, QString >( static_cast(r), QString() ) {} - ProcessResult( int r, QString s ) : QPair< int, QString >( r, s ) {} + ProcessResult( Code r ) + : QPair< int, QString >( static_cast< int >( r ), QString() ) + { + } + ProcessResult( int r, QString s ) + : QPair< int, QString >( r, s ) + { + } int getExitCode() const { return first; } QString getOutput() const { return second; } @@ -62,7 +68,8 @@ public: * @param timeout Timeout passed to the process runner, for explaining * error code -4 (timeout). */ - static Calamares::JobResult explainProcess( int errorCode, const QString& command, const QString& output, std::chrono::seconds timeout ); + static Calamares::JobResult + explainProcess( int errorCode, const QString& command, const QString& output, std::chrono::seconds timeout ); /// @brief Convenience wrapper for explainProcess() inline Calamares::JobResult explainProcess( const QString& command, std::chrono::seconds timeout ) const @@ -75,7 +82,7 @@ public: { return explainProcess( getExitCode(), command.join( ' ' ), getOutput(), timeout ); } -} ; +}; /** * @brief The System class is a singleton with utility functions that perform @@ -116,7 +123,11 @@ public: /** (Typed) Boolean describing where a particular command should be run, * whether in the host (live) system or in the (chroot) target system. */ - enum class RunLocation { RunInHost, RunInTarget }; + enum class RunLocation + { + RunInHost, + RunInTarget + }; /** * Runs the specified command in the chroot of the target system. @@ -135,37 +146,31 @@ public: * NoWorkingDirectory = bad arguments * TimedOut = QProcess timeout */ - static DLLEXPORT ProcessResult runCommand( - RunLocation location, - const QStringList &args, - const QString& workingPath = QString(), - const QString& stdInput = QString(), - std::chrono::seconds timeoutSec = std::chrono::seconds(0) ); + static DLLEXPORT ProcessResult runCommand( RunLocation location, + const QStringList& args, + const QString& workingPath = QString(), + const QString& stdInput = QString(), + std::chrono::seconds timeoutSec = std::chrono::seconds( 0 ) ); /** @brief Convenience wrapper for runCommand(). * Runs the command in the location specified through the boolean * doChroot(), which is what you usually want for running commands * during installation. */ - inline ProcessResult targetEnvCommand( - const QStringList &args, - const QString& workingPath = QString(), - const QString& stdInput = QString(), - std::chrono::seconds timeoutSec = std::chrono::seconds(0) ) + inline ProcessResult targetEnvCommand( const QStringList& args, + const QString& workingPath = QString(), + const QString& stdInput = QString(), + std::chrono::seconds timeoutSec = std::chrono::seconds( 0 ) ) { return runCommand( - m_doChroot ? RunLocation::RunInTarget : RunLocation::RunInHost, - args, - workingPath, - stdInput, - timeoutSec ); + m_doChroot ? RunLocation::RunInTarget : RunLocation::RunInHost, args, workingPath, stdInput, timeoutSec ); } /** @brief Convenience wrapper for targetEnvCommand() which returns only the exit code */ inline int targetEnvCall( const QStringList& args, const QString& workingPath = QString(), const QString& stdInput = QString(), - std::chrono::seconds timeoutSec = std::chrono::seconds(0) ) + std::chrono::seconds timeoutSec = std::chrono::seconds( 0 ) ) { return targetEnvCommand( args, workingPath, stdInput, timeoutSec ).first; } @@ -174,9 +179,9 @@ public: inline int targetEnvCall( const QString& command, const QString& workingPath = QString(), const QString& stdInput = QString(), - std::chrono::seconds timeoutSec = std::chrono::seconds(0) ) + std::chrono::seconds timeoutSec = std::chrono::seconds( 0 ) ) { - return targetEnvCall( QStringList{ command }, workingPath, stdInput, timeoutSec ); + return targetEnvCall( QStringList { command }, workingPath, stdInput, timeoutSec ); } /** @brief Convenience wrapper for targetEnvCommand() which returns only the exit code @@ -184,10 +189,10 @@ public: * Places the called program's output in the @p output string. */ int targetEnvOutput( const QStringList& args, - QString& output, - const QString& workingPath = QString(), - const QString& stdInput = QString(), - std::chrono::seconds timeoutSec = std::chrono::seconds(0) ) + QString& output, + const QString& workingPath = QString(), + const QString& stdInput = QString(), + std::chrono::seconds timeoutSec = std::chrono::seconds( 0 ) ) { auto r = targetEnvCommand( args, workingPath, stdInput, timeoutSec ); output = r.second; @@ -202,9 +207,9 @@ public: QString& output, const QString& workingPath = QString(), const QString& stdInput = QString(), - std::chrono::seconds timeoutSec = std::chrono::seconds(0) ) + std::chrono::seconds timeoutSec = std::chrono::seconds( 0 ) ) { - return targetEnvOutput( QStringList{ command }, output, workingPath, stdInput, timeoutSec ); + return targetEnvOutput( QStringList { command }, output, workingPath, stdInput, timeoutSec ); } @@ -255,7 +260,7 @@ public: * * @return size, guesstimate-factor */ - DLLEXPORT QPair getTotalMemoryB() const; + DLLEXPORT QPair< quint64, float > getTotalMemoryB() const; /** * @brief getCpuDescription returns a string describing the CPU. @@ -279,6 +284,6 @@ private: bool m_doChroot; }; -} // namespace +} // namespace CalamaresUtils #endif diff --git a/src/libcalamares/utils/CommandList.cpp b/src/libcalamares/utils/CommandList.cpp index 414cfa9e5..85b4cd1e3 100644 --- a/src/libcalamares/utils/CommandList.cpp +++ b/src/libcalamares/utils/CommandList.cpp @@ -32,34 +32,44 @@ namespace CalamaresUtils { -static CommandLine get_variant_object( const QVariantMap& m ) +static CommandLine +get_variant_object( const QVariantMap& m ) { QString command = CalamaresUtils::getString( m, "command" ); int timeout = CalamaresUtils::getInteger( m, "timeout", -1 ); if ( !command.isEmpty() ) + { return CommandLine( command, timeout >= 0 ? std::chrono::seconds( timeout ) : CommandLine::TimeoutNotSet() ); + } cWarning() << "Bad CommandLine element" << m; return CommandLine(); } -static CommandList_t get_variant_stringlist( const QVariantList& l ) +static CommandList_t +get_variant_stringlist( const QVariantList& l ) { CommandList_t retl; unsigned int count = 0; for ( const auto& v : l ) { if ( v.type() == QVariant::String ) + { retl.append( CommandLine( v.toString(), CommandLine::TimeoutNotSet() ) ); + } else if ( v.type() == QVariant::Map ) { auto command( get_variant_object( v.toMap() ) ); if ( command.isValid() ) + { retl.append( command ); + } // Otherwise warning is already given } else + { cWarning() << "Bad CommandList element" << count << v.type() << v; + } ++count; } return retl; @@ -78,37 +88,48 @@ CommandList::CommandList::CommandList( const QVariant& v, bool doChroot, std::ch { const auto v_list = v.toList(); if ( v_list.count() ) + { append( get_variant_stringlist( v_list ) ); + } else + { cWarning() << "Empty CommandList"; + } } else if ( v.type() == QVariant::String ) + { append( v.toString() ); + } else if ( v.type() == QVariant::Map ) { auto c( get_variant_object( v.toMap() ) ); if ( c.isValid() ) + { append( c ); + } // Otherwise warning is already given } else + { cWarning() << "CommandList does not understand variant" << v.type(); + } } -CommandList::~CommandList() -{ -} +CommandList::~CommandList() {} static inline bool findInCommands( const CommandList& l, const QString& needle ) { for ( CommandList::const_iterator i = l.cbegin(); i != l.cend(); ++i ) if ( i->command().contains( needle ) ) + { return true; + } return false; } -Calamares::JobResult CommandList::run() +Calamares::JobResult +CommandList::run() { QLatin1Literal rootMagic( "@@ROOT@@" ); QLatin1Literal userMagic( "@@USER@@" ); @@ -125,8 +146,11 @@ Calamares::JobResult CommandList::run() if ( !gs || !gs->contains( "rootMountPoint" ) ) { cError() << "No rootMountPoint defined."; - return Calamares::JobResult::error( QCoreApplication::translate( "CommandList", "Could not run command." ), - QCoreApplication::translate( "CommandList", "The command runs in the host environment and needs to know the root path, but no rootMountPoint is defined." ) ); + return Calamares::JobResult::error( + QCoreApplication::translate( "CommandList", "Could not run command." ), + QCoreApplication::translate( "CommandList", + "The command runs in the host environment and needs to know the root " + "path, but no rootMountPoint is defined." ) ); } root = gs->value( "rootMountPoint" ).toString(); } @@ -137,7 +161,8 @@ Calamares::JobResult CommandList::run() cError() << "No username defined."; return Calamares::JobResult::error( QCoreApplication::translate( "CommandList", "Could not run command." ), - QCoreApplication::translate( "CommandList", "The command needs to know the user's name, but no username is defined." ) ); + QCoreApplication::translate( "CommandList", + "The command needs to know the user's name, but no username is defined." ) ); } QString user = gs->value( "username" ).toString(); // may be blank if unset @@ -156,15 +181,18 @@ Calamares::JobResult CommandList::run() shell_cmd << processed_cmd; std::chrono::seconds timeout = i->timeout() >= std::chrono::seconds::zero() ? i->timeout() : m_timeout; - ProcessResult r = System::runCommand( - location, shell_cmd, QString(), QString(), timeout ); + ProcessResult r = System::runCommand( location, shell_cmd, QString(), QString(), timeout ); if ( r.getExitCode() != 0 ) { if ( suppress_result ) + { cDebug() << "Error code" << r.getExitCode() << "ignored by CommandList configuration."; + } else + { return r.explainProcess( processed_cmd, timeout ); + } } } @@ -177,4 +205,4 @@ CommandList::append( const QString& s ) append( CommandLine( s, m_timeout ) ); } -} // namespace +} // namespace CalamaresUtils diff --git a/src/libcalamares/utils/CommandList.h b/src/libcalamares/utils/CommandList.h index 7453ae6ce..71a5a483c 100644 --- a/src/libcalamares/utils/CommandList.h +++ b/src/libcalamares/utils/CommandList.h @@ -35,7 +35,7 @@ namespace CalamaresUtils */ struct CommandLine : public QPair< QString, std::chrono::seconds > { - static inline constexpr std::chrono::seconds TimeoutNotSet() { return std::chrono::seconds(-1); } + static inline constexpr std::chrono::seconds TimeoutNotSet() { return std::chrono::seconds( -1 ); } /// An invalid command line CommandLine() @@ -49,25 +49,16 @@ struct CommandLine : public QPair< QString, std::chrono::seconds > } CommandLine( const QString& s, std::chrono::seconds t ) - : QPair( s, t) + : QPair( s, t ) { } - QString command() const - { - return first; - } + QString command() const { return first; } - std::chrono::seconds timeout() const - { - return second; - } + std::chrono::seconds timeout() const { return second; } - bool isValid() const - { - return !first.isEmpty(); - } -} ; + bool isValid() const { return !first.isEmpty(); } +}; /** @brief Abbreviation, used internally. */ using CommandList_t = QList< CommandLine >; @@ -88,19 +79,16 @@ public: CommandList( const QVariant& v, bool doChroot = true, std::chrono::seconds timeout = std::chrono::seconds( 10 ) ); ~CommandList(); - bool doChroot() const - { - return m_doChroot; - } + bool doChroot() const { return m_doChroot; } Calamares::JobResult run(); - using CommandList_t::isEmpty; - using CommandList_t::count; + using CommandList_t::at; using CommandList_t::cbegin; using CommandList_t::cend; using CommandList_t::const_iterator; - using CommandList_t::at; + using CommandList_t::count; + using CommandList_t::isEmpty; protected: using CommandList_t::append; @@ -109,7 +97,7 @@ protected: private: bool m_doChroot; std::chrono::seconds m_timeout; -} ; +}; -} // namespace +} // namespace CalamaresUtils #endif diff --git a/src/libcalamares/utils/Dirs.cpp b/src/libcalamares/utils/Dirs.cpp index 1fd309584..ca569490f 100644 --- a/src/libcalamares/utils/Dirs.cpp +++ b/src/libcalamares/utils/Dirs.cpp @@ -101,16 +101,24 @@ mungeEnvironment( QStringList& l, const char* name, const char* defaultDirs ) QStringList dirs = QString( qgetenv( name ) ).split( ':' ); if ( dirs.isEmpty() ) + { dirs = QString( defaultDirs ).split( ':' ); + } for ( auto s : dirs ) { if ( s.isEmpty() ) + { continue; + } if ( s.endsWith( '/' ) ) + { l << ( s + calamaresSubdir ) << s; + } else + { l << ( s + '/' + calamaresSubdir ) << ( s + '/' ); + } } } @@ -127,7 +135,9 @@ QStringList extraConfigDirs() { if ( s_haveExtraDirs ) + { return s_extraConfigDirs; + } return QStringList(); } @@ -135,7 +145,9 @@ QStringList extraDataDirs() { if ( s_haveExtraDirs ) + { return s_extraDataDirs; + } return QStringList(); } @@ -173,12 +185,16 @@ appLogDir() QString path = QStandardPaths::writableLocation( QStandardPaths::CacheLocation ); QDir dir( path ); if ( isWritableDir( dir ) ) + { return dir; + } cerr << "warning: Could not find a standard writable location for log dir, falling back to $HOME\n"; dir = QDir::home(); if ( isWritableDir( dir ) ) + { return dir; + } cerr << "warning: Found no writable location for log dir, falling back to the temp dir\n"; return QDir::temp(); @@ -191,4 +207,4 @@ setQmlModulesDir( const QDir& dir ) s_qmlModulesDir = dir; } -} // namespace +} // namespace CalamaresUtils diff --git a/src/libcalamares/utils/Dirs.h b/src/libcalamares/utils/Dirs.h index 5532cb79b..a63e679da 100644 --- a/src/libcalamares/utils/Dirs.h +++ b/src/libcalamares/utils/Dirs.h @@ -31,43 +31,43 @@ namespace CalamaresUtils { - DLLEXPORT QDir qmlModulesDir(); +DLLEXPORT QDir qmlModulesDir(); - /** - * @brief appDataDir returns the directory with common application data. - * Defaults to CMAKE_INSTALL_FULL_DATADIR (usually /usr/share/calamares). - */ - DLLEXPORT QDir appDataDir(); +/** + * @brief appDataDir returns the directory with common application data. + * Defaults to CMAKE_INSTALL_FULL_DATADIR (usually /usr/share/calamares). + */ +DLLEXPORT QDir appDataDir(); - /** - * @brief appLogDir returns the directory for Calamares logs. - * Defaults to QStandardPaths::CacheLocation (usually ~/.cache/Calamares). - */ - DLLEXPORT QDir appLogDir(); +/** + * @brief appLogDir returns the directory for Calamares logs. + * Defaults to QStandardPaths::CacheLocation (usually ~/.cache/Calamares). + */ +DLLEXPORT QDir appLogDir(); - /** - * @brief systemLibDir returns the system's lib directory. - * Defaults to CMAKE_INSTALL_FULL_LIBDIR (usually /usr/lib64 or /usr/lib). - */ - DLLEXPORT QDir systemLibDir(); +/** + * @brief systemLibDir returns the system's lib directory. + * Defaults to CMAKE_INSTALL_FULL_LIBDIR (usually /usr/lib64 or /usr/lib). + */ +DLLEXPORT QDir systemLibDir(); - /** - * Override app data dir. Only for testing purposes. - */ - DLLEXPORT void setAppDataDir( const QDir& dir ); - DLLEXPORT bool isAppDataDirOverridden(); +/** + * Override app data dir. Only for testing purposes. + */ +DLLEXPORT void setAppDataDir( const QDir& dir ); +DLLEXPORT bool isAppDataDirOverridden(); - DLLEXPORT void setQmlModulesDir( const QDir& dir ); +DLLEXPORT void setQmlModulesDir( const QDir& dir ); - /** @brief Setup extra config and data dirs from the XDG variables. - */ - DLLEXPORT void setXdgDirs(); - /** @brief Are any extra directories configured? */ - DLLEXPORT bool haveExtraDirs(); - /** @brief XDG_CONFIG_DIRS, each guaranteed to end with / */ - DLLEXPORT QStringList extraConfigDirs(); - /** @brief XDG_DATA_DIRS, each guaranteed to end with / */ - DLLEXPORT QStringList extraDataDirs(); -} // namespace +/** @brief Setup extra config and data dirs from the XDG variables. + */ +DLLEXPORT void setXdgDirs(); +/** @brief Are any extra directories configured? */ +DLLEXPORT bool haveExtraDirs(); +/** @brief XDG_CONFIG_DIRS, each guaranteed to end with / */ +DLLEXPORT QStringList extraConfigDirs(); +/** @brief XDG_DATA_DIRS, each guaranteed to end with / */ +DLLEXPORT QStringList extraDataDirs(); +} // namespace CalamaresUtils #endif diff --git a/src/libcalamares/utils/Logger.cpp b/src/libcalamares/utils/Logger.cpp index 433e01fbb..0e207fa02 100644 --- a/src/libcalamares/utils/Logger.cpp +++ b/src/libcalamares/utils/Logger.cpp @@ -20,8 +20,8 @@ #include "Logger.h" -#include #include +#include #include #include @@ -30,17 +30,17 @@ #include #include -#include "utils/Dirs.h" #include "CalamaresVersion.h" +#include "utils/Dirs.h" #define LOGFILE_SIZE 1024 * 256 static std::ofstream logfile; static unsigned int s_threshold = #ifdef QT_NO_DEBUG - Logger::LOG_DISABLE; + Logger::LOG_DISABLE; #else - Logger::LOGEXTRA + 1; // Comparison is < in log() function + Logger::LOGEXTRA + 1; // Comparison is < in log() function #endif static QMutex s_mutex; @@ -48,15 +48,17 @@ namespace Logger { void -setupLogLevel(unsigned int level) +setupLogLevel( unsigned int level ) { if ( level > LOGVERBOSE ) + { level = LOGVERBOSE; + } s_threshold = level + 1; // Comparison is < in log() function } bool -logLevelEnabled(unsigned int level) +logLevelEnabled( unsigned int level ) { return level < s_threshold; } @@ -77,11 +79,9 @@ log( const char* msg, unsigned int debugLevel ) // If we don't format the date as a Qt::ISODate then we get a crash when // logging at exit as Qt tries to use QLocale to format, but QLocale is // on its way out. - logfile << QDate::currentDate().toString( Qt::ISODate ).toUtf8().data() - << " - " - << QTime::currentTime().toString().toUtf8().data() - << " [" << QString::number( debugLevel ).toUtf8().data() << "]: " - << msg << std::endl; + logfile << QDate::currentDate().toString( Qt::ISODate ).toUtf8().data() << " - " + << QTime::currentTime().toString().toUtf8().data() << " [" + << QString::number( debugLevel ).toUtf8().data() << "]: " << msg << std::endl; logfile.flush(); } @@ -90,9 +90,8 @@ log( const char* msg, unsigned int debugLevel ) { QMutexLocker lock( &s_mutex ); - std::cout << QTime::currentTime().toString().toUtf8().data() - << " [" << QString::number( debugLevel ).toUtf8().data() << "]: " - << msg << std::endl; + std::cout << QTime::currentTime().toString().toUtf8().data() << " [" + << QString::number( debugLevel ).toUtf8().data() << "]: " << msg << std::endl; std::cout.flush(); } } @@ -107,21 +106,21 @@ CalamaresLogHandler( QtMsgType type, const QMessageLogContext&, const QString& m const char* message = ba.constData(); QMutexLocker locker( &s_mutex ); - switch( type ) + switch ( type ) { - case QtDebugMsg: - log( message, LOGVERBOSE ); - break; + case QtDebugMsg: + log( message, LOGVERBOSE ); + break; - case QtInfoMsg: - log( message, 1 ); - break; + case QtInfoMsg: + log( message, 1 ); + break; - case QtCriticalMsg: - case QtWarningMsg: - case QtFatalMsg: - log( message, 0 ); - break; + case QtCriticalMsg: + case QtWarningMsg: + case QtFatalMsg: + log( message, 0 ); + break; } } @@ -161,11 +160,13 @@ setupLogfile() // Lock while (re-)opening the logfile { - QMutexLocker lock( &s_mutex ); - logfile.open( logFile().toLocal8Bit(), std::ios::app ); - if ( logfile.tellp() ) - logfile << "\n\n" << std::endl; - logfile << "=== START CALAMARES " << CALAMARES_VERSION << std::endl; + QMutexLocker lock( &s_mutex ); + logfile.open( logFile().toLocal8Bit(), std::ios::app ); + if ( logfile.tellp() ) + { + logfile << "\n\n" << std::endl; + } + logfile << "=== START CALAMARES " << CALAMARES_VERSION << std::endl; } qInstallMessageHandler( CalamaresLogHandler ); @@ -183,14 +184,13 @@ CLog::~CLog() log( m_msg.toUtf8().data(), m_debugLevel ); } -CDebug::~CDebug() -{ -} +CDebug::~CDebug() {} const char Continuation[] = "\n "; const char SubEntry[] = " .. "; -QString toString( const QVariant& v ) +QString +toString( const QVariant& v ) { auto t = v.type(); @@ -199,11 +199,15 @@ QString toString( const QVariant& v ) QStringList s; auto l = v.toList(); for ( auto lit = l.constBegin(); lit != l.constEnd(); ++lit ) + { s << lit->toString(); - return s.join(", "); + } + return s.join( ", " ); } else + { return v.toString(); + } } -} // namespace +} // namespace Logger diff --git a/src/libcalamares/utils/Logger.h b/src/libcalamares/utils/Logger.h index 4d1534e4b..643b3059b 100644 --- a/src/libcalamares/utils/Logger.h +++ b/src/libcalamares/utils/Logger.h @@ -27,169 +27,181 @@ namespace Logger { - DLLEXPORT extern const char Continuation[]; - DLLEXPORT extern const char SubEntry[]; +DLLEXPORT extern const char Continuation[]; +DLLEXPORT extern const char SubEntry[]; - enum +enum +{ + LOG_DISABLE = 0, + LOGERROR = 1, + LOGWARNING = 2, + LOGINFO = 3, + LOGEXTRA = 5, + LOGDEBUG = 6, + LOGVERBOSE = 8 +}; + +class DLLEXPORT CLog : public QDebug +{ +public: + explicit CLog( unsigned int debugLevel ); + virtual ~CLog(); + +private: + QString m_msg; + unsigned int m_debugLevel; +}; + +class DLLEXPORT CDebug : public CLog +{ +public: + CDebug( unsigned int debugLevel = LOGDEBUG ) + : CLog( debugLevel ) { - LOG_DISABLE = 0, - LOGERROR = 1, - LOGWARNING = 2, - LOGINFO = 3, - LOGEXTRA = 5, - LOGDEBUG = 6, - LOGVERBOSE = 8 - } ; - - class DLLEXPORT CLog : public QDebug - { - public: - explicit CLog( unsigned int debugLevel ); - virtual ~CLog(); - - private: - QString m_msg; - unsigned int m_debugLevel; - }; - - class DLLEXPORT CDebug : public CLog - { - public: - CDebug( unsigned int debugLevel = LOGDEBUG ) : CLog( debugLevel ) + if ( debugLevel <= LOGERROR ) { - if ( debugLevel <= LOGERROR ) - *this << "ERROR:"; - else if ( debugLevel <= LOGWARNING ) - *this << "WARNING:"; + *this << "ERROR:"; } - virtual ~CDebug(); - }; + else if ( debugLevel <= LOGWARNING ) + { + *this << "WARNING:"; + } + } + virtual ~CDebug(); +}; - /** - * @brief The full path of the log file. - */ - DLLEXPORT QString logFile(); +/** + * @brief The full path of the log file. + */ +DLLEXPORT QString logFile(); - /** - * @brief Start logging to the log file. - * - * Call this (once) to start logging to the log file (usually - * ~/.cache/calamares/session.log ). An existing log file is - * rolled over if it is too large. - */ - DLLEXPORT void setupLogfile(); +/** + * @brief Start logging to the log file. + * + * Call this (once) to start logging to the log file (usually + * ~/.cache/calamares/session.log ). An existing log file is + * rolled over if it is too large. + */ +DLLEXPORT void setupLogfile(); - /** - * @brief Set a log level for future logging. - * - * Pass in a value from the LOG* enum, above. Use 0 to - * disable logging. Values greater than LOGVERBOSE are - * limited to LOGVERBOSE, which will log everything. - * - * Practical values are 0, 1, 2, and 6. - */ - DLLEXPORT void setupLogLevel( unsigned int level ); +/** + * @brief Set a log level for future logging. + * + * Pass in a value from the LOG* enum, above. Use 0 to + * disable logging. Values greater than LOGVERBOSE are + * limited to LOGVERBOSE, which will log everything. + * + * Practical values are 0, 1, 2, and 6. + */ +DLLEXPORT void setupLogLevel( unsigned int level ); - /** @brief Return the configured log-level. */ - DLLEXPORT unsigned int logLevel(); +/** @brief Return the configured log-level. */ +DLLEXPORT unsigned int logLevel(); - /** @brief Would the given @p level really be logged? */ - DLLEXPORT bool logLevelEnabled( unsigned int level ); +/** @brief Would the given @p level really be logged? */ +DLLEXPORT bool logLevelEnabled( unsigned int level ); - /** - * @brief Row-oriented formatted logging. - * - * Use DebugRow to produce multiple rows of 2-column output - * in a debugging statement. For instance, - * cDebug() << DebugRow(1,12) - * << DebugRow(2,24) - * will produce a single timestamped debug line with continuations. - * Each DebugRow produces one line of output, with the two values. - */ - template - struct DebugRow +/** + * @brief Row-oriented formatted logging. + * + * Use DebugRow to produce multiple rows of 2-column output + * in a debugging statement. For instance, + * cDebug() << DebugRow(1,12) + * << DebugRow(2,24) + * will produce a single timestamped debug line with continuations. + * Each DebugRow produces one line of output, with the two values. + */ +template < typename T, typename U > +struct DebugRow +{ +public: + explicit DebugRow( const T& t, const U& u ) + : first( t ) + , second( u ) { - public: - explicit DebugRow(const T& t, const U& u) - : first(t) - , second(u) - {} - - const T& first; - const U& second; - } ; - - /** - * @brief List-oriented formatted logging. - * - * Use DebugList to produce multiple rows of output in a debugging - * statement. For instance, - * cDebug() << DebugList( QStringList() << "foo" << "bar" ) - * will produce a single timestamped debug line with continuations. - * Each element of the list of strings will be logged on a separate line. - */ - struct DebugList - { - explicit DebugList( const QStringList& l ) - : list(l) - {} - - const QStringList& list; - } ; - - /** - * @brief Map-oriented formatted logging. - * - * Use DebugMap to produce multiple rows of output in a debugging - * statement from a map. The output is intentionally a bit-yaml-ish. - * cDebug() << DebugMap( map ) - * will produce a single timestamped debug line with continuations. - * The continued lines will have a key (from the map) and a value - * on each line. - */ - struct DebugMap - { - public: - explicit DebugMap(const QVariantMap& m) - : map( m ) - {} - - const QVariantMap& map; - } ; - - /** @brief output operator for DebugRow */ - template - inline QDebug& - operator <<( QDebug& s, const DebugRow& t ) - { - s << Continuation << t.first << ':' << ' ' << t.second; - return s; } - /** @brief output operator for DebugList */ - inline QDebug& - operator <<( QDebug& s, const DebugList& c ) + const T& first; + const U& second; +}; + +/** + * @brief List-oriented formatted logging. + * + * Use DebugList to produce multiple rows of output in a debugging + * statement. For instance, + * cDebug() << DebugList( QStringList() << "foo" << "bar" ) + * will produce a single timestamped debug line with continuations. + * Each element of the list of strings will be logged on a separate line. + */ +struct DebugList +{ + explicit DebugList( const QStringList& l ) + : list( l ) { - for( const auto& i : c.list ) - s << Continuation << i; - return s; } - /** @brief supporting method for outputting a DebugMap */ - QString toString( const QVariant& v ); + const QStringList& list; +}; - /** @brief output operator for DebugMap */ - inline QDebug& - operator <<( QDebug& s, const DebugMap& t ) +/** + * @brief Map-oriented formatted logging. + * + * Use DebugMap to produce multiple rows of output in a debugging + * statement from a map. The output is intentionally a bit-yaml-ish. + * cDebug() << DebugMap( map ) + * will produce a single timestamped debug line with continuations. + * The continued lines will have a key (from the map) and a value + * on each line. + */ +struct DebugMap +{ +public: + explicit DebugMap( const QVariantMap& m ) + : map( m ) { - for ( auto it = t.map.constBegin(); it != t.map.constEnd(); ++it ) - s << Continuation << it.key().toUtf8().constData() << ':' << ' ' << toString( it.value() ).toUtf8().constData(); - return s; } -} // namespace + + const QVariantMap& map; +}; + +/** @brief output operator for DebugRow */ +template < typename T, typename U > +inline QDebug& +operator<<( QDebug& s, const DebugRow< T, U >& t ) +{ + s << Continuation << t.first << ':' << ' ' << t.second; + return s; +} + +/** @brief output operator for DebugList */ +inline QDebug& +operator<<( QDebug& s, const DebugList& c ) +{ + for ( const auto& i : c.list ) + { + s << Continuation << i; + } + return s; +} + +/** @brief supporting method for outputting a DebugMap */ +QString toString( const QVariant& v ); + +/** @brief output operator for DebugMap */ +inline QDebug& +operator<<( QDebug& s, const DebugMap& t ) +{ + for ( auto it = t.map.constBegin(); it != t.map.constEnd(); ++it ) + { + s << Continuation << it.key().toUtf8().constData() << ':' << ' ' << toString( it.value() ).toUtf8().constData(); + } + return s; +} +} // namespace Logger #define cDebug Logger::CDebug -#define cWarning() Logger::CDebug(Logger::LOGWARNING) -#define cError() Logger::CDebug(Logger::LOGERROR) +#define cWarning() Logger::CDebug( Logger::LOGWARNING ) +#define cError() Logger::CDebug( Logger::LOGERROR ) #endif diff --git a/src/libcalamares/utils/NamedEnum.h b/src/libcalamares/utils/NamedEnum.h index 5ff62f54c..76c8ed3bb 100644 --- a/src/libcalamares/utils/NamedEnum.h +++ b/src/libcalamares/utils/NamedEnum.h @@ -31,12 +31,12 @@ #include -#include -#include #include +#include +#include /** @brief Type for collecting parts of a named enum. */ -template +template < typename T > struct NamedEnumTable { using string_t = QString; @@ -53,7 +53,11 @@ struct NamedEnumTable * * static const NamedEnumTable c{ {"red", Colors::Red } }; */ - NamedEnumTable( const std::initializer_list< pair_t >& v ) : table( v ) { /* static_assert( v.size() > 0 ); */ } + NamedEnumTable( const std::initializer_list< pair_t >& v ) + : table( v ) + { + /* static_assert( v.size() > 0 ); */ + } /** @brief Find a name @p s in the table. * @@ -89,8 +93,8 @@ struct NamedEnumTable { ok = false; - for ( const auto &p : table ) - if ( s == p.second) + for ( const auto& p : table ) + if ( s == p.second ) { ok = true; return p.first; @@ -99,13 +103,14 @@ struct NamedEnumTable // ok is still false return string_t(); } -} ; +}; /** @brief Smashes an enum value to its underlying type. */ -template -constexpr typename std::underlying_type::type smash( const E e ) +template < typename E > +constexpr typename std::underlying_type< E >::type +smash( const E e ) { - return static_cast::type>( e ); + return static_cast< typename std::underlying_type< E >::type >( e ); } #endif diff --git a/src/libcalamares/utils/NamedSuffix.h b/src/libcalamares/utils/NamedSuffix.h index f58277698..e697c0640 100644 --- a/src/libcalamares/utils/NamedSuffix.h +++ b/src/libcalamares/utils/NamedSuffix.h @@ -42,7 +42,7 @@ #include "NamedEnum.h" /** @brief Template that takes the enum type to work with and a special none-enum. */ -template +template < typename T, T _none > class NamedSuffix { public: @@ -52,7 +52,7 @@ public: /** @brief Empty value. */ NamedSuffix() - : m_value(0) + : m_value( 0 ) , m_unit( none ) { } @@ -69,10 +69,10 @@ public: * This parses the given string @p s by comparing with the suffixes * in @p table and uses the first matching suffix as the unit. */ - NamedSuffix( const NamedEnumTable& table, const QString& s ) + NamedSuffix( const NamedEnumTable< T >& table, const QString& s ) : NamedSuffix() { - for( const auto& suffix : table.table ) + for ( const auto& suffix : table.table ) if ( s.endsWith( suffix.first ) ) { m_value = s.left( s.length() - suffix.first.length() ).toInt(); diff --git a/src/libcalamares/utils/PluginFactory_p.h b/src/libcalamares/utils/PluginFactory_p.h index 7a6db217e..dc272f077 100644 --- a/src/libcalamares/utils/PluginFactory_p.h +++ b/src/libcalamares/utils/PluginFactory_p.h @@ -32,23 +32,24 @@ namespace Calamares class PluginFactoryPrivate { - Q_DECLARE_PUBLIC(PluginFactory) + Q_DECLARE_PUBLIC( PluginFactory ) protected: - typedef QPair Plugin; + typedef QPair< const QMetaObject*, PluginFactory::CreateInstanceFunction > Plugin; PluginFactoryPrivate() : catalogInitialized( false ) , q_ptr( nullptr ) - {} + { + } ~PluginFactoryPrivate() {} - QHash createInstanceHash; + QHash< QString, Plugin > createInstanceHash; QString catalogName; bool catalogInitialized; - PluginFactory *q_ptr; + PluginFactory* q_ptr; }; -} // namespace +} // namespace Calamares #endif diff --git a/src/libcalamares/utils/Retranslator.cpp b/src/libcalamares/utils/Retranslator.cpp index 93560f4ae..e154350b9 100644 --- a/src/libcalamares/utils/Retranslator.cpp +++ b/src/libcalamares/utils/Retranslator.cpp @@ -26,27 +26,30 @@ #include -namespace CalamaresUtils { +namespace CalamaresUtils +{ static QTranslator* s_brandingTranslator = nullptr; static QTranslator* s_translator = nullptr; static QString s_translatorLocaleName; void -installTranslator( const QLocale& locale, - const QString& brandingTranslationsPrefix, - QObject* parent ) +installTranslator( const QLocale& locale, const QString& brandingTranslationsPrefix, QObject* parent ) { QString localeName = locale.name(); localeName.replace( "-", "_" ); if ( localeName == "C" ) + { localeName = "en"; + } // Special case of sr@latin // // See top-level CMakeLists.txt about special cases for translation loading. if ( locale.language() == QLocale::Language::Serbian && locale.script() == QLocale::Script::LatinScript ) + { localeName = QStringLiteral( "sr@latin" ); + } cDebug() << "Looking for translations for" << localeName; @@ -56,19 +59,14 @@ installTranslator( const QLocale& locale, if ( !brandingTranslationsPrefix.isEmpty() ) { QString brandingTranslationsDirPath( brandingTranslationsPrefix ); - brandingTranslationsDirPath.truncate( brandingTranslationsPrefix.lastIndexOf( - QDir::separator() ) ); + brandingTranslationsDirPath.truncate( brandingTranslationsPrefix.lastIndexOf( QDir::separator() ) ); QDir brandingTranslationsDir( brandingTranslationsDirPath ); if ( brandingTranslationsDir.exists() ) { QString filenameBase( brandingTranslationsPrefix ); - filenameBase.remove( 0, brandingTranslationsPrefix.lastIndexOf( - QDir::separator() ) + 1 ); + filenameBase.remove( 0, brandingTranslationsPrefix.lastIndexOf( QDir::separator() ) + 1 ); translator = new QTranslator( parent ); - if ( translator->load( locale, - filenameBase, - "_", - brandingTranslationsDir.absolutePath() ) ) + if ( translator->load( locale, filenameBase, "_", brandingTranslationsDir.absolutePath() ) ) { cDebug() << Logger::SubEntry << "Branding using locale:" << localeName; } @@ -121,19 +119,22 @@ translatorLocaleName() } void -Retranslator::attachRetranslator( QObject* parent, - std::function< void ( void ) > retranslateFunc ) +Retranslator::attachRetranslator( QObject* parent, std::function< void( void ) > retranslateFunc ) { Retranslator* r = nullptr; for ( QObject* child : parent->children() ) { r = qobject_cast< Retranslator* >( child ); if ( r ) + { break; + } } if ( !r ) + { r = new Retranslator( parent ); + } r->m_retranslateFuncList.append( retranslateFunc ); retranslateFunc(); @@ -155,7 +156,9 @@ Retranslator::eventFilter( QObject* obj, QEvent* e ) if ( e->type() == QEvent::LanguageChange ) { foreach ( std::function< void() > func, m_retranslateFuncList ) + { func(); + } } } // pass the event on to the base @@ -163,4 +166,4 @@ Retranslator::eventFilter( QObject* obj, QEvent* e ) } -} // namespace CalamaresUtils +} // namespace CalamaresUtils diff --git a/src/libcalamares/utils/Retranslator.h b/src/libcalamares/utils/Retranslator.h index e06630630..32e8dcf41 100644 --- a/src/libcalamares/utils/Retranslator.h +++ b/src/libcalamares/utils/Retranslator.h @@ -32,24 +32,21 @@ class QLocale; namespace CalamaresUtils { - /** - * @brief installTranslator changes the application language. - * @param locale the new locale. - * @param brandingTranslationsPrefix the branding path prefix, from Calamares::Branding. - * @param parent the parent QObject. - */ - DLLEXPORT void installTranslator( const QLocale& locale, - const QString& brandingTranslationsPrefix, - QObject* parent ); +/** + * @brief installTranslator changes the application language. + * @param locale the new locale. + * @param brandingTranslationsPrefix the branding path prefix, from Calamares::Branding. + * @param parent the parent QObject. + */ +DLLEXPORT void installTranslator( const QLocale& locale, const QString& brandingTranslationsPrefix, QObject* parent ); - DLLEXPORT QString translatorLocaleName(); +DLLEXPORT QString translatorLocaleName(); class Retranslator : public QObject { Q_OBJECT public: - static void attachRetranslator( QObject* parent, - std::function< void( void ) > retranslateFunc ); + static void attachRetranslator( QObject* parent, std::function< void( void ) > retranslateFunc ); void addRetranslateFunc( std::function< void( void ) > retranslateFunc ); @@ -63,11 +60,10 @@ private: }; -} // namespace +} // namespace CalamaresUtils -#define CALAMARES_RETRANSLATE(body) \ - CalamaresUtils::Retranslator::attachRetranslator( this, [=] { body } ); -#define CALAMARES_RETRANSLATE_WIDGET(widget,body) \ +#define CALAMARES_RETRANSLATE( body ) CalamaresUtils::Retranslator::attachRetranslator( this, [=] { body } ); +#define CALAMARES_RETRANSLATE_WIDGET( widget, body ) \ CalamaresUtils::Retranslator::attachRetranslator( widget, [=] { body } ); #endif diff --git a/src/libcalamares/utils/String.cpp b/src/libcalamares/utils/String.cpp index f577aee17..e39132328 100644 --- a/src/libcalamares/utils/String.cpp +++ b/src/libcalamares/utils/String.cpp @@ -74,7 +74,7 @@ removeDiacritics( const QString& string ) // *INDENT-ON* QString output; - for ( const QChar &c : string ) + for ( const QChar& c : string ) { int i = diacriticLetters.indexOf( c ); if ( i < 0 ) @@ -119,14 +119,14 @@ QString obscure( const QString& string ) { QString result; - const QChar *unicode = string.unicode(); + const QChar* unicode = string.unicode(); for ( int i = 0; i < string.length(); ++i ) - // yes, no typo. can't encode ' ' or '!' because - // they're the unicode BOM. stupid scrambling. stupid. - result += ( unicode[ i ].unicode() <= 0x21 ) ? - unicode[ i ] : - QChar( 0x1001F - unicode[ i ].unicode() ); + // yes, no typo. can't encode ' ' or '!' because + // they're the unicode BOM. stupid scrambling. stupid. + { + result += ( unicode[ i ].unicode() <= 0x21 ) ? unicode[ i ] : QChar( 0x1001F - unicode[ i ].unicode() ); + } return result; } -} +} // namespace CalamaresUtils diff --git a/src/libcalamares/utils/String.h b/src/libcalamares/utils/String.h index 0a69bcf83..cdf7d0b41 100644 --- a/src/libcalamares/utils/String.h +++ b/src/libcalamares/utils/String.h @@ -34,20 +34,20 @@ */ namespace CalamaresUtils { - /** - * @brief removeDiacritics replaces letters with diacritics and ligatures with - * alternative forms and digraphs. - * @param string the string to transform. - * @return the output string with plain characters. - */ - DLLEXPORT QString removeDiacritics( const QString& string ); +/** + * @brief removeDiacritics replaces letters with diacritics and ligatures with + * alternative forms and digraphs. + * @param string the string to transform. + * @return the output string with plain characters. + */ +DLLEXPORT QString removeDiacritics( const QString& string ); - /** - * @brief obscure is a bidirectional obfuscation function, from KStringHandler. - * @param string the input string. - * @return the obfuscated string. - */ - DLLEXPORT QString obscure( const QString& string ); -} // namespace +/** + * @brief obscure is a bidirectional obfuscation function, from KStringHandler. + * @param string the input string. + * @return the obfuscated string. + */ +DLLEXPORT QString obscure( const QString& string ); +} // namespace CalamaresUtils #endif diff --git a/src/libcalamares/utils/Units.h b/src/libcalamares/utils/Units.h index 8fb34c3e0..e1f30460a 100644 --- a/src/libcalamares/utils/Units.h +++ b/src/libcalamares/utils/Units.h @@ -26,76 +26,88 @@ namespace CalamaresUtils { /** User defined literals, 1_KiB is 1 KibiByte (= 2^10 bytes) */ -constexpr qint64 operator ""_KiB( unsigned long long m ) +constexpr qint64 operator""_KiB( unsigned long long m ) { - return qint64(m) * 1024; + return qint64( m ) * 1024; } /** User defined literals, 1_MiB is 1 MibiByte (= 2^20 bytes) */ -constexpr qint64 operator ""_MiB( unsigned long long m ) +constexpr qint64 operator""_MiB( unsigned long long m ) { - return operator ""_KiB(m) * 1024; + return operator""_KiB(m)*1024; } /** User defined literals, 1_GiB is 1 GibiByte (= 2^30 bytes) */ -constexpr qint64 operator ""_GiB( unsigned long long m ) +constexpr qint64 operator""_GiB( unsigned long long m ) { - return operator ""_MiB(m) * 1024; + return operator""_MiB(m)*1024; } -constexpr qint64 KiBtoBytes( unsigned long long m ) +constexpr qint64 +KiBtoBytes( unsigned long long m ) { - return operator ""_KiB( m ); + return operator""_KiB( m ); } -constexpr qint64 MiBtoBytes( unsigned long long m ) +constexpr qint64 +MiBtoBytes( unsigned long long m ) { - return operator ""_MiB( m ); + return operator""_MiB( m ); } -constexpr qint64 GiBtoBytes( unsigned long long m ) +constexpr qint64 +GiBtoBytes( unsigned long long m ) { - return operator ""_GiB( m ); + return operator""_GiB( m ); } -constexpr qint64 KiBtoBytes( double m ) +constexpr qint64 +KiBtoBytes( double m ) { - return qint64(m * 1024); + return qint64( m * 1024 ); } -constexpr qint64 MiBtoBytes( double m ) +constexpr qint64 +MiBtoBytes( double m ) { - return qint64(m * 1024 * 1024); + return qint64( m * 1024 * 1024 ); } -constexpr qint64 GiBtoBytes( double m ) +constexpr qint64 +GiBtoBytes( double m ) { - return qint64(m * 1024 * 1024 * 1024); + return qint64( m * 1024 * 1024 * 1024 ); } -constexpr int BytesToMiB( qint64 b ) +constexpr int +BytesToMiB( qint64 b ) { return int( b / 1024 / 1024 ); } -constexpr int BytesToGiB( qint64 b ) +constexpr int +BytesToGiB( qint64 b ) { return int( b / 1024 / 1024 / 1024 ); } -constexpr qint64 alignBytesToBlockSize( qint64 bytes, qint64 blocksize ) +constexpr qint64 +alignBytesToBlockSize( qint64 bytes, qint64 blocksize ) { qint64 blocks = bytes / blocksize; if ( blocks * blocksize != bytes ) + { ++blocks; + } return blocks * blocksize; } -constexpr qint64 bytesToSectors( qint64 bytes, qint64 blocksize ) +constexpr qint64 +bytesToSectors( qint64 bytes, qint64 blocksize ) { - return alignBytesToBlockSize( alignBytesToBlockSize( bytes, blocksize), MiBtoBytes(1ULL) ) / blocksize; + return alignBytesToBlockSize( alignBytesToBlockSize( bytes, blocksize ), MiBtoBytes( 1ULL ) ) / blocksize; } -} // namespace +} // namespace CalamaresUtils #endif diff --git a/src/libcalamares/utils/Variant.cpp b/src/libcalamares/utils/Variant.cpp index f11853916..2e7a13eed 100644 --- a/src/libcalamares/utils/Variant.cpp +++ b/src/libcalamares/utils/Variant.cpp @@ -39,20 +39,24 @@ getBool( const QVariantMap& map, const QString& key, bool d ) { auto v = map.value( key ); if ( v.type() == QVariant::Bool ) + { result = v.toBool(); + } } return result; } QString -getString(const QVariantMap& map, const QString& key) +getString( const QVariantMap& map, const QString& key ) { if ( map.contains( key ) ) { auto v = map.value( key ); if ( v.type() == QVariant::String ) + { return v.toString(); + } } return QString(); } @@ -65,7 +69,9 @@ getInteger( const QVariantMap& map, const QString& key, int d ) { auto v = map.value( key ); if ( v.type() == QVariant::Int ) + { result = v.toInt(); + } } return result; @@ -79,9 +85,13 @@ getDouble( const QVariantMap& map, const QString& key, double d ) { auto v = map.value( key ); if ( v.type() == QVariant::Int ) + { result = v.toInt(); + } else if ( v.type() == QVariant::Double ) + { result = v.toDouble(); + } } return result; @@ -104,4 +114,4 @@ getSubMap( const QVariantMap& map, const QString& key, bool& success ) return QVariantMap(); } -} +} // namespace CalamaresUtils diff --git a/src/libcalamares/utils/Variant.h b/src/libcalamares/utils/Variant.h index e60eccb4e..c68c2a801 100644 --- a/src/libcalamares/utils/Variant.h +++ b/src/libcalamares/utils/Variant.h @@ -27,36 +27,36 @@ namespace CalamaresUtils { - /** - * Get a bool value from a mapping with a given key; returns the default - * if no value is stored in the map. - */ - DLLEXPORT bool getBool( const QVariantMap& map, const QString& key, bool d ); +/** + * Get a bool value from a mapping with a given key; returns the default + * if no value is stored in the map. + */ +DLLEXPORT bool getBool( const QVariantMap& map, const QString& key, bool d ); - /** - * Get a string value from a mapping; returns empty QString if no value. - */ - DLLEXPORT QString getString( const QVariantMap& map, const QString& key ); +/** + * Get a string value from a mapping; returns empty QString if no value. + */ +DLLEXPORT QString getString( const QVariantMap& map, const QString& key ); - /** - * Get an integer value from a mapping; returns @p d if no value. - */ - DLLEXPORT int getInteger( const QVariantMap& map, const QString& key, int d ); +/** + * Get an integer value from a mapping; returns @p d if no value. + */ +DLLEXPORT int getInteger( const QVariantMap& map, const QString& key, int d ); - /** - * Get a double value from a mapping (integers are converted); returns @p d if no value. - */ - DLLEXPORT double getDouble( const QVariantMap& map, const QString& key, double d ); +/** + * Get a double value from a mapping (integers are converted); returns @p d if no value. + */ +DLLEXPORT double getDouble( const QVariantMap& map, const QString& key, double d ); - /** - * Returns a sub-map (i.e. a nested map) from the given mapping with the - * given key. @p success is set to true if the @p key exists - * in @p map and converts to a map, false otherwise. - * - * Returns an empty map if there is no such key or it is not a map-value. - * (e.g. if @p success is false). - */ - DLLEXPORT QVariantMap getSubMap( const QVariantMap& map, const QString& key, bool& success ); -} // namespace +/** + * Returns a sub-map (i.e. a nested map) from the given mapping with the + * given key. @p success is set to true if the @p key exists + * in @p map and converts to a map, false otherwise. + * + * Returns an empty map if there is no such key or it is not a map-value. + * (e.g. if @p success is false). + */ +DLLEXPORT QVariantMap getSubMap( const QVariantMap& map, const QString& key, bool& success ); +} // namespace CalamaresUtils #endif diff --git a/src/libcalamares/utils/Yaml.cpp b/src/libcalamares/utils/Yaml.cpp index aa7ef6c2e..cad6ac1fe 100644 --- a/src/libcalamares/utils/Yaml.cpp +++ b/src/libcalamares/utils/Yaml.cpp @@ -70,13 +70,21 @@ yamlScalarToVariant( const YAML::Node& scalarNode ) std::string stdScalar = scalarNode.as< std::string >(); QString scalarString = QString::fromStdString( stdScalar ); if ( _yamlScalarTrueValues.exactMatch( scalarString ) ) + { return QVariant( true ); + } if ( _yamlScalarFalseValues.exactMatch( scalarString ) ) + { return QVariant( false ); + } if ( QRegExp( "[-+]?\\d+" ).exactMatch( scalarString ) ) + { return QVariant( scalarString.toInt() ); + } if ( QRegExp( "[-+]?\\d*\\.?\\d+" ).exactMatch( scalarString ) ) + { return QVariant( scalarString.toDouble() ); + } return QVariant( scalarString ); } @@ -85,8 +93,7 @@ QVariant yamlSequenceToVariant( const YAML::Node& sequenceNode ) { QVariantList vl; - for ( YAML::const_iterator it = sequenceNode.begin(); - it != sequenceNode.end(); ++it ) + for ( YAML::const_iterator it = sequenceNode.begin(); it != sequenceNode.end(); ++it ) { vl << yamlToVariant( *it ); } @@ -98,17 +105,15 @@ QVariant yamlMapToVariant( const YAML::Node& mapNode ) { QVariantMap vm; - for ( YAML::const_iterator it = mapNode.begin(); - it != mapNode.end(); ++it ) + for ( YAML::const_iterator it = mapNode.begin(); it != mapNode.end(); ++it ) { - vm.insert( QString::fromStdString( it->first.as< std::string >() ), - yamlToVariant( it->second ) ); + vm.insert( QString::fromStdString( it->first.as< std::string >() ), yamlToVariant( it->second ) ); } return vm; } QStringList -yamlToStringList(const YAML::Node& listNode) +yamlToStringList( const YAML::Node& listNode ) { QStringList l; listNode >> l; @@ -117,7 +122,7 @@ yamlToStringList(const YAML::Node& listNode) void -explainYamlException( const YAML::Exception& e, const QByteArray& yamlData, const char *label ) +explainYamlException( const YAML::Exception& e, const QByteArray& yamlData, const char* label ) { cWarning() << "YAML error " << e.what() << "in" << label << '.'; explainYamlException( e, yamlData ); @@ -142,7 +147,9 @@ explainYamlException( const YAML::Exception& e, const QByteArray& yamlData ) linestart = yamlData.indexOf( '\n', linestart ); // No more \ns found, weird if ( linestart < 0 ) + { break; + } linestart += 1; // Skip that \n } int lineend = linestart; @@ -150,34 +157,43 @@ explainYamlException( const YAML::Exception& e, const QByteArray& yamlData ) { lineend = yamlData.indexOf( '\n', linestart ); if ( lineend < 0 ) + { lineend = yamlData.length(); + } } int rangestart = linestart; int rangeend = lineend; // Adjust range (linestart..lineend) so it's not too long if ( ( linestart >= 0 ) && ( e.mark.column > 30 ) ) + { rangestart += ( e.mark.column - 30 ); + } if ( ( linestart >= 0 ) && ( rangeend - rangestart > 40 ) ) + { rangeend = rangestart + 40; + } if ( linestart >= 0 ) - cWarning() << "offending YAML data:" << yamlData.mid( rangestart, rangeend-rangestart ).constData(); - + { + cWarning() << "offending YAML data:" << yamlData.mid( rangestart, rangeend - rangestart ).constData(); + } } } QVariantMap -loadYaml(const QFileInfo& fi, bool* ok) +loadYaml( const QFileInfo& fi, bool* ok ) { return loadYaml( fi.absoluteFilePath(), ok ); } QVariantMap -loadYaml(const QString& filename, bool* ok) +loadYaml( const QString& filename, bool* ok ) { if ( ok ) + { *ok = false; + } QFile yamlFile( filename ); QVariant yamlContents; @@ -197,12 +213,12 @@ loadYaml(const QString& filename, bool* ok) } - if ( yamlContents.isValid() && - !yamlContents.isNull() && - yamlContents.type() == QVariant::Map ) + if ( yamlContents.isValid() && !yamlContents.isNull() && yamlContents.type() == QVariant::Map ) { if ( ok ) + { *ok = true; + } return yamlContents.toMap(); } @@ -214,7 +230,9 @@ static void writeIndent( QFile& f, int indent ) { while ( indent-- > 0 ) + { f.write( " " ); + } } // forward declaration @@ -229,7 +247,9 @@ static void dumpYamlElement( QFile& f, const QVariant& value, int indent ) { if ( value.type() == QVariant::Type::Bool ) + { f.write( value.toBool() ? "true" : "false" ); + } else if ( value.type() == QVariant::Type::String ) { f.write( quote ); @@ -251,17 +271,19 @@ dumpYamlElement( QFile& f, const QVariant& value, int indent ) { ++c; f.write( newline ); - writeIndent( f, indent+1 ); + writeIndent( f, indent + 1 ); f.write( "- " ); - dumpYamlElement( f, it, indent+1 ); + dumpYamlElement( f, it, indent + 1 ); } if ( !c ) // i.e. list was empty + { f.write( "[]" ); + } } else if ( value.type() == QVariant::Type::Map ) { f.write( newline ); - dumpYaml( f, value.toMap(), indent+1 ); + dumpYaml( f, value.toMap(), indent + 1 ); } else { @@ -293,12 +315,13 @@ saveYaml( const QString& filename, const QVariantMap& map ) { QFile f( filename ); if ( !f.open( QFile::WriteOnly ) ) + { return false; + } f.write( "# YAML dump\n---\n" ); return dumpYaml( f, map, 0 ); } - -} // namespace +} // namespace CalamaresUtils diff --git a/src/libcalamares/utils/Yaml.h b/src/libcalamares/utils/Yaml.h index 8755be336..6b786aef8 100644 --- a/src/libcalamares/utils/Yaml.h +++ b/src/libcalamares/utils/Yaml.h @@ -73,10 +73,10 @@ bool saveYaml( const QString& filename, const QVariantMap& map ); * what is going on in terms of the data passed to the parser. * Uses @p label when labeling the data source (e.g. "netinstall data") */ -void explainYamlException( const YAML::Exception& e, const QByteArray& data, const char *label ); +void explainYamlException( const YAML::Exception& e, const QByteArray& data, const char* label ); void explainYamlException( const YAML::Exception& e, const QByteArray& data, const QString& label ); void explainYamlException( const YAML::Exception& e, const QByteArray& data ); -} // namespace +} // namespace CalamaresUtils #endif From 312865cdd91048ca8c7a2833c1a524a9af984ed5 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 4 Aug 2019 22:09:53 +0200 Subject: [PATCH 090/302] [libcalamares] Fix build on FreeBSD --- src/libcalamares/utils/CalamaresUtilsSystem.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.cpp b/src/libcalamares/utils/CalamaresUtilsSystem.cpp index 6221c1f15..00b879224 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.cpp +++ b/src/libcalamares/utils/CalamaresUtilsSystem.cpp @@ -34,8 +34,11 @@ #endif #ifdef Q_OS_FREEBSD -#include +// clang-format off +// these includes need to stay in-order (that's a FreeBSD thing) #include +#include +// clang-format on #endif /** @brief When logging commands, don't log everything. From fa2b94d931a366b5fd2261751d166e43c968a28e Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 4 Aug 2019 22:13:58 +0200 Subject: [PATCH 091/302] [libcalamares] Apply current coding style to libcalamares/partition/ --- src/libcalamares/partition/PartitionSize.cpp | 71 +++++++++++---- src/libcalamares/partition/PartitionSize.h | 38 ++++---- src/libcalamares/partition/Tests.cpp | 96 ++++++++++---------- src/libcalamares/partition/Tests.h | 4 +- 4 files changed, 120 insertions(+), 89 deletions(-) diff --git a/src/libcalamares/partition/PartitionSize.cpp b/src/libcalamares/partition/PartitionSize.cpp index ee3d4c80b..3f4463f3c 100644 --- a/src/libcalamares/partition/PartitionSize.cpp +++ b/src/libcalamares/partition/PartitionSize.cpp @@ -26,16 +26,13 @@ namespace CalamaresUtils namespace Partition { -static const NamedEnumTable& +static const NamedEnumTable< SizeUnit >& unitSuffixes() { - static const NamedEnumTable names{ - { QStringLiteral( "%" ), SizeUnit::Percent }, - { QStringLiteral( "K" ), SizeUnit::KiB }, - { QStringLiteral( "KiB" ), SizeUnit::KiB }, - { QStringLiteral( "M" ), SizeUnit::MiB }, - { QStringLiteral( "MiB" ), SizeUnit::MiB }, - { QStringLiteral( "G" ), SizeUnit::GiB }, + static const NamedEnumTable< SizeUnit > names { + { QStringLiteral( "%" ), SizeUnit::Percent }, { QStringLiteral( "K" ), SizeUnit::KiB }, + { QStringLiteral( "KiB" ), SizeUnit::KiB }, { QStringLiteral( "M" ), SizeUnit::MiB }, + { QStringLiteral( "MiB" ), SizeUnit::MiB }, { QStringLiteral( "G" ), SizeUnit::GiB }, { QStringLiteral( "GiB" ), SizeUnit::GiB } }; @@ -55,7 +52,9 @@ PartitionSize::PartitionSize( const QString& s ) { m_value = s.toInt(); if ( m_value > 0 ) + { m_unit = SizeUnit::Byte; + } } if ( m_value <= 0 ) @@ -69,9 +68,13 @@ qint64 PartitionSize::toSectors( qint64 totalSectors, qint64 sectorSize ) const { if ( !isValid() ) + { return -1; + } if ( totalSectors < 1 || sectorSize < 1 ) + { return -1; + } switch ( m_unit ) { @@ -79,14 +82,18 @@ PartitionSize::toSectors( qint64 totalSectors, qint64 sectorSize ) const return -1; case SizeUnit::Percent: if ( value() == 100 ) + { return totalSectors; // Common-case, avoid futzing around + } else + { return totalSectors * value() / 100; + } case SizeUnit::Byte: case SizeUnit::KiB: case SizeUnit::MiB: case SizeUnit::GiB: - return CalamaresUtils::bytesToSectors ( toBytes(), sectorSize ); + return CalamaresUtils::bytesToSectors( toBytes(), sectorSize ); } return -1; @@ -96,7 +103,9 @@ qint64 PartitionSize::toBytes( qint64 totalSectors, qint64 sectorSize ) const { if ( !isValid() ) + { return -1; + } switch ( m_unit ) { @@ -104,11 +113,17 @@ PartitionSize::toBytes( qint64 totalSectors, qint64 sectorSize ) const return -1; case SizeUnit::Percent: if ( totalSectors < 1 || sectorSize < 1 ) + { return -1; + } if ( value() == 100 ) + { return totalSectors * sectorSize; // Common-case, avoid futzing around + } else + { return totalSectors * value() / 100; + } case SizeUnit::Byte: case SizeUnit::KiB: case SizeUnit::MiB: @@ -124,7 +139,9 @@ qint64 PartitionSize::toBytes( qint64 totalBytes ) const { if ( !isValid() ) + { return -1; + } switch ( m_unit ) { @@ -132,11 +149,17 @@ PartitionSize::toBytes( qint64 totalBytes ) const return -1; case SizeUnit::Percent: if ( totalBytes < 1 ) + { return -1; + } if ( value() == 100 ) + { return totalBytes; // Common-case, avoid futzing around + } else + { return totalBytes * value() / 100; + } case SizeUnit::Byte: case SizeUnit::KiB: case SizeUnit::MiB: @@ -152,7 +175,9 @@ qint64 PartitionSize::toBytes() const { if ( !isValid() ) + { return -1; + } switch ( m_unit ) { @@ -162,20 +187,22 @@ PartitionSize::toBytes() const case SizeUnit::Byte: return value(); case SizeUnit::KiB: - return CalamaresUtils::KiBtoBytes( static_cast( value() ) ); + return CalamaresUtils::KiBtoBytes( static_cast< unsigned long long >( value() ) ); case SizeUnit::MiB: - return CalamaresUtils::MiBtoBytes( static_cast( value() ) ); + return CalamaresUtils::MiBtoBytes( static_cast< unsigned long long >( value() ) ); case SizeUnit::GiB: - return CalamaresUtils::GiBtoBytes( static_cast( value() ) ); + return CalamaresUtils::GiBtoBytes( static_cast< unsigned long long >( value() ) ); } NOTREACHED return -1; } bool -PartitionSize::operator< ( const PartitionSize& other ) const +PartitionSize::operator<( const PartitionSize& other ) const { if ( !unitsComparable( m_unit, other.m_unit ) ) + { return false; + } switch ( m_unit ) { @@ -187,16 +214,18 @@ PartitionSize::operator< ( const PartitionSize& other ) const case SizeUnit::KiB: case SizeUnit::MiB: case SizeUnit::GiB: - return ( toBytes() < other.toBytes () ); + return ( toBytes() < other.toBytes() ); } NOTREACHED return false; } bool -PartitionSize::operator> ( const PartitionSize& other ) const +PartitionSize::operator>( const PartitionSize& other ) const { if ( !unitsComparable( m_unit, other.m_unit ) ) + { return false; + } switch ( m_unit ) { @@ -208,16 +237,18 @@ PartitionSize::operator> ( const PartitionSize& other ) const case SizeUnit::KiB: case SizeUnit::MiB: case SizeUnit::GiB: - return ( toBytes() > other.toBytes () ); + return ( toBytes() > other.toBytes() ); } NOTREACHED return false; } bool -PartitionSize::operator== ( const PartitionSize& other ) const +PartitionSize::operator==( const PartitionSize& other ) const { if ( !unitsComparable( m_unit, other.m_unit ) ) + { return false; + } switch ( m_unit ) { @@ -229,10 +260,10 @@ PartitionSize::operator== ( const PartitionSize& other ) const case SizeUnit::KiB: case SizeUnit::MiB: case SizeUnit::GiB: - return ( toBytes() == other.toBytes () ); + return ( toBytes() == other.toBytes() ); } NOTREACHED return false; } -} -} // namespace +} // namespace Partition +} // namespace CalamaresUtils diff --git a/src/libcalamares/partition/PartitionSize.h b/src/libcalamares/partition/PartitionSize.h index d8d5593a6..44cedbffe 100644 --- a/src/libcalamares/partition/PartitionSize.h +++ b/src/libcalamares/partition/PartitionSize.h @@ -20,8 +20,8 @@ #ifndef PARTITION_PARTITIONSIZE_H #define PARTITION_PARTITIONSIZE_H -#include "utils/Units.h" #include "utils/NamedSuffix.h" +#include "utils/Units.h" // Qt #include @@ -47,21 +47,24 @@ enum class SizeUnit * the available drive space are on). This class handles parsing * of such strings from the config file. */ -class PartitionSize : public NamedSuffix +class PartitionSize : public NamedSuffix< SizeUnit, SizeUnit::None > { public: - PartitionSize() : NamedSuffix() { } - PartitionSize( int v, SizeUnit u ) : NamedSuffix( v, u ) { } + PartitionSize() + : NamedSuffix() + { + } + PartitionSize( int v, SizeUnit u ) + : NamedSuffix( v, u ) + { + } PartitionSize( const QString& ); - bool isValid() const - { - return ( unit() != SizeUnit::None ) && ( value() > 0 ); - } + bool isValid() const { return ( unit() != SizeUnit::None ) && ( value() > 0 ); } - bool operator< ( const PartitionSize& other ) const; - bool operator> ( const PartitionSize& other ) const; - bool operator== ( const PartitionSize& other ) const; + bool operator<( const PartitionSize& other ) const; + bool operator>( const PartitionSize& other ) const; + bool operator==( const PartitionSize& other ) const; /** @brief Convert the size to the number of sectors @p totalSectors . * @@ -109,14 +112,13 @@ public: */ static constexpr bool unitsComparable( const SizeUnit u1, const SizeUnit u2 ) { - return !( ( u1 == SizeUnit::None || u2 == SizeUnit::None ) || - ( u1 == SizeUnit::Percent && u2 != SizeUnit::Percent ) || - ( u1 != SizeUnit::Percent && u2 == SizeUnit::Percent ) ); + return !( ( u1 == SizeUnit::None || u2 == SizeUnit::None ) + || ( u1 == SizeUnit::Percent && u2 != SizeUnit::Percent ) + || ( u1 != SizeUnit::Percent && u2 == SizeUnit::Percent ) ); } - }; -} -} // namespace +} // namespace Partition +} // namespace CalamaresUtils -#endif // PARTITION_PARTITIONSIZE_H +#endif // PARTITION_PARTITIONSIZE_H diff --git a/src/libcalamares/partition/Tests.cpp b/src/libcalamares/partition/Tests.cpp index c0eb5206a..0800fa455 100644 --- a/src/libcalamares/partition/Tests.cpp +++ b/src/libcalamares/partition/Tests.cpp @@ -31,13 +31,9 @@ Q_DECLARE_METATYPE( SizeUnit ) QTEST_GUILESS_MAIN( PartitionSizeTests ) -PartitionSizeTests::PartitionSizeTests() -{ -} +PartitionSizeTests::PartitionSizeTests() {} -PartitionSizeTests::~PartitionSizeTests() -{ -} +PartitionSizeTests::~PartitionSizeTests() {} void PartitionSizeTests::initTestCase() @@ -47,36 +43,38 @@ PartitionSizeTests::initTestCase() void PartitionSizeTests::testUnitComparison_data() { - QTest::addColumn("u1"); - QTest::addColumn("u2"); - QTest::addColumn("comparable"); + QTest::addColumn< SizeUnit >( "u1" ); + QTest::addColumn< SizeUnit >( "u2" ); + QTest::addColumn< bool >( "comparable" ); - QTest::newRow("nones") << SizeUnit::None << SizeUnit::None << false; - QTest::newRow("none+%") << SizeUnit::None << SizeUnit::Percent<< false; - QTest::newRow("%+none") << SizeUnit::Percent << SizeUnit::None << false; - QTest::newRow("KiB+none") << SizeUnit::KiB << SizeUnit::None << false; - QTest::newRow("none+MiB") << SizeUnit::None << SizeUnit::MiB << false; + QTest::newRow( "nones" ) << SizeUnit::None << SizeUnit::None << false; + QTest::newRow( "none+%" ) << SizeUnit::None << SizeUnit::Percent << false; + QTest::newRow( "%+none" ) << SizeUnit::Percent << SizeUnit::None << false; + QTest::newRow( "KiB+none" ) << SizeUnit::KiB << SizeUnit::None << false; + QTest::newRow( "none+MiB" ) << SizeUnit::None << SizeUnit::MiB << false; - QTest::newRow("KiB+KiB") << SizeUnit::KiB << SizeUnit::KiB << true; - QTest::newRow("KiB+MiB") << SizeUnit::KiB << SizeUnit::MiB << true; - QTest::newRow("KiB+GiB") << SizeUnit::KiB << SizeUnit::GiB << true; - QTest::newRow("MiB+MiB") << SizeUnit::MiB << SizeUnit::MiB << true; - QTest::newRow("MiB+GiB") << SizeUnit::MiB << SizeUnit::GiB << true; - QTest::newRow("GiB+GiB") << SizeUnit::GiB << SizeUnit::GiB << true; + QTest::newRow( "KiB+KiB" ) << SizeUnit::KiB << SizeUnit::KiB << true; + QTest::newRow( "KiB+MiB" ) << SizeUnit::KiB << SizeUnit::MiB << true; + QTest::newRow( "KiB+GiB" ) << SizeUnit::KiB << SizeUnit::GiB << true; + QTest::newRow( "MiB+MiB" ) << SizeUnit::MiB << SizeUnit::MiB << true; + QTest::newRow( "MiB+GiB" ) << SizeUnit::MiB << SizeUnit::GiB << true; + QTest::newRow( "GiB+GiB" ) << SizeUnit::GiB << SizeUnit::GiB << true; - QTest::newRow("%+None") << SizeUnit::Percent << SizeUnit::None << false; - QTest::newRow("%+%") << SizeUnit::Percent << SizeUnit::Percent << true; - QTest::newRow("%+KiB") << SizeUnit::Percent << SizeUnit::KiB << false; + QTest::newRow( "%+None" ) << SizeUnit::Percent << SizeUnit::None << false; + QTest::newRow( "%+%" ) << SizeUnit::Percent << SizeUnit::Percent << true; + QTest::newRow( "%+KiB" ) << SizeUnit::Percent << SizeUnit::KiB << false; } static bool original_compare( SizeUnit m_unit, SizeUnit other_m_unit ) { - if ( ( m_unit == SizeUnit::None || other_m_unit == SizeUnit::None ) || - ( m_unit == SizeUnit::Percent && other_m_unit != SizeUnit::Percent ) || - ( m_unit != SizeUnit::Percent && other_m_unit == SizeUnit::Percent ) ) + if ( ( m_unit == SizeUnit::None || other_m_unit == SizeUnit::None ) + || ( m_unit == SizeUnit::Percent && other_m_unit != SizeUnit::Percent ) + || ( m_unit != SizeUnit::Percent && other_m_unit == SizeUnit::Percent ) ) + { return false; + } return true; } @@ -104,33 +102,33 @@ PartitionSizeTests::testUnitComparison() void PartitionSizeTests::testUnitNormalisation_data() { - QTest::addColumn("u1"); - QTest::addColumn("v"); - QTest::addColumn("bytes"); + QTest::addColumn< SizeUnit >( "u1" ); + QTest::addColumn< int >( "v" ); + QTest::addColumn< long >( "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 << -1L; + QTest::newRow( "none" ) << SizeUnit::None << 0 << -1L; + QTest::newRow( "none" ) << SizeUnit::None << -2 << -1L; - 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 << -1L; + QTest::newRow( "percent" ) << SizeUnit::Percent << 16 << -1L; + QTest::newRow( "percent" ) << SizeUnit::Percent << -2 << -1L; - 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 << -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("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 << -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("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 << -1L; + QTest::newRow( "GiB" ) << SizeUnit::GiB << 1 << 1024 * 1024 * 1024L; + QTest::newRow( "GiB" ) << SizeUnit::GiB << 2 << 2048 * 1024 * 1024L; } void @@ -140,5 +138,5 @@ PartitionSizeTests::testUnitNormalisation() QFETCH( int, v ); QFETCH( long, bytes ); - QCOMPARE( PartitionSize( v, u1 ).toBytes(), static_cast( bytes ) ); + QCOMPARE( PartitionSize( v, u1 ).toBytes(), static_cast< qint64 >( bytes ) ); } diff --git a/src/libcalamares/partition/Tests.h b/src/libcalamares/partition/Tests.h index 24398233d..799f50c04 100644 --- a/src/libcalamares/partition/Tests.h +++ b/src/libcalamares/partition/Tests.h @@ -30,10 +30,10 @@ public: private Q_SLOTS: void initTestCase(); - + void testUnitComparison_data(); void testUnitComparison(); - + void testUnitNormalisation_data(); void testUnitNormalisation(); }; From 43ba59361bcea73f91cd744fa00384514055c9cd Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 4 Aug 2019 22:16:33 +0200 Subject: [PATCH 092/302] [libcalamares] Don't format generated files of CLDR data --- src/libcalamares/locale/CountryData_p.cpp | 6 ++++-- src/libcalamares/locale/cldr-extractor.py | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/libcalamares/locale/CountryData_p.cpp b/src/libcalamares/locale/CountryData_p.cpp index a6e9b3a95..f4736fa2e 100644 --- a/src/libcalamares/locale/CountryData_p.cpp +++ b/src/libcalamares/locale/CountryData_p.cpp @@ -10,12 +10,14 @@ * Unicode Data Files ("DATA FILES") include all data files under the directories: * https://www.unicode.org/Public/ * C. Terms of Use -* 2. Any person is hereby authorized, without fee, to view, use, reproduce, -* and distribute all documents and files, subject to the Terms and +* 2. Any person is hereby authorized, without fee, to view, use, reproduce, +* and distribute all documents and files, subject to the Terms and * Conditions herein. */ // BEGIN Generated from CLDR data +// *INDENT-OFF* +// clang-format off struct CountryData diff --git a/src/libcalamares/locale/cldr-extractor.py b/src/libcalamares/locale/cldr-extractor.py index 4e279337b..aae71ed1d 100644 --- a/src/libcalamares/locale/cldr-extractor.py +++ b/src/libcalamares/locale/cldr-extractor.py @@ -225,12 +225,14 @@ cpp_header_comment = """/* GENERATED FILE DO NOT EDIT * Unicode Data Files ("DATA FILES") include all data files under the directories: * https://www.unicode.org/Public/ * C. Terms of Use -* 2. Any person is hereby authorized, without fee, to view, use, reproduce, -* and distribute all documents and files, subject to the Terms and +* 2. Any person is hereby authorized, without fee, to view, use, reproduce, +* and distribute all documents and files, subject to the Terms and * Conditions herein. */ // BEGIN Generated from CLDR data +// *INDENT-OFF* +// clang-format off """ From 7fcb7be1e4aead26b1f50e319242230d5b36fd19 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 4 Aug 2019 22:17:12 +0200 Subject: [PATCH 093/302] [libcalamares] Apply current coding style to libcalamares/locale/ --- src/libcalamares/locale/Label.cpp | 20 +++++++--- src/libcalamares/locale/Label.h | 54 ++++++++------------------ src/libcalamares/locale/LabelModel.cpp | 53 ++++++++++++++----------- src/libcalamares/locale/LabelModel.h | 12 +++--- src/libcalamares/locale/Lookup.cpp | 49 ++++++++++++++--------- src/libcalamares/locale/Lookup.h | 44 ++++++++++----------- src/libcalamares/locale/Tests.cpp | 8 +--- 7 files changed, 122 insertions(+), 118 deletions(-) diff --git a/src/libcalamares/locale/Label.cpp b/src/libcalamares/locale/Label.cpp index 8d3cd443f..58c19101d 100644 --- a/src/libcalamares/locale/Label.cpp +++ b/src/libcalamares/locale/Label.cpp @@ -50,18 +50,24 @@ Label::setLabels( const QString& locale, LabelFormat format ) QString countryName; if ( languageName.isEmpty() ) + { languageName = QString( "* %1 (%2)" ).arg( locale, englishName ); + } - bool needsCountryName = ( format == LabelFormat::AlwaysWithCountry ) || - (locale.contains( '_' ) && QLocale::countriesForLanguage( m_locale.language() ).count() > 1 ); + bool needsCountryName = ( format == LabelFormat::AlwaysWithCountry ) + || ( locale.contains( '_' ) && QLocale::countriesForLanguage( m_locale.language() ).count() > 1 ); if ( needsCountryName ) + { countryName = m_locale.nativeCountryName(); + } m_label = needsCountryName ? longFormat.arg( languageName, countryName ) : languageName; - m_englishLabel = needsCountryName ? longFormat.arg( englishName, QLocale::countryToString( m_locale.country() ) ) : englishName; + m_englishLabel = needsCountryName ? longFormat.arg( englishName, QLocale::countryToString( m_locale.country() ) ) + : englishName; } -QLocale Label::getLocale( const QString& localeName ) +QLocale +Label::getLocale( const QString& localeName ) { if ( localeName.contains( "@latin" ) ) { @@ -69,8 +75,10 @@ QLocale Label::getLocale( const QString& localeName ) return QLocale( loc.language(), QLocale::Script::LatinScript, loc.country() ); } else + { return QLocale( localeName ); + } } -} -} // namespace +} // namespace Locale +} // namespace CalamaresUtils diff --git a/src/libcalamares/locale/Label.h b/src/libcalamares/locale/Label.h index 7935b0880..ab3e80ad0 100644 --- a/src/libcalamares/locale/Label.h +++ b/src/libcalamares/locale/Label.h @@ -23,7 +23,7 @@ #include #include -namespace CalamaresUtils +namespace CalamaresUtils { namespace Locale { @@ -39,7 +39,11 @@ class Label { public: /** @brief Formatting option for label -- add (country) to label. */ - enum class LabelFormat { AlwaysWithCountry, IfNeededWithCountry } ; + enum class LabelFormat + { + AlwaysWithCountry, + IfNeededWithCountry + }; /** @brief Empty locale. This uses the system-default locale. */ Label(); @@ -56,54 +60,30 @@ public: * * English (@see isEnglish() -- it means en_US) is sorted at the top. */ - bool operator <( const Label& other ) const - { - return m_localeId < other.m_localeId; - } + bool operator<( const Label& other ) const { return m_localeId < other.m_localeId; } /** @brief Is this locale English? * * en_US and en (American English) is defined as English. The Queen's * English -- proper English -- is relegated to non-English status. */ - bool isEnglish() const - { - return m_localeId == QLatin1Literal( "en_US" ) || m_localeId == QLatin1Literal( "en" ); - } + bool isEnglish() const { return m_localeId == QLatin1Literal( "en_US" ) || m_localeId == QLatin1Literal( "en" ); } /** @brief Get the human-readable name for this locale. */ - QString label() const - { - return m_label; - } + QString label() const { return m_label; } /** @brief Get the *English* human-readable name for this locale. */ - QString englishLabel() const - { - return m_englishLabel; - } + QString englishLabel() const { return m_englishLabel; } /** @brief Get the Qt locale. */ - QLocale locale() const - { - return m_locale; - } + QLocale locale() const { return m_locale; } - QString name() const - { - return m_locale.name(); - } + QString name() const { return m_locale.name(); } /// @brief Convenience accessor to the language part of the locale - QLocale::Language language() const - { - return m_locale.language(); - } + QLocale::Language language() const { return m_locale.language(); } /// @brief Convenience accessor to the country part (if any) of the locale - QLocale::Country country() const - { - return m_locale.country(); - } + QLocale::Country country() const { return m_locale.country(); } /** @brief Get a Qt locale for the given @p localeName * @@ -119,9 +99,9 @@ protected: QString m_localeId; // the locale identifier, e.g. "en_GB" QString m_label; // the native name of the locale QString m_englishLabel; -} ; +}; -} -} // namespace +} // namespace Locale +} // namespace CalamaresUtils #endif diff --git a/src/libcalamares/locale/LabelModel.cpp b/src/libcalamares/locale/LabelModel.cpp index 79ff5d67b..87fca9d85 100644 --- a/src/libcalamares/locale/LabelModel.cpp +++ b/src/libcalamares/locale/LabelModel.cpp @@ -34,12 +34,12 @@ LabelModel::LabelModel( const QStringList& locales, QObject* parent ) m_locales.reserve( locales.count() ); for ( const auto& l : locales ) + { m_locales.push_back( Label( l ) ); + } } -LabelModel::~LabelModel() -{ -} +LabelModel::~LabelModel() {} int LabelModel::rowCount( const QModelIndex& ) const @@ -51,10 +51,14 @@ QVariant LabelModel::data( const QModelIndex& index, int role ) const { if ( ( role != LabelRole ) && ( role != EnglishLabelRole ) ) + { return QVariant(); + } if ( !index.isValid() ) + { return QVariant(); + } const auto& locale = m_locales.at( index.row() ); switch ( role ) @@ -75,59 +79,62 @@ LabelModel::locale( int row ) const { for ( const auto& l : m_locales ) if ( l.isEnglish() ) + { return l; - return m_locales[0]; + } + return m_locales[ 0 ]; } - return m_locales[row]; + return m_locales[ row ]; } int -LabelModel::find( std::function predicate ) const +LabelModel::find( std::function< bool( const Label& ) > predicate ) const { - for ( int row = 0; row < m_locales.count() ; ++row ) + for ( int row = 0; row < m_locales.count(); ++row ) { - if ( predicate( m_locales[row] ) ) + if ( predicate( m_locales[ row ] ) ) + { return row; + } } return -1; } int -LabelModel::find( std::function predicate ) const +LabelModel::find( std::function< bool( const QLocale& ) > predicate ) const { - return find( [&]( const Label& l ) - { - return predicate( l.locale() ); - } ); + return find( [&]( const Label& l ) { return predicate( l.locale() ); } ); } int LabelModel::find( const QLocale& locale ) const { - return find( [&]( const Label& l ) - { - return locale == l.locale(); - } ); + return find( [&]( const Label& l ) { return locale == l.locale(); } ); } int LabelModel::find( const QString& countryCode ) const { if ( countryCode.length() != 2 ) + { return -1; + } auto c_l = countryData( countryCode ); - int r = find( [&]( const Label& l ){ return ( l.language() == c_l.second ) && ( l.country() == c_l.first ); } ); + int r = find( [&]( const Label& l ) { return ( l.language() == c_l.second ) && ( l.country() == c_l.first ); } ); if ( r >= 0 ) + { return r; - return find( [&]( const Label& l ){ return l.language() == c_l.second; } ); + } + return find( [&]( const Label& l ) { return l.language() == c_l.second; } ); } -LabelModel* availableTranslations() +LabelModel* +availableTranslations() { - static LabelModel* model = new LabelModel( QString( CALAMARES_TRANSLATION_LANGUAGES ).split( ';') ); + static LabelModel* model = new LabelModel( QString( CALAMARES_TRANSLATION_LANGUAGES ).split( ';' ) ); return model; } -} -} // namespace +} // namespace Locale +} // namespace CalamaresUtils diff --git a/src/libcalamares/locale/LabelModel.h b/src/libcalamares/locale/LabelModel.h index 2f3bee629..5082440d3 100644 --- a/src/libcalamares/locale/LabelModel.h +++ b/src/libcalamares/locale/LabelModel.h @@ -26,7 +26,7 @@ #include -namespace CalamaresUtils +namespace CalamaresUtils { namespace Locale { @@ -58,8 +58,8 @@ public: * * Returns the row number of the first match, or -1 if there isn't one. */ - int find( std::function predicate ) const; - int find( std::function predicate ) const; + int find( std::function< bool( const QLocale& ) > predicate ) const; + int find( std::function< bool( const Label& ) > predicate ) const; /// @brief Looks for an item using the same locale, -1 if there isn't one int find( const QLocale& ) const; /// @brief Looks for an item that best matches the 2-letter country code @@ -67,7 +67,7 @@ public: private: QVector< Label > m_locales; -} ; +}; /** @brief Returns a model with all available translations. * @@ -80,6 +80,6 @@ private: * NOTE: While the model is not typed const, it should be. Do not modify. */ DLLEXPORT LabelModel* availableTranslations(); -} -} // namespace +} // namespace Locale +} // namespace CalamaresUtils #endif diff --git a/src/libcalamares/locale/Lookup.cpp b/src/libcalamares/locale/Lookup.cpp index 73d706de6..baa3ce5b1 100644 --- a/src/libcalamares/locale/Lookup.cpp +++ b/src/libcalamares/locale/Lookup.cpp @@ -28,13 +28,13 @@ namespace Locale struct TwoChar { TwoChar( const QString& code ) - : cc1(0) - , cc2(0) + : cc1( 0 ) + , cc2( 0 ) { if ( code.length() == 2 ) { - cc1 = code[0].toLatin1(); - cc2 = code[1].toLatin1(); + cc1 = code[ 0 ].toLatin1(); + cc2 = code[ 1 ].toLatin1(); } } @@ -42,52 +42,65 @@ struct TwoChar char cc2; }; -static const CountryData* lookup( TwoChar c ) +static const CountryData* +lookup( TwoChar c ) { if ( !c.cc1 ) + { return nullptr; + } - const CountryData* p = std::find_if(country_data_table, country_data_table + country_data_size, - [c=c]( const CountryData& d ){ return (d.cc1 == c.cc1) && (d.cc2 == c.cc2); } - ); + const CountryData* p + = std::find_if( country_data_table, country_data_table + country_data_size, [c = c]( const CountryData& d ) { + return ( d.cc1 == c.cc1 ) && ( d.cc2 == c.cc2 ); + } ); if ( p == country_data_table + country_data_size ) + { return nullptr; + } return p; } -QLocale::Country countryForCode(const QString& code) +QLocale::Country +countryForCode( const QString& code ) { const CountryData* p = lookup( TwoChar( code ) ); return p ? p->c : QLocale::Country::AnyCountry; } -QLocale::Language languageForCountry(const QString& code) +QLocale::Language +languageForCountry( const QString& code ) { const CountryData* p = lookup( TwoChar( code ) ); return p ? p->l : QLocale::Language::AnyLanguage; } -QPair countryData(const QString& code) +QPair< QLocale::Country, QLocale::Language > +countryData( const QString& code ) { const CountryData* p = lookup( TwoChar( code ) ); return p ? qMakePair( p->c, p->l ) : qMakePair( QLocale::Country::AnyCountry, QLocale::Language::AnyLanguage ); } -QLocale countryLocale(const QString& code) +QLocale +countryLocale( const QString& code ) { auto p = countryData( code ); return QLocale( p.second, p.first ); } -QLocale::Language languageForCountry(QLocale::Country country) +QLocale::Language +languageForCountry( QLocale::Country country ) { - const CountryData* p = std::find_if(country_data_table, country_data_table + country_data_size, - [c=country]( const CountryData& d ){ return d.c == c; } - ); + const CountryData* p = std::find_if( country_data_table, + country_data_table + country_data_size, + [c = country]( const CountryData& d ) { return d.c == c; } ); if ( p == country_data_table + country_data_size ) + { return QLocale::Language::AnyLanguage; + } return p->l; } -} -} // namespace +} // namespace Locale +} // namespace CalamaresUtils diff --git a/src/libcalamares/locale/Lookup.h b/src/libcalamares/locale/Lookup.h index 9d1c23cd8..abcee0ed3 100644 --- a/src/libcalamares/locale/Lookup.h +++ b/src/libcalamares/locale/Lookup.h @@ -24,32 +24,32 @@ #include #include -namespace CalamaresUtils +namespace CalamaresUtils { namespace Locale { - /* All the functions in this file do lookups of locale data - * based on CLDR tables; these are lookups that you can't (easily) - * do with just QLocale (e.g. from 2-letter country code to a likely - * locale). - */ +/* All the functions in this file do lookups of locale data + * based on CLDR tables; these are lookups that you can't (easily) + * do with just QLocale (e.g. from 2-letter country code to a likely + * locale). + */ - /// @brief Map a 2-letter code to a Country, or AnyCountry if not found - DLLEXPORT QLocale::Country countryForCode( const QString& code ); - /** @brief Map a Country to a Language, or AnyLanguage if not found - * - * This is a *likely* language for the given country, based on the - * CLDR tables. For instance, this maps Belgium to Dutch. - */ - DLLEXPORT QLocale::Language languageForCountry( QLocale::Country country ); - /// @brief Map a 2-letter code to a Language, or AnyLanguage if not found - DLLEXPORT QLocale::Language languageForCountry( const QString& code ); +/// @brief Map a 2-letter code to a Country, or AnyCountry if not found +DLLEXPORT QLocale::Country countryForCode( const QString& code ); +/** @brief Map a Country to a Language, or AnyLanguage if not found + * + * This is a *likely* language for the given country, based on the + * CLDR tables. For instance, this maps Belgium to Dutch. + */ +DLLEXPORT QLocale::Language languageForCountry( QLocale::Country country ); +/// @brief Map a 2-letter code to a Language, or AnyLanguage if not found +DLLEXPORT QLocale::Language languageForCountry( const QString& code ); - /// @brief Get both Country and Language for a 2-letter code - DLLEXPORT QPair< QLocale::Country, QLocale::Language > countryData( const QString& code ); - /// @brief Get a likely locale for a 2-letter country code - DLLEXPORT QLocale countryLocale( const QString& code ); -} -} // namespace +/// @brief Get both Country and Language for a 2-letter code +DLLEXPORT QPair< QLocale::Country, QLocale::Language > countryData( const QString& code ); +/// @brief Get a likely locale for a 2-letter country code +DLLEXPORT QLocale countryLocale( const QString& code ); +} // namespace Locale +} // namespace CalamaresUtils #endif diff --git a/src/libcalamares/locale/Tests.cpp b/src/libcalamares/locale/Tests.cpp index 6fd0f3e61..9e2071a31 100644 --- a/src/libcalamares/locale/Tests.cpp +++ b/src/libcalamares/locale/Tests.cpp @@ -25,13 +25,9 @@ QTEST_GUILESS_MAIN( LocaleTests ) -LocaleTests::LocaleTests() -{ -} +LocaleTests::LocaleTests() {} -LocaleTests::~LocaleTests() -{ -} +LocaleTests::~LocaleTests() {} void LocaleTests::initTestCase() From fa676c573ed1e69243abd5f0750eda5dd0b95f82 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 4 Aug 2019 22:21:53 +0200 Subject: [PATCH 094/302] CI: Fix style script - when passing in more than one directory, expanded the wrong variable --- ci/calamaresstyle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/calamaresstyle b/ci/calamaresstyle index a877de7d1..46acbdc3d 100755 --- a/ci/calamaresstyle +++ b/ci/calamaresstyle @@ -37,7 +37,7 @@ style_some() if test "x$any_dirs" = "xyes" ; then for d in "$@" do - if test -d "$@" ; then + if test -d "$d" ; then style_some $( find "$d" -maxdepth 1 -type f -name '*.cpp' -o -name '*.h' ) else style_some "$d" From 1afa9c4d0890fa49b6b0bf15090faef8ec57df4d Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 4 Aug 2019 22:24:55 +0200 Subject: [PATCH 095/302] [libcalamares] Apply current coding style to all of libcalamares/ --- src/libcalamares/CppJob.cpp | 8 +- src/libcalamares/CppJob.h | 4 +- src/libcalamares/DllMacro.h | 10 +- src/libcalamares/GlobalStorage.cpp | 37 ++-- src/libcalamares/GlobalStorage.h | 10 +- src/libcalamares/Job.cpp | 8 +- src/libcalamares/Job.h | 9 +- src/libcalamares/JobExample.cpp | 5 +- src/libcalamares/JobExample.h | 14 +- src/libcalamares/JobQueue.cpp | 66 +++--- src/libcalamares/JobQueue.h | 4 +- src/libcalamares/PluginDllMacro.h | 10 +- src/libcalamares/ProcessJob.cpp | 38 ++-- src/libcalamares/ProcessJob.h | 9 +- src/libcalamares/PythonHelper.cpp | 59 +++++- src/libcalamares/PythonHelper.h | 20 +- src/libcalamares/PythonJob.cpp | 319 +++++++++++------------------ src/libcalamares/PythonJob.h | 9 +- src/libcalamares/PythonJobApi.cpp | 101 +++++---- src/libcalamares/PythonJobApi.h | 30 +-- src/libcalamares/Settings.cpp | 61 +++--- src/libcalamares/Settings.h | 8 +- 22 files changed, 406 insertions(+), 433 deletions(-) diff --git a/src/libcalamares/CppJob.cpp b/src/libcalamares/CppJob.cpp index 0512df377..82af344dd 100644 --- a/src/libcalamares/CppJob.cpp +++ b/src/libcalamares/CppJob.cpp @@ -24,11 +24,11 @@ namespace Calamares CppJob::CppJob( QObject* parent ) : Job( parent ) -{} +{ +} -CppJob::~CppJob() -{} +CppJob::~CppJob() {} void @@ -44,4 +44,4 @@ CppJob::setConfigurationMap( const QVariantMap& configurationMap ) Q_UNUSED( configurationMap ) } -} +} // namespace Calamares diff --git a/src/libcalamares/CppJob.h b/src/libcalamares/CppJob.h index 36116b3e7..10ab71649 100644 --- a/src/libcalamares/CppJob.h +++ b/src/libcalamares/CppJob.h @@ -45,6 +45,6 @@ protected: QString m_instanceKey; }; -} +} // namespace Calamares -#endif // CALAMARES_CPPJOB_H +#endif // CALAMARES_CPPJOB_H diff --git a/src/libcalamares/DllMacro.h b/src/libcalamares/DllMacro.h index e0281d7a7..d3e1c8098 100644 --- a/src/libcalamares/DllMacro.h +++ b/src/libcalamares/DllMacro.h @@ -22,11 +22,11 @@ #include #ifndef DLLEXPORT -# if defined (DLLEXPORT_PRO) -# define DLLEXPORT Q_DECL_EXPORT -# else -# define DLLEXPORT Q_DECL_IMPORT -# endif +#if defined( DLLEXPORT_PRO ) +#define DLLEXPORT Q_DECL_EXPORT +#else +#define DLLEXPORT Q_DECL_IMPORT +#endif #endif #endif diff --git a/src/libcalamares/GlobalStorage.cpp b/src/libcalamares/GlobalStorage.cpp index 99be39246..5094ad2fd 100644 --- a/src/libcalamares/GlobalStorage.cpp +++ b/src/libcalamares/GlobalStorage.cpp @@ -21,8 +21,8 @@ #include "JobQueue.h" #include "utils/Logger.h" -#include "utils/Yaml.h" #include "utils/Units.h" +#include "utils/Yaml.h" #include #include @@ -40,7 +40,8 @@ namespace bp = boost::python; using CalamaresUtils::operator""_MiB; -namespace Calamares { +namespace Calamares +{ GlobalStorage::GlobalStorage() : QObject( nullptr ) @@ -102,13 +103,15 @@ GlobalStorage::debugDump() const } bool -GlobalStorage::save(const QString& filename) +GlobalStorage::save( const QString& filename ) { QFile f( filename ); if ( !f.open( QFile::WriteOnly ) ) + { return false; + } - f.write( QJsonDocument::fromVariant( m ).toJson() ) ; + f.write( QJsonDocument::fromVariant( m ).toJson() ); f.close(); return true; } @@ -118,18 +121,24 @@ GlobalStorage::load( const QString& filename ) { QFile f( filename ); if ( !f.open( QFile::ReadOnly ) ) + { return false; + } QJsonParseError e; QJsonDocument d = QJsonDocument::fromJson( f.read( 1_MiB ), &e ); if ( d.isNull() ) + { cWarning() << filename << e.errorString(); + } else if ( !d.isObject() ) + { cWarning() << filename << "Not suitable JSON."; + } else { auto map = d.toVariant().toMap(); - for( auto i = map.constBegin() ; i != map.constEnd() ; ++i ) + for ( auto i = map.constBegin(); i != map.constEnd(); ++i ) { insert( i.key(), *i ); } @@ -150,12 +159,14 @@ GlobalStorage::loadYaml( const QString& filename ) bool ok = false; auto gs = CalamaresUtils::loadYaml( filename, &ok ); if ( ok ) + { m = gs; + } return ok; } -} // namespace Calamares +} // namespace Calamares #ifdef WITH_PYTHON @@ -172,7 +183,7 @@ Calamares::GlobalStorage* GlobalStoragePythonWrapper::s_gs_instance = nullptr; GlobalStoragePythonWrapper::GlobalStoragePythonWrapper( Calamares::GlobalStorage* gs ) : m_gs( gs ? gs : s_gs_instance ) { - if (!m_gs) + if ( !m_gs ) { s_gs_instance = new Calamares::GlobalStorage; m_gs = s_gs_instance; @@ -194,11 +205,9 @@ GlobalStoragePythonWrapper::count() const void -GlobalStoragePythonWrapper::insert( const std::string& key, - const bp::object& value ) +GlobalStoragePythonWrapper::insert( const std::string& key, const bp::object& value ) { - m_gs->insert( QString::fromStdString( key ), - CalamaresPython::variantFromPyObject( value ) ); + m_gs->insert( QString::fromStdString( key ), CalamaresPython::variantFromPyObject( value ) ); } bp::list @@ -207,7 +216,9 @@ GlobalStoragePythonWrapper::keys() const bp::list pyList; const auto keys = m_gs->keys(); for ( const QString& key : keys ) + { pyList.append( key.toStdString() ); + } return pyList; } @@ -225,6 +236,6 @@ GlobalStoragePythonWrapper::value( const std::string& key ) const return CalamaresPython::variantToPyObject( m_gs->value( QString::fromStdString( key ) ) ); } -} // namespace CalamaresPython +} // namespace CalamaresPython -#endif // WITH_PYTHON +#endif // WITH_PYTHON diff --git a/src/libcalamares/GlobalStorage.h b/src/libcalamares/GlobalStorage.h index 89ebb5050..6fdb43fa0 100644 --- a/src/libcalamares/GlobalStorage.h +++ b/src/libcalamares/GlobalStorage.h @@ -34,8 +34,8 @@ namespace api class object; } class list; -} -} +} // namespace python +} // namespace boost #endif namespace Calamares @@ -96,7 +96,7 @@ private: friend DebugWindow; }; -} // namespace Calamares +} // namespace Calamares #ifdef WITH_PYTHON namespace CalamaresPython @@ -124,7 +124,7 @@ private: static Calamares::GlobalStorage* s_gs_instance; // See globalStorageInstance() }; -} // namespace CalamaresPython +} // namespace CalamaresPython #endif -#endif // CALAMARES_GLOBALSTORAGE_H +#endif // CALAMARES_GLOBALSTORAGE_H diff --git a/src/libcalamares/Job.cpp b/src/libcalamares/Job.cpp index 116ed77e2..d074a18cb 100644 --- a/src/libcalamares/Job.cpp +++ b/src/libcalamares/Job.cpp @@ -84,7 +84,8 @@ JobResult::JobResult( const QString& message, const QString& details, int number : m_message( message ) , m_details( details ) , m_number( number ) -{} +{ +} Job::Job( QObject* parent ) @@ -93,8 +94,7 @@ Job::Job( QObject* parent ) } -Job::~Job() -{} +Job::~Job() {} qreal @@ -118,4 +118,4 @@ Job::prettyStatusMessage() const } -} // namespace Calamares +} // namespace Calamares diff --git a/src/libcalamares/Job.h b/src/libcalamares/Job.h index e0b24fa9b..3eaa251ef 100644 --- a/src/libcalamares/Job.h +++ b/src/libcalamares/Job.h @@ -25,7 +25,8 @@ #include #include -namespace Calamares { +namespace Calamares +{ class DLLEXPORT JobResult { @@ -43,7 +44,7 @@ public: GenericError = -1, PythonUncaughtException = 1, InvalidConfiguration = 2 - } ; + }; JobResult( const JobResult& rhs ) = delete; JobResult( JobResult&& rhs ); @@ -102,6 +103,6 @@ private: using job_ptr = QSharedPointer< Job >; using JobList = QList< job_ptr >; -} // namespace Calamares +} // namespace Calamares -#endif // CALAMARES_JOB_H +#endif // CALAMARES_JOB_H diff --git a/src/libcalamares/JobExample.cpp b/src/libcalamares/JobExample.cpp index 83259ae6d..83da2b1e1 100644 --- a/src/libcalamares/JobExample.cpp +++ b/src/libcalamares/JobExample.cpp @@ -36,7 +36,8 @@ GoodJob::exec() JobResult FailJob::exec() { - return JobResult::error( tr( "Job failed (%1)" ).arg( m_name ), tr( "Programmed job failure was explicitly requested." ) ); + return JobResult::error( tr( "Job failed (%1)" ).arg( m_name ), + tr( "Programmed job failure was explicitly requested." ) ); } -} // namespace +} // namespace Calamares diff --git a/src/libcalamares/JobExample.h b/src/libcalamares/JobExample.h index fd5eea109..92f8f8fb6 100644 --- a/src/libcalamares/JobExample.h +++ b/src/libcalamares/JobExample.h @@ -21,7 +21,8 @@ #include "Job.h" -namespace Calamares { +namespace Calamares +{ /** @brief A Job with a name * @@ -39,9 +40,10 @@ public: } virtual QString prettyName() const override; + protected: const QString m_name; -} ; +}; /// @brief Job does nothing, always succeeds class DLLEXPORT GoodJob : public NamedJob @@ -53,7 +55,7 @@ public: } virtual JobResult exec() override; -} ; +}; /// @brief Job does nothing, always fails @@ -66,8 +68,8 @@ public: } virtual JobResult exec() override; -} ; +}; -} // namespace Calamares +} // namespace Calamares -#endif // CALAMARES_JOB_EXAMPLE_H +#endif // CALAMARES_JOB_EXAMPLE_H diff --git a/src/libcalamares/JobQueue.cpp b/src/libcalamares/JobQueue.cpp index 49a70bca8..6772671b7 100644 --- a/src/libcalamares/JobQueue.cpp +++ b/src/libcalamares/JobQueue.cpp @@ -19,8 +19,8 @@ #include "JobQueue.h" -#include "Job.h" #include "GlobalStorage.h" +#include "Job.h" #include "utils/Logger.h" #include "CalamaresConfig.h" @@ -50,14 +50,14 @@ public: m_jobs = jobs; qreal totalJobsWeight = 0.0; - for( auto job : m_jobs ) + for ( auto job : m_jobs ) { totalJobsWeight += job->getJobWeight(); } - for( auto job : m_jobs ) + for ( auto job : m_jobs ) { qreal jobWeight = qreal( job->getJobWeight() / totalJobsWeight ); - m_jobWeights.append( jobWeight ) ; + m_jobWeights.append( jobWeight ); } } @@ -68,7 +68,7 @@ public: QString details; m_jobIndex = 0; - for( auto job : m_jobs ) + for ( auto job : m_jobs ) { if ( anyFailed && !job->isEmergency() ) { @@ -87,12 +87,18 @@ public: details = result.details(); } if ( !anyFailed ) + { ++m_jobIndex; + } } if ( anyFailed ) + { emitFailed( message, details ); + } else + { emitProgress(); + } emitFinished(); } @@ -109,49 +115,39 @@ private: jobPercent = qBound( qreal( 0 ), jobPercent, qreal( 1 ) ); int jobCount = m_jobs.size(); - QString message = m_jobIndex < jobCount - ? m_jobs.at( m_jobIndex )->prettyStatusMessage() - : tr( "Done" ); + QString message = m_jobIndex < jobCount ? m_jobs.at( m_jobIndex )->prettyStatusMessage() : tr( "Done" ); qreal cumulativeProgress = 0.0; - for( auto jobWeight : m_jobWeights.mid( 0, m_jobIndex ) ) + for ( auto jobWeight : m_jobWeights.mid( 0, m_jobIndex ) ) { cumulativeProgress += jobWeight; } - qreal percent = m_jobIndex < jobCount - ? cumulativeProgress + ( ( m_jobWeights.at( m_jobIndex ) ) * jobPercent ) - : 1.0; + qreal percent + = m_jobIndex < jobCount ? cumulativeProgress + ( ( m_jobWeights.at( m_jobIndex ) ) * jobPercent ) : 1.0; - if (m_jobIndex < jobCount) + if ( m_jobIndex < jobCount ) { - cDebug(Logger::LOGVERBOSE) << "[JOBQUEUE]: Progress for Job[" << m_jobIndex << "]: " << ( jobPercent * 100 ) << "% completed"; - cDebug(Logger::LOGVERBOSE) << "[JOBQUEUE]: Progress Overall: " << ( cumulativeProgress * 100 ) << "% (accumulated) + " - << ( ( ( m_jobWeights.at( m_jobIndex ) ) * jobPercent ) * 100 ) << "% (this job) = " - << ( percent * 100 ) << "% (total)"; + cDebug( Logger::LOGVERBOSE ) << "[JOBQUEUE]: Progress for Job[" << m_jobIndex + << "]: " << ( jobPercent * 100 ) << "% completed"; + cDebug( Logger::LOGVERBOSE ) << "[JOBQUEUE]: Progress Overall: " << ( cumulativeProgress * 100 ) + << "% (accumulated) + " + << ( ( ( m_jobWeights.at( m_jobIndex ) ) * jobPercent ) * 100 ) + << "% (this job) = " << ( percent * 100 ) << "% (total)"; } - QMetaObject::invokeMethod( m_queue, "progress", Qt::QueuedConnection, - Q_ARG( qreal, percent ), - Q_ARG( QString, message ) - ); + QMetaObject::invokeMethod( + m_queue, "progress", Qt::QueuedConnection, Q_ARG( qreal, percent ), Q_ARG( QString, message ) ); } void emitFailed( const QString& message, const QString& details ) { - QMetaObject::invokeMethod( m_queue, "failed", Qt::QueuedConnection, - Q_ARG( QString, message ), - Q_ARG( QString, details ) - ); + QMetaObject::invokeMethod( + m_queue, "failed", Qt::QueuedConnection, Q_ARG( QString, message ), Q_ARG( QString, details ) ); } - void emitFinished() - { - QMetaObject::invokeMethod( m_queue, "finished", Qt::QueuedConnection ); - } + void emitFinished() { QMetaObject::invokeMethod( m_queue, "finished", Qt::QueuedConnection ); } }; -JobThread::~JobThread() -{ -} +JobThread::~JobThread() {} JobQueue* JobQueue::s_instance = nullptr; @@ -186,8 +182,10 @@ JobQueue::~JobQueue() if ( m_thread->isRunning() ) { m_thread->terminate(); - if ( !m_thread->wait(300) ) + if ( !m_thread->wait( 300 ) ) + { cError() << "Could not terminate job thread (expect a crash now)."; + } delete m_thread; } @@ -222,4 +220,4 @@ JobQueue::enqueue( const JobList& jobs ) emit queueChanged( m_jobs ); } -} // namespace Calamares +} // namespace Calamares diff --git a/src/libcalamares/JobQueue.h b/src/libcalamares/JobQueue.h index 4e5dffe8a..a58b873d9 100644 --- a/src/libcalamares/JobQueue.h +++ b/src/libcalamares/JobQueue.h @@ -59,6 +59,6 @@ private: GlobalStorage* m_storage; }; -} +} // namespace Calamares -#endif // CALAMARES_JOBQUEUE_H +#endif // CALAMARES_JOBQUEUE_H diff --git a/src/libcalamares/PluginDllMacro.h b/src/libcalamares/PluginDllMacro.h index cabe09887..d790230b9 100644 --- a/src/libcalamares/PluginDllMacro.h +++ b/src/libcalamares/PluginDllMacro.h @@ -22,11 +22,11 @@ #include #ifndef PLUGINDLLEXPORT -# if defined (PLUGINDLLEXPORT_PRO) -# define PLUGINDLLEXPORT Q_DECL_EXPORT -# else -# define PLUGINDLLEXPORT Q_DECL_IMPORT -# endif +#if defined( PLUGINDLLEXPORT_PRO ) +#define PLUGINDLLEXPORT Q_DECL_EXPORT +#else +#define PLUGINDLLEXPORT Q_DECL_IMPORT +#endif #endif #endif diff --git a/src/libcalamares/ProcessJob.cpp b/src/libcalamares/ProcessJob.cpp index f952fefe6..744f5f9bf 100644 --- a/src/libcalamares/ProcessJob.cpp +++ b/src/libcalamares/ProcessJob.cpp @@ -25,7 +25,8 @@ #include #include -namespace Calamares { +namespace Calamares +{ ProcessJob::ProcessJob( const QString& command, @@ -38,27 +39,24 @@ ProcessJob::ProcessJob( const QString& command, , m_workingPath( workingPath ) , m_runInChroot( runInChroot ) , m_timeoutSec( secondsTimeout ) -{} +{ +} -ProcessJob::~ProcessJob() -{} +ProcessJob::~ProcessJob() {} QString ProcessJob::prettyName() const { - return ( m_runInChroot ? tr( "Run command '%1' in target system." ) : tr( " Run command '%1'." ) ) - .arg( m_command ); + return ( m_runInChroot ? tr( "Run command '%1' in target system." ) : tr( " Run command '%1'." ) ).arg( m_command ); } QString ProcessJob::prettyStatusMessage() const { - return tr( "Running command %1 %2" ) - .arg( m_command ) - .arg( m_runInChroot ? "in chroot." : " ." ); + return tr( "Running command %1 %2" ).arg( m_command ).arg( m_runInChroot ? "in chroot." : " ." ); } @@ -68,20 +66,16 @@ ProcessJob::exec() using CalamaresUtils::System; if ( m_runInChroot ) - return CalamaresUtils::System::instance()-> - targetEnvCommand( { m_command }, - m_workingPath, - QString(), - m_timeoutSec ) - .explainProcess( m_command, m_timeoutSec ); + return CalamaresUtils::System::instance() + ->targetEnvCommand( { m_command }, m_workingPath, QString(), m_timeoutSec ) + .explainProcess( m_command, m_timeoutSec ); else - return - System::runCommand( System::RunLocation::RunInHost, - { "/bin/sh", "-c", m_command }, - m_workingPath, - QString(), - m_timeoutSec ) + return System::runCommand( System::RunLocation::RunInHost, + { "/bin/sh", "-c", m_command }, + m_workingPath, + QString(), + m_timeoutSec ) .explainProcess( m_command, m_timeoutSec ); } -} // namespace Calamares +} // namespace Calamares diff --git a/src/libcalamares/ProcessJob.h b/src/libcalamares/ProcessJob.h index 84f84e550..e826acb1d 100644 --- a/src/libcalamares/ProcessJob.h +++ b/src/libcalamares/ProcessJob.h @@ -24,7 +24,8 @@ #include -namespace Calamares { +namespace Calamares +{ class ProcessJob : public Job { @@ -33,7 +34,7 @@ public: explicit ProcessJob( const QString& command, const QString& workingPath, bool runInChroot = false, - std::chrono::seconds secondsTimeout = std::chrono::seconds(30), + std::chrono::seconds secondsTimeout = std::chrono::seconds( 30 ), QObject* parent = nullptr ); virtual ~ProcessJob() override; @@ -48,6 +49,6 @@ private: std::chrono::seconds m_timeoutSec; }; -} // namespace Calamares +} // namespace Calamares -#endif // CALAMARES_PROCESSJOB_H +#endif // CALAMARES_PROCESSJOB_H diff --git a/src/libcalamares/PythonHelper.cpp b/src/libcalamares/PythonHelper.cpp index 3c4d1cca6..40210856b 100644 --- a/src/libcalamares/PythonHelper.cpp +++ b/src/libcalamares/PythonHelper.cpp @@ -72,25 +72,39 @@ variantFromPyObject( const boost::python::object& pyObject ) { std::string pyType = bp::extract< std::string >( pyObject.attr( "__class__" ).attr( "__name__" ) ); if ( pyType == "dict" ) + { return variantMapFromPyDict( bp::extract< bp::dict >( pyObject ) ); + } else if ( pyType == "list" ) + { return variantListFromPyList( bp::extract< bp::list >( pyObject ) ); + } else if ( pyType == "int" ) + { return QVariant( bp::extract< int >( pyObject ) ); + } else if ( pyType == "float" ) + { return QVariant( bp::extract< double >( pyObject ) ); + } else if ( pyType == "str" ) + { return QVariant( QString::fromStdString( bp::extract< std::string >( pyObject ) ) ); + } else if ( pyType == "bool" ) + { return QVariant( bp::extract< bool >( pyObject ) ); + } else + { return QVariant(); + } } @@ -99,7 +113,9 @@ variantListToPyList( const QVariantList& variantList ) { bp::list pyList; for ( const QVariant& variant : variantList ) + { pyList.append( variantToPyObject( variant ) ); + } return pyList; } @@ -109,7 +125,9 @@ variantListFromPyList( const boost::python::list& pyList ) { QVariantList list; for ( int i = 0; i < bp::len( pyList ); ++i ) + { list.append( variantFromPyObject( pyList[ i ] ) ); + } return list; } @@ -119,7 +137,9 @@ variantMapToPyDict( const QVariantMap& variantMap ) { bp::dict pyDict; for ( auto it = variantMap.constBegin(); it != variantMap.constEnd(); ++it ) + { pyDict[ it.key().toStdString() ] = variantToPyObject( it.value() ); + } return pyDict; } @@ -152,7 +172,9 @@ variantHashToPyDict( const QVariantHash& variantHash ) { bp::dict pyDict; for ( auto it = variantHash.constBegin(); it != variantHash.constEnd(); ++it ) + { pyDict[ it.key().toStdString() ] = variantToPyObject( it.value() ); + } return pyDict; } @@ -181,17 +203,21 @@ variantHashFromPyDict( const boost::python::dict& pyDict ) } - Helper* Helper::s_instance = nullptr; -static inline void add_if_lib_exists( const QDir& dir, const char* name, QStringList& list ) +static inline void +add_if_lib_exists( const QDir& dir, const char* name, QStringList& list ) { - if ( ! ( dir.exists() && dir.isReadable() ) ) + if ( !( dir.exists() && dir.isReadable() ) ) + { return; + } QFileInfo fi( dir.absoluteFilePath( name ) ); if ( fi.exists() && fi.isReadable() ) + { list.append( fi.dir().absolutePath() ); + } } Helper::Helper( QObject* parent ) @@ -201,7 +227,9 @@ Helper::Helper( QObject* parent ) if ( !s_instance ) { if ( !Py_IsInitialized() ) + { Py_Initialize(); + } m_mainModule = bp::import( "__main__" ); m_mainNamespace = m_mainModule.attr( "__dict__" ); @@ -209,8 +237,7 @@ Helper::Helper( QObject* parent ) // If we're running from the build dir add_if_lib_exists( QDir::current(), "libcalamares.so", m_pythonPaths ); - QDir calaPythonPath( CalamaresUtils::systemLibDir().absolutePath() + - QDir::separator() + "calamares" ); + QDir calaPythonPath( CalamaresUtils::systemLibDir().absolutePath() + QDir::separator() + "calamares" ); add_if_lib_exists( calaPythonPath, "libcalamares.so", m_pythonPaths ); bp::object sys = bp::import( "sys" ); @@ -251,7 +278,7 @@ Helper::createCleanNamespace() QString Helper::handleLastError() { - PyObject* type = nullptr, *val = nullptr, *traceback_p = nullptr; + PyObject *type = nullptr, *val = nullptr, *traceback_p = nullptr; PyErr_Fetch( &type, &val, &traceback_p ); Logger::CDebug debug; @@ -264,10 +291,14 @@ Helper::handleLastError() bp::str pystr( h_type ); bp::extract< std::string > extracted( pystr ); if ( extracted.check() ) + { typeMsg = QString::fromStdString( extracted() ).trimmed(); + } if ( typeMsg.isEmpty() ) + { typeMsg = tr( "Unknown exception type" ); + } debug << typeMsg << '\n'; } @@ -278,10 +309,14 @@ Helper::handleLastError() bp::str pystr( h_val ); bp::extract< std::string > extracted( pystr ); if ( extracted.check() ) + { valMsg = QString::fromStdString( extracted() ).trimmed(); + } if ( valMsg.isEmpty() ) + { valMsg = tr( "unparseable Python error" ); + } // Special-case: CalledProcessError has an attribute "output" with the command output, // add that to the printed message. @@ -318,22 +353,32 @@ Helper::handleLastError() bp::object pystr( bp::str( "\n" ).join( tb_list ) ); bp::extract< std::string > extracted( pystr ); if ( extracted.check() ) + { tbMsg = QString::fromStdString( extracted() ).trimmed(); + } if ( tbMsg.isEmpty() ) + { tbMsg = tr( "unparseable Python traceback" ); + } debug << tbMsg << '\n'; } if ( typeMsg.isEmpty() && valMsg.isEmpty() && tbMsg.isEmpty() ) + { return tr( "Unfetchable Python error." ); + } QStringList msgList; if ( !typeMsg.isEmpty() ) + { msgList.append( QString( "%1" ).arg( typeMsg.toHtmlEscaped() ) ); + } if ( !valMsg.isEmpty() ) + { msgList.append( valMsg.toHtmlEscaped() ); + } if ( !tbMsg.isEmpty() ) { @@ -346,4 +391,4 @@ Helper::handleLastError() } -} // namespace CalamaresPython +} // namespace CalamaresPython diff --git a/src/libcalamares/PythonHelper.h b/src/libcalamares/PythonHelper.h index 693d80d8b..667a08614 100644 --- a/src/libcalamares/PythonHelper.h +++ b/src/libcalamares/PythonHelper.h @@ -32,17 +32,17 @@ namespace CalamaresPython { -boost::python::object variantToPyObject( const QVariant& variant ); -QVariant variantFromPyObject( const boost::python::object& pyObject ); +boost::python::object variantToPyObject( const QVariant& variant ); +QVariant variantFromPyObject( const boost::python::object& pyObject ); -boost::python::list variantListToPyList( const QVariantList& variantList ); -QVariantList variantListFromPyList( const boost::python::list& pyList ); +boost::python::list variantListToPyList( const QVariantList& variantList ); +QVariantList variantListFromPyList( const boost::python::list& pyList ); -boost::python::dict variantMapToPyDict( const QVariantMap& variantMap ); -QVariantMap variantMapFromPyDict( const boost::python::dict& pyDict ); +boost::python::dict variantMapToPyDict( const QVariantMap& variantMap ); +QVariantMap variantMapFromPyDict( const boost::python::dict& pyDict ); -boost::python::dict variantHashToPyDict( const QVariantHash& variantHash ); -QVariantHash variantHashFromPyDict( const boost::python::dict& pyDict ); +boost::python::dict variantHashToPyDict( const QVariantHash& variantHash ); +QVariantHash variantHashFromPyDict( const boost::python::dict& pyDict ); class Helper : public QObject @@ -66,6 +66,6 @@ private: QStringList m_pythonPaths; }; -} // namespace Calamares +} // namespace CalamaresPython -#endif // CALAMARES_PYTHONJOBHELPER_H +#endif // CALAMARES_PYTHONJOBHELPER_H diff --git a/src/libcalamares/PythonJob.cpp b/src/libcalamares/PythonJob.cpp index 32792e737..da87b8b00 100644 --- a/src/libcalamares/PythonJob.cpp +++ b/src/libcalamares/PythonJob.cpp @@ -19,10 +19,10 @@ #include "PythonJob.h" -#include "PythonHelper.h" -#include "utils/Logger.h" #include "GlobalStorage.h" #include "JobQueue.h" +#include "PythonHelper.h" +#include "utils/Logger.h" #include @@ -35,27 +35,19 @@ namespace bp = boost::python; -BOOST_PYTHON_FUNCTION_OVERLOADS( mount_overloads, - CalamaresPython::mount, - 2, 4 ); -BOOST_PYTHON_FUNCTION_OVERLOADS( target_env_call_str_overloads, - CalamaresPython::target_env_call, - 1, 3 ); -BOOST_PYTHON_FUNCTION_OVERLOADS( target_env_call_list_overloads, - CalamaresPython::target_env_call, - 1, 3 ); -BOOST_PYTHON_FUNCTION_OVERLOADS( check_target_env_call_str_overloads, - CalamaresPython::check_target_env_call, - 1, 3 ); -BOOST_PYTHON_FUNCTION_OVERLOADS( check_target_env_call_list_overloads, - CalamaresPython::check_target_env_call, - 1, 3 ); +BOOST_PYTHON_FUNCTION_OVERLOADS( mount_overloads, CalamaresPython::mount, 2, 4 ); +BOOST_PYTHON_FUNCTION_OVERLOADS( target_env_call_str_overloads, CalamaresPython::target_env_call, 1, 3 ); +BOOST_PYTHON_FUNCTION_OVERLOADS( target_env_call_list_overloads, CalamaresPython::target_env_call, 1, 3 ); +BOOST_PYTHON_FUNCTION_OVERLOADS( check_target_env_call_str_overloads, CalamaresPython::check_target_env_call, 1, 3 ); +BOOST_PYTHON_FUNCTION_OVERLOADS( check_target_env_call_list_overloads, CalamaresPython::check_target_env_call, 1, 3 ); BOOST_PYTHON_FUNCTION_OVERLOADS( check_target_env_output_str_overloads, CalamaresPython::check_target_env_output, - 1, 3 ); + 1, + 3 ); BOOST_PYTHON_FUNCTION_OVERLOADS( check_target_env_output_list_overloads, CalamaresPython::check_target_env_output, - 1, 3 ); + 1, + 3 ); BOOST_PYTHON_MODULE( libcalamares ) { bp::object package = bp::scope(); @@ -68,25 +60,24 @@ BOOST_PYTHON_MODULE( libcalamares ) bp::scope().attr( "VERSION_SHORT" ) = CALAMARES_VERSION_SHORT; bp::class_< CalamaresPython::PythonJobInterface >( "Job", bp::init< Calamares::PythonJob* >() ) - .def_readonly( "module_name", &CalamaresPython::PythonJobInterface::moduleName ) - .def_readonly( "pretty_name", &CalamaresPython::PythonJobInterface::prettyName ) - .def_readonly( "working_path", &CalamaresPython::PythonJobInterface::workingPath ) + .def_readonly( "module_name", &CalamaresPython::PythonJobInterface::moduleName ) + .def_readonly( "pretty_name", &CalamaresPython::PythonJobInterface::prettyName ) + .def_readonly( "working_path", &CalamaresPython::PythonJobInterface::workingPath ) .def_readonly( "configuration", &CalamaresPython::PythonJobInterface::configuration ) - .def( - "setprogress", - &CalamaresPython::PythonJobInterface::setprogress, - bp::args( "progress" ), - "Reports the progress status of this job to Calamares, " - "as a real number between 0 and 1." - ); + .def( "setprogress", + &CalamaresPython::PythonJobInterface::setprogress, + bp::args( "progress" ), + "Reports the progress status of this job to Calamares, " + "as a real number between 0 and 1." ); - bp::class_< CalamaresPython::GlobalStoragePythonWrapper >( "GlobalStorage", bp::init< Calamares::GlobalStorage* >() ) - .def( "contains", &CalamaresPython::GlobalStoragePythonWrapper::contains ) - .def( "count", &CalamaresPython::GlobalStoragePythonWrapper::count ) - .def( "insert", &CalamaresPython::GlobalStoragePythonWrapper::insert ) - .def( "keys", &CalamaresPython::GlobalStoragePythonWrapper::keys ) - .def( "remove", &CalamaresPython::GlobalStoragePythonWrapper::remove ) - .def( "value", &CalamaresPython::GlobalStoragePythonWrapper::value ); + bp::class_< CalamaresPython::GlobalStoragePythonWrapper >( "GlobalStorage", + bp::init< Calamares::GlobalStorage* >() ) + .def( "contains", &CalamaresPython::GlobalStoragePythonWrapper::contains ) + .def( "count", &CalamaresPython::GlobalStoragePythonWrapper::count ) + .def( "insert", &CalamaresPython::GlobalStoragePythonWrapper::insert ) + .def( "keys", &CalamaresPython::GlobalStoragePythonWrapper::keys ) + .def( "remove", &CalamaresPython::GlobalStoragePythonWrapper::remove ) + .def( "value", &CalamaresPython::GlobalStoragePythonWrapper::value ); // libcalamares.utils submodule starts here bp::object utilsModule( bp::handle<>( bp::borrowed( PyImport_AddModule( "libcalamares.utils" ) ) ) ); @@ -95,151 +86,88 @@ BOOST_PYTHON_MODULE( libcalamares ) Q_UNUSED( utilsScope ) bp::def( - "debug", - &CalamaresPython::debug, - bp::args( "s" ), - "Writes the given string to the Calamares debug stream." - ); - bp::def( - "warning", - &CalamaresPython::warning, - bp::args( "s" ), - "Writes the given string to the Calamares warning stream." - ); + "debug", &CalamaresPython::debug, bp::args( "s" ), "Writes the given string to the Calamares debug stream." ); + bp::def( "warning", + &CalamaresPython::warning, + bp::args( "s" ), + "Writes the given string to the Calamares warning stream." ); - bp::def( - "mount", - &CalamaresPython::mount, - mount_overloads( - bp::args( "device_path", - "mount_point", - "filesystem_name", - "options" ), - "Runs the mount utility with the specified parameters.\n" - "Returns the program's exit code, or:\n" - "-1 = QProcess crash\n" - "-2 = QProcess cannot start\n" - "-3 = bad arguments" - ) - ); + bp::def( "mount", + &CalamaresPython::mount, + mount_overloads( bp::args( "device_path", "mount_point", "filesystem_name", "options" ), + "Runs the mount utility with the specified parameters.\n" + "Returns the program's exit code, or:\n" + "-1 = QProcess crash\n" + "-2 = QProcess cannot start\n" + "-3 = bad arguments" ) ); bp::def( "target_env_call", - static_cast< int (*)( const std::string&, - const std::string&, - int ) >( &CalamaresPython::target_env_call ), - target_env_call_str_overloads( - bp::args( "command", - "stdin", - "timeout" ), - "Runs the specified command in the chroot of the target system.\n" - "Returns the program's exit code, or:\n" - "-1 = QProcess crash\n" - "-2 = QProcess cannot start\n" - "-3 = bad arguments\n" - "-4 = QProcess timeout" - ) - ); - bp::def( - "target_env_call", - static_cast< int (*)( const bp::list&, - const std::string&, - int ) >( &CalamaresPython::target_env_call ), - target_env_call_list_overloads( - bp::args( "args", - "stdin", - "timeout" ), - "Runs the specified command in the chroot of the target system.\n" - "Returns the program's exit code, or:\n" - "-1 = QProcess crash\n" - "-2 = QProcess cannot start\n" - "-3 = bad arguments\n" - "-4 = QProcess timeout" - ) - ); + static_cast< int ( * )( const std::string&, const std::string&, int ) >( &CalamaresPython::target_env_call ), + target_env_call_str_overloads( bp::args( "command", "stdin", "timeout" ), + "Runs the specified command in the chroot of the target system.\n" + "Returns the program's exit code, or:\n" + "-1 = QProcess crash\n" + "-2 = QProcess cannot start\n" + "-3 = bad arguments\n" + "-4 = QProcess timeout" ) ); + bp::def( "target_env_call", + static_cast< int ( * )( const bp::list&, const std::string&, int ) >( &CalamaresPython::target_env_call ), + target_env_call_list_overloads( bp::args( "args", "stdin", "timeout" ), + "Runs the specified command in the chroot of the target system.\n" + "Returns the program's exit code, or:\n" + "-1 = QProcess crash\n" + "-2 = QProcess cannot start\n" + "-3 = bad arguments\n" + "-4 = QProcess timeout" ) ); + bp::def( "check_target_env_call", + static_cast< int ( * )( const std::string&, const std::string&, int ) >( + &CalamaresPython::check_target_env_call ), + check_target_env_call_str_overloads( bp::args( "command", "stdin", "timeout" ), + "Runs the specified command in the chroot of the target system.\n" + "Returns 0, which is program's exit code if the program exited " + "successfully, or raises a subprocess.CalledProcessError." ) ); bp::def( "check_target_env_call", - static_cast< int (*)( const std::string&, - const std::string&, - int ) >( &CalamaresPython::check_target_env_call ), - check_target_env_call_str_overloads( - bp::args( "command", - "stdin", - "timeout" ), - "Runs the specified command in the chroot of the target system.\n" - "Returns 0, which is program's exit code if the program exited " - "successfully, or raises a subprocess.CalledProcessError." - ) - ); - bp::def( - "check_target_env_call", - static_cast< int (*)( const bp::list&, - const std::string&, - int ) >( &CalamaresPython::check_target_env_call ), - check_target_env_call_list_overloads( - bp::args( "args", - "stdin", - "timeout" ), - "Runs the specified command in the chroot of the target system.\n" - "Returns 0, which is program's exit code if the program exited " - "successfully, or raises a subprocess.CalledProcessError." - ) - ); + static_cast< int ( * )( const bp::list&, const std::string&, int ) >( &CalamaresPython::check_target_env_call ), + check_target_env_call_list_overloads( bp::args( "args", "stdin", "timeout" ), + "Runs the specified command in the chroot of the target system.\n" + "Returns 0, which is program's exit code if the program exited " + "successfully, or raises a subprocess.CalledProcessError." ) ); - bp::def( - "check_target_env_output", - static_cast< std::string (*)( const std::string&, - const std::string&, - int ) >( &CalamaresPython::check_target_env_output ), - check_target_env_output_str_overloads( - bp::args( "command", - "stdin", - "timeout" ), - "Runs the specified command in the chroot of the target system.\n" - "Returns the program's standard output, and raises a " - "subprocess.CalledProcessError if something went wrong." - ) - ); - bp::def( - "check_target_env_output", - static_cast< std::string (*)( const bp::list&, - const std::string&, - int ) >( &CalamaresPython::check_target_env_output ), - check_target_env_output_list_overloads( - bp::args( "args", - "stdin", - "timeout" ), - "Runs the specified command in the chroot of the target system.\n" - "Returns the program's standard output, and raises a " - "subprocess.CalledProcessError if something went wrong." - ) - ); - bp::def( - "obscure", - &CalamaresPython::obscure, - bp::args( "s" ), - "Simple string obfuscation function based on KStringHandler::obscure.\n" - "Returns a string, generated using a simple symmetric encryption.\n" - "Applying the function to a string obscured by this function will result " - "in the original string." - ); + bp::def( "check_target_env_output", + static_cast< std::string ( * )( const std::string&, const std::string&, int ) >( + &CalamaresPython::check_target_env_output ), + check_target_env_output_str_overloads( bp::args( "command", "stdin", "timeout" ), + "Runs the specified command in the chroot of the target system.\n" + "Returns the program's standard output, and raises a " + "subprocess.CalledProcessError if something went wrong." ) ); + bp::def( "check_target_env_output", + static_cast< std::string ( * )( const bp::list&, const std::string&, int ) >( + &CalamaresPython::check_target_env_output ), + check_target_env_output_list_overloads( bp::args( "args", "stdin", "timeout" ), + "Runs the specified command in the chroot of the target system.\n" + "Returns the program's standard output, and raises a " + "subprocess.CalledProcessError if something went wrong." ) ); + bp::def( "obscure", + &CalamaresPython::obscure, + bp::args( "s" ), + "Simple string obfuscation function based on KStringHandler::obscure.\n" + "Returns a string, generated using a simple symmetric encryption.\n" + "Applying the function to a string obscured by this function will result " + "in the original string." ); - bp::def( - "gettext_languages", - &CalamaresPython::gettext_languages, - "Returns list of languages (most to least-specific) for gettext." - ); + bp::def( "gettext_languages", + &CalamaresPython::gettext_languages, + "Returns list of languages (most to least-specific) for gettext." ); - bp::def( - "gettext_path", - &CalamaresPython::gettext_path, - "Returns path for gettext search." - ); + bp::def( "gettext_path", &CalamaresPython::gettext_path, "Returns path for gettext search." ); } -namespace Calamares { +namespace Calamares +{ PythonJob::PythonJob( const QString& scriptFile, @@ -255,8 +183,7 @@ PythonJob::PythonJob( const QString& scriptFile, } -PythonJob::~PythonJob() -{} +PythonJob::~PythonJob() {} QString @@ -270,10 +197,11 @@ QString PythonJob::prettyStatusMessage() const { if ( m_description.isEmpty() ) - return tr( "Running %1 operation." ) - .arg( QDir( m_workingPath ).dirName() ); + return tr( "Running %1 operation." ).arg( QDir( m_workingPath ).dirName() ); else + { return m_description; + } } @@ -282,24 +210,20 @@ PythonJob::exec() { // We assume m_scriptFile to be relative to m_workingPath. QDir workingDir( m_workingPath ); - if ( !workingDir.exists() || - !workingDir.isReadable() ) + if ( !workingDir.exists() || !workingDir.isReadable() ) { - return JobResult::error( tr( "Bad working directory path" ), - tr( "Working directory %1 for python job %2 is not readable." ) - .arg( m_workingPath ) - .arg( prettyName() ) ); + return JobResult::error( + tr( "Bad working directory path" ), + tr( "Working directory %1 for python job %2 is not readable." ).arg( m_workingPath ).arg( prettyName() ) ); } QFileInfo scriptFI( workingDir.absoluteFilePath( m_scriptFile ) ); - if ( !scriptFI.exists() || - !scriptFI.isFile() || - !scriptFI.isReadable() ) + if ( !scriptFI.exists() || !scriptFI.isFile() || !scriptFI.isReadable() ) { return JobResult::error( tr( "Bad main script file" ), tr( "Main script file %1 for python job %2 is not readable." ) - .arg( scriptFI.absoluteFilePath() ) - .arg( prettyName() ) ); + .arg( scriptFI.absoluteFilePath() ) + .arg( prettyName() ) ); } try @@ -310,15 +234,14 @@ PythonJob::exec() bp::dict calamaresNamespace = bp::extract< bp::dict >( calamaresModule.attr( "__dict__" ) ); calamaresNamespace[ "job" ] = CalamaresPython::PythonJobInterface( this ); - calamaresNamespace[ "globalstorage" ] = CalamaresPython::GlobalStoragePythonWrapper( - JobQueue::instance()->globalStorage() ); + calamaresNamespace[ "globalstorage" ] + = CalamaresPython::GlobalStoragePythonWrapper( JobQueue::instance()->globalStorage() ); - bp::object execResult = bp::exec_file( scriptFI.absoluteFilePath().toLocal8Bit().data(), - scriptNamespace, - scriptNamespace ); + bp::object execResult + = bp::exec_file( scriptFI.absoluteFilePath().toLocal8Bit().data(), scriptNamespace, scriptNamespace ); bp::object entryPoint = scriptNamespace[ "run" ]; - bp::object prettyNameFunc = scriptNamespace.get("pretty_name", bp::object()); + bp::object prettyNameFunc = scriptNamespace.get( "pretty_name", bp::object() ); cDebug() << "Job file" << scriptFI.absoluteFilePath(); if ( !prettyNameFunc.is_none() ) @@ -337,14 +260,16 @@ PythonJob::exec() if ( m_description.isEmpty() ) { - bp::extract< std::string > entryPoint_doc_attr(entryPoint.attr( "__doc__" ) ); + bp::extract< std::string > entryPoint_doc_attr( entryPoint.attr( "__doc__" ) ); if ( entryPoint_doc_attr.check() ) { m_description = QString::fromStdString( entryPoint_doc_attr() ).trimmed(); - auto i_newline = m_description.indexOf('\n'); + auto i_newline = m_description.indexOf( '\n' ); if ( i_newline > 0 ) + { m_description.truncate( i_newline ); + } cDebug() << "Job description from __doc__" << prettyName() << "=" << m_description; emit progress( 0 ); } @@ -356,7 +281,7 @@ PythonJob::exec() { return JobResult::ok(); } - else // Something happened in the Python job + else // Something happened in the Python job { bp::tuple resultTuple = bp::extract< bp::tuple >( runResult ); QString message = QString::fromStdString( bp::extract< std::string >( resultTuple[ 0 ] ) ); @@ -374,9 +299,7 @@ PythonJob::exec() bp::handle_exception(); PyErr_Clear(); return JobResult::internalError( - tr( "Boost.Python error in job \"%1\"." ).arg( prettyName() ), - msg, - JobResult::PythonUncaughtException ); + tr( "Boost.Python error in job \"%1\"." ).arg( prettyName() ), msg, JobResult::PythonUncaughtException ); } } @@ -392,10 +315,12 @@ CalamaresPython::Helper* PythonJob::helper() { auto ptr = CalamaresPython::Helper::s_instance; - if (!ptr) + if ( !ptr ) + { ptr = new CalamaresPython::Helper; + } return ptr; } -} // namespace Calamares +} // namespace Calamares diff --git a/src/libcalamares/PythonJob.h b/src/libcalamares/PythonJob.h index c3b447472..a2bdf171c 100644 --- a/src/libcalamares/PythonJob.h +++ b/src/libcalamares/PythonJob.h @@ -27,9 +27,10 @@ namespace CalamaresPython { class PythonJobInterface; class Helper; -} +} // namespace CalamaresPython -namespace Calamares { +namespace Calamares +{ class PythonJob : public Job { @@ -57,6 +58,6 @@ private: QVariantMap m_configurationMap; }; -} // namespace Calamares +} // namespace Calamares -#endif // CALAMARES_PYTHONJOB_H +#endif // CALAMARES_PYTHONJOB_H diff --git a/src/libcalamares/PythonJobApi.cpp b/src/libcalamares/PythonJobApi.cpp index 750d8ea73..610003492 100644 --- a/src/libcalamares/PythonJobApi.cpp +++ b/src/libcalamares/PythonJobApi.cpp @@ -20,8 +20,8 @@ #include "PythonJobApi.h" #include "PythonHelper.h" -#include "utils/Logger.h" #include "utils/CalamaresUtilsSystem.h" +#include "utils/Logger.h" #include "utils/String.h" #include "GlobalStorage.h" @@ -40,15 +40,19 @@ static int _handle_check_target_env_call_error( const CalamaresUtils::ProcessResult& ec, const QString& cmd ) { if ( !ec.first ) + { return ec.first; + } QString raise = QString( "import subprocess\n" "e = subprocess.CalledProcessError(%1,\"%2\")\n" ) - .arg( ec.first ) - .arg( cmd ); + .arg( ec.first ) + .arg( cmd ); if ( !ec.second.isEmpty() ) - raise.append( QStringLiteral("e.output = \"\"\"%1\"\"\"\n").arg( ec.second ) ); - raise.append("raise e"); + { + raise.append( QStringLiteral( "e.output = \"\"\"%1\"\"\"\n" ).arg( ec.second ) ); + } + raise.append( "raise e" ); bp::exec( raise.toStdString().c_str() ); bp::throw_error_already_set(); return ec.first; @@ -63,11 +67,10 @@ mount( const std::string& device_path, const std::string& filesystem_name, const std::string& options ) { - return CalamaresUtils::System::instance()-> - mount( QString::fromStdString( device_path ), - QString::fromStdString( mount_point ), - QString::fromStdString( filesystem_name ), - QString::fromStdString( options ) ); + return CalamaresUtils::System::instance()->mount( QString::fromStdString( device_path ), + QString::fromStdString( mount_point ), + QString::fromStdString( filesystem_name ), + QString::fromStdString( options ) ); } @@ -77,66 +80,50 @@ _bp_list_to_qstringlist( const bp::list& args ) QStringList list; for ( int i = 0; i < bp::len( args ); ++i ) { - list.append( QString::fromStdString( - bp::extract< std::string >( args[ i ] ) ) ); + list.append( QString::fromStdString( bp::extract< std::string >( args[ i ] ) ) ); } return list; } static inline CalamaresUtils::ProcessResult -_target_env_command( - const QStringList& args, - const std::string& stdin, - int timeout ) +_target_env_command( const QStringList& args, const std::string& stdin, int timeout ) { // Since Python doesn't give us the type system for distinguishing // seconds from other integral types, massage to seconds here. - return CalamaresUtils::System::instance()-> - targetEnvCommand( args, - QString(), - QString::fromStdString( stdin ), - std::chrono::seconds( timeout ) ); + return CalamaresUtils::System::instance()->targetEnvCommand( + args, QString(), QString::fromStdString( stdin ), std::chrono::seconds( timeout ) ); } int -target_env_call( const std::string& command, - const std::string& stdin, - int timeout ) +target_env_call( const std::string& command, const std::string& stdin, int timeout ) { - return _target_env_command( - QStringList{ QString::fromStdString( command ) }, stdin, timeout ).first; + return _target_env_command( QStringList { QString::fromStdString( command ) }, stdin, timeout ).first; } int -target_env_call( const bp::list& args, - const std::string& stdin, - int timeout ) +target_env_call( const bp::list& args, const std::string& stdin, int timeout ) { - return _target_env_command( - _bp_list_to_qstringlist( args ), stdin, timeout ).first; + return _target_env_command( _bp_list_to_qstringlist( args ), stdin, timeout ).first; } int -check_target_env_call( const std::string& command, - const std::string& stdin, - int timeout ) +check_target_env_call( const std::string& command, const std::string& stdin, int timeout ) { - auto ec = _target_env_command( - QStringList{ QString::fromStdString( command ) }, stdin, timeout ); + auto ec = _target_env_command( QStringList { QString::fromStdString( command ) }, stdin, timeout ); return _handle_check_target_env_call_error( ec, QString::fromStdString( command ) ); } int -check_target_env_call( const bp::list& args, - const std::string& stdin, - int timeout ) +check_target_env_call( const bp::list& args, const std::string& stdin, int timeout ) { auto ec = _target_env_command( _bp_list_to_qstringlist( args ), stdin, timeout ); if ( !ec.first ) + { return ec.first; + } QStringList failedCmdList = _bp_list_to_qstringlist( args ); return _handle_check_target_env_call_error( ec, failedCmdList.join( ' ' ) ); @@ -144,25 +131,19 @@ check_target_env_call( const bp::list& args, std::string -check_target_env_output( const std::string& command, - const std::string& stdin, - int timeout ) +check_target_env_output( const std::string& command, const std::string& stdin, int timeout ) { - auto ec = _target_env_command( - QStringList{ QString::fromStdString( command ) }, stdin, timeout ); + auto ec = _target_env_command( QStringList { QString::fromStdString( command ) }, stdin, timeout ); _handle_check_target_env_call_error( ec, QString::fromStdString( command ) ); return ec.second.toStdString(); } std::string -check_target_env_output( const bp::list& args, - const std::string& stdin, - int timeout ) +check_target_env_output( const bp::list& args, const std::string& stdin, int timeout ) { QStringList list = _bp_list_to_qstringlist( args ); - auto ec = _target_env_command( - list, stdin, timeout ); + auto ec = _target_env_command( list, stdin, timeout ); _handle_check_target_env_call_error( ec, list.join( ' ' ) ); return ec.second.toStdString(); } @@ -194,7 +175,9 @@ void PythonJobInterface::setprogress( qreal progress ) { if ( progress >= 0 && progress <= 1 ) + { m_parent->emitProgress( progress ); + } } @@ -216,7 +199,8 @@ _gettext_languages() // own GlobalStoragePythonWrapper, which then holds a // GlobalStorage object for all of Python. Calamares::JobQueue* jq = Calamares::JobQueue::instance(); - Calamares::GlobalStorage* gs = jq ? jq->globalStorage() : CalamaresPython::GlobalStoragePythonWrapper::globalStorageInstance(); + Calamares::GlobalStorage* gs + = jq ? jq->globalStorage() : CalamaresPython::GlobalStoragePythonWrapper::globalStorageInstance(); QVariant localeConf_ = gs->value( "localeConf" ); if ( localeConf_.canConvert< QVariantMap >() ) @@ -246,7 +230,9 @@ gettext_languages() { bp::list pyList; for ( auto lang : _gettext_languages() ) + { pyList.append( lang.toStdString() ); + } return pyList; } @@ -257,7 +243,9 @@ _add_localedirs( QStringList& pathList, const QString& candidate ) { pathList.prepend( candidate ); if ( QDir( candidate ).cd( "lang" ) ) + { pathList.prepend( candidate + "/lang" ); + } } } @@ -266,16 +254,19 @@ gettext_path() { // TODO: distinguish between -d runs and normal runs // TODO: can we detect DESTDIR-installs? - QStringList candidatePaths = QStandardPaths::locateAll( QStandardPaths::GenericDataLocation, "locale", QStandardPaths::LocateDirectory ); + QStringList candidatePaths + = QStandardPaths::locateAll( QStandardPaths::GenericDataLocation, "locale", QStandardPaths::LocateDirectory ); QString extra = QCoreApplication::applicationDirPath(); - _add_localedirs( candidatePaths, extra ); // Often /usr/local/bin + _add_localedirs( candidatePaths, extra ); // Often /usr/local/bin if ( !extra.isEmpty() ) { QDir d( extra ); - if ( d.cd( "../share/locale" ) ) // Often /usr/local/bin/../share/locale -> /usr/local/share/locale + if ( d.cd( "../share/locale" ) ) // Often /usr/local/bin/../share/locale -> /usr/local/share/locale + { _add_localedirs( candidatePaths, d.canonicalPath() ); + } } - _add_localedirs( candidatePaths, QDir().canonicalPath() ); // . + _add_localedirs( candidatePaths, QDir().canonicalPath() ); // . cDebug() << "Determining gettext path from" << candidatePaths; @@ -296,4 +287,4 @@ gettext_path() } -} +} // namespace CalamaresPython diff --git a/src/libcalamares/PythonJobApi.h b/src/libcalamares/PythonJobApi.h index a19a0581b..3d3783f5f 100644 --- a/src/libcalamares/PythonJobApi.h +++ b/src/libcalamares/PythonJobApi.h @@ -35,29 +35,19 @@ int mount( const std::string& device_path, const std::string& filesystem_name = std::string(), const std::string& options = std::string() ); -int target_env_call( const std::string& command, - const std::string& stdin = std::string(), - int timeout = 0 ); +int target_env_call( const std::string& command, const std::string& stdin = std::string(), int timeout = 0 ); -int target_env_call( const boost::python::list& args, - const std::string& stdin = std::string(), - int timeout = 0 ); +int target_env_call( const boost::python::list& args, const std::string& stdin = std::string(), int timeout = 0 ); -int check_target_env_call( const std::string& command, - const std::string& stdin = std::string(), - int timeout = 0 ); +int check_target_env_call( const std::string& command, const std::string& stdin = std::string(), int timeout = 0 ); -int check_target_env_call( const boost::python::list& args, - const std::string& stdin = std::string(), - int timeout = 0 ); +int check_target_env_call( const boost::python::list& args, const std::string& stdin = std::string(), int timeout = 0 ); -std::string check_target_env_output( const std::string& command, - const std::string& stdin = std::string(), - int timeout = 0 ); +std::string +check_target_env_output( const std::string& command, const std::string& stdin = std::string(), int timeout = 0 ); -std::string check_target_env_output( const boost::python::list& args, - const std::string& stdin = std::string(), - int timeout = 0 ); +std::string +check_target_env_output( const boost::python::list& args, const std::string& stdin = std::string(), int timeout = 0 ); std::string obscure( const std::string& string ); @@ -85,6 +75,6 @@ private: Calamares::PythonJob* m_parent; }; -} +} // namespace CalamaresPython -#endif // PYTHONJOBAPI_H +#endif // PYTHONJOBAPI_H diff --git a/src/libcalamares/Settings.cpp b/src/libcalamares/Settings.cpp index 71825b1e5..b55292bd4 100644 --- a/src/libcalamares/Settings.cpp +++ b/src/libcalamares/Settings.cpp @@ -40,8 +40,10 @@ static QString requireString( const YAML::Node& config, const char* key ) { auto v = config[ key ]; - if ( hasValue(v) ) + if ( hasValue( v ) ) + { return QString::fromStdString( v.as< std::string >() ); + } else { cWarning() << Logger::SubEntry << "Required settings.conf key" << key << "is missing."; @@ -54,8 +56,10 @@ static bool requireBool( const YAML::Node& config, const char* key, bool d ) { auto v = config[ key ]; - if ( hasValue(v) ) + if ( hasValue( v ) ) + { return v.as< bool >(); + } else { cWarning() << Logger::SubEntry << "Required settings.conf key" << key << "is missing."; @@ -86,17 +90,17 @@ interpretModulesSearch( const bool debugMode, const QStringList& rawPaths, QStri // module search path in the build dir. if ( debugMode ) { - QString buildDirModules = QDir::current().absolutePath() + - QDir::separator() + "src" + - QDir::separator() + "modules"; + QString buildDirModules + = QDir::current().absolutePath() + QDir::separator() + "src" + QDir::separator() + "modules"; if ( QDir( buildDirModules ).exists() ) + { output.append( buildDirModules ); + } } // Install path is set in CalamaresAddPlugin.cmake - output.append( CalamaresUtils::systemLibDir().absolutePath() + - QDir::separator() + "calamares" + - QDir::separator() + "modules" ); + output.append( CalamaresUtils::systemLibDir().absolutePath() + QDir::separator() + "calamares" + + QDir::separator() + "modules" ); } else { @@ -106,7 +110,9 @@ interpretModulesSearch( const bool debugMode, const QStringList& rawPaths, QStri output.append( d.absolutePath() ); } else + { cDebug() << Logger::SubEntry << "module-search entry non-existent" << path; + } } } } @@ -124,15 +130,17 @@ interpretInstances( const YAML::Node& node, Settings::InstanceDescriptionList& c for ( const QVariant& instancesVListItem : instances ) { if ( instancesVListItem.type() != QVariant::Map ) + { continue; - QVariantMap instancesVListItemMap = - instancesVListItem.toMap(); + } + QVariantMap instancesVListItemMap = instancesVListItem.toMap(); Settings::InstanceDescription instanceMap; - for ( auto it = instancesVListItemMap.constBegin(); - it != instancesVListItemMap.constEnd(); ++it ) + for ( auto it = instancesVListItemMap.constBegin(); it != instancesVListItemMap.constEnd(); ++it ) { if ( it.value().type() != QVariant::String ) + { continue; + } instanceMap.insert( it.key(), it.value().toString() ); } customInstances.append( instanceMap ); @@ -149,37 +157,43 @@ interpretSequence( const YAML::Node& node, Settings::ModuleSequence& moduleSeque { QVariant sequenceV = CalamaresUtils::yamlToVariant( node ); if ( !( sequenceV.type() == QVariant::List ) ) + { throw YAML::Exception( YAML::Mark(), "sequence key does not have a list-value" ); + } const auto sequence = sequenceV.toList(); for ( const QVariant& sequenceVListItem : sequence ) { if ( sequenceVListItem.type() != QVariant::Map ) + { continue; + } QString thisActionS = sequenceVListItem.toMap().firstKey(); ModuleAction thisAction; if ( thisActionS == "show" ) + { thisAction = ModuleAction::Show; + } else if ( thisActionS == "exec" ) + { thisAction = ModuleAction::Exec; + } else + { continue; + } - QStringList thisActionRoster = sequenceVListItem - .toMap() - .value( thisActionS ) - .toStringList(); - moduleSequence.append( qMakePair( thisAction, - thisActionRoster ) ); + QStringList thisActionRoster = sequenceVListItem.toMap().value( thisActionS ).toStringList(); + moduleSequence.append( qMakePair( thisAction, thisActionRoster ) ); } } else + { throw YAML::Exception( YAML::Mark(), "sequence key is missing" ); + } } -Settings::Settings( const QString& settingsFilePath, - bool debugMode, - QObject* parent ) +Settings::Settings( const QString& settingsFilePath, bool debugMode, QObject* parent ) : QObject( parent ) , m_debug( debugMode ) , m_doChroot( true ) @@ -198,7 +212,8 @@ Settings::Settings( const QString& settingsFilePath, YAML::Node config = YAML::Load( ba.constData() ); Q_ASSERT( config.IsMap() ); - interpretModulesSearch( debugMode, CalamaresUtils::yamlToStringList( config[ "modules-search" ] ), m_modulesSearchPaths ); + interpretModulesSearch( + debugMode, CalamaresUtils::yamlToStringList( config[ "modules-search" ] ), m_modulesSearchPaths ); interpretInstances( config[ "instances" ], m_customModuleInstances ); interpretSequence( config[ "sequence" ], m_modulesSequence ); @@ -283,4 +298,4 @@ Settings::disableCancelDuringExec() const } -} +} // namespace Calamares diff --git a/src/libcalamares/Settings.h b/src/libcalamares/Settings.h index a095ee567..a52eac82e 100644 --- a/src/libcalamares/Settings.h +++ b/src/libcalamares/Settings.h @@ -36,9 +36,7 @@ class DLLEXPORT Settings : public QObject { Q_OBJECT public: - explicit Settings( const QString& settingsFilePath, - bool debugMode, - QObject* parent = nullptr ); + explicit Settings( const QString& settingsFilePath, bool debugMode, QObject* parent = nullptr ); static Settings* instance(); @@ -88,6 +86,6 @@ private: bool m_disableCancelDuringExec; }; -} +} // namespace Calamares -#endif // SETTINGS_H +#endif // SETTINGS_H From 8ea4091c7b6d14e52367ef2f8bda8dfee2ec23b5 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 4 Aug 2019 22:56:41 +0200 Subject: [PATCH 096/302] [libcalamares] Add a TranslatedString class to locale/ - While QObject::tr and gettext give us translations **most** of the time via the translation mechanism, we sometimes have strings embedded in configuration files that need to be shown to people as well. Follow the .desktop style in handling this. - A key's value **might** be translated; use `key[lang]` for the translation into one of the languages that Calamares understands. Code that expects a translated (human-readable) string in a configuration file can use TranslatedString to collect all the translations of a given key, so that it displays the right string from the configuration when needed. --- src/libcalamares/CMakeLists.txt | 1 + .../locale/TranslatableConfiguration.cpp | 67 +++++++++++++++++++ .../locale/TranslatableConfiguration.h | 54 +++++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 src/libcalamares/locale/TranslatableConfiguration.cpp create mode 100644 src/libcalamares/locale/TranslatableConfiguration.h diff --git a/src/libcalamares/CMakeLists.txt b/src/libcalamares/CMakeLists.txt index 19bcc921d..0aca79233 100644 --- a/src/libcalamares/CMakeLists.txt +++ b/src/libcalamares/CMakeLists.txt @@ -34,6 +34,7 @@ set( libSources locale/Label.cpp locale/LabelModel.cpp locale/Lookup.cpp + locale/TranslatableConfiguration.cpp # Partition service partition/PartitionSize.cpp diff --git a/src/libcalamares/locale/TranslatableConfiguration.cpp b/src/libcalamares/locale/TranslatableConfiguration.cpp new file mode 100644 index 000000000..6d4684121 --- /dev/null +++ b/src/libcalamares/locale/TranslatableConfiguration.cpp @@ -0,0 +1,67 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 "TranslatableConfiguration.h" + +#include "LabelModel.h" + +#include "utils/Logger.h" +#include "utils/Variant.h" + +#include +#include + +namespace CalamaresUtils +{ +namespace Locale +{ +TranslatedString::TranslatedString(const QString& string) +{ + m_strings[QString()]=string; +} +TranslatedString::TranslatedString(const QVariantMap& map, const QString& key) +{ + // Get the un-decorated value for the key + QString value = CalamaresUtils::getString( map, key ); + if ( value.isEmpty() ) + { + value = key; + } + m_strings[QString()] = value; + + for ( auto it = m_strings.constKeyValueBegin(); it != m_strings.constKeyValueEnd(); ++it ) + { + QString subkey = (*it).first; + if ( subkey == key ) + { + // Already obtained, above + } + else if ( subkey.startsWith( key ) ) + { + QRegularExpressionMatch match; + if ( subkey.indexOf( QRegularExpression("\\[([a-zA-Z_@]*)\\]"), 0, &match ) > 0 ) + { + QString language = match.captured(1); + cDebug() << "Found translation" << key << '[' << language << ']'; + } + } + } +} + +} // namespace Locale +} // namespace CalamaresUtils diff --git a/src/libcalamares/locale/TranslatableConfiguration.h b/src/libcalamares/locale/TranslatableConfiguration.h new file mode 100644 index 000000000..8cc02fadd --- /dev/null +++ b/src/libcalamares/locale/TranslatableConfiguration.h @@ -0,0 +1,54 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 LOCALE_TRANSLATABLECONFIGURATION_H +#define LOCALE_TRANSLATABLECONFIGURATION_H + +#include "DllMacro.h" + +#include +#include +#include + +namespace CalamaresUtils +{ +namespace Locale +{ + /** @brief A human-readable string from a configuration file + * + * The configuration files can contain human-readable strings, + * but those need their own translations and are not supported + * by QObject::tr or anything else. + */ + class DLLEXPORT TranslatedString + { + public: + /** @brief Get all the translations connected to @p key + */ + TranslatedString( const QVariantMap& map, const QString& key ); + /** @brief Not-actually-translated string. + */ + TranslatedString( const QString& string ); + private: + // Maps locale name to human-readable string, "" is English + QMap< QString, QString > m_strings; + }; +} // namespace Locale +} // namespace CalamaresUtils + +#endif From 19ca1b3c30074db64f408c9a362e2ee4f6fa15a3 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 4 Aug 2019 23:00:03 +0200 Subject: [PATCH 097/302] [libcalamares] One missing bit of coding style --- src/libcalamares/PythonJob.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libcalamares/PythonJob.cpp b/src/libcalamares/PythonJob.cpp index da87b8b00..39f500194 100644 --- a/src/libcalamares/PythonJob.cpp +++ b/src/libcalamares/PythonJob.cpp @@ -197,7 +197,9 @@ QString PythonJob::prettyStatusMessage() const { if ( m_description.isEmpty() ) + { return tr( "Running %1 operation." ).arg( QDir( m_workingPath ).dirName() ); + } else { return m_description; From 18e2f2ae527f6c83a1bb33d0e046bc0556e33a4f Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 5 Aug 2019 17:57:32 +0200 Subject: [PATCH 098/302] [libcalamares] Add tests for new TranslatedString - Test that construction works as expected - Add count() method to TranslatedString for testing purposes. --- src/libcalamares/locale/Tests.cpp | 47 +++++++++++++++++++ src/libcalamares/locale/Tests.h | 3 ++ .../locale/TranslatableConfiguration.cpp | 5 +- .../locale/TranslatableConfiguration.h | 3 ++ 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/src/libcalamares/locale/Tests.cpp b/src/libcalamares/locale/Tests.cpp index 9e2071a31..a87de8a98 100644 --- a/src/libcalamares/locale/Tests.cpp +++ b/src/libcalamares/locale/Tests.cpp @@ -19,7 +19,10 @@ #include "Tests.h" #include "locale/LabelModel.h" +#include "locale/TranslatableConfiguration.h" + #include "utils/Logger.h" +#include "CalamaresVersion.h" #include @@ -81,3 +84,47 @@ LocaleTests::testEsperanto() QCOMPARE( QLocale( "eo" ).language(), QLocale::C ); } + +static const QStringList& +someLanguages() +{ + static QStringList languages{ "nl", "de", "da", "nb", "sr@latin", "ar", "ru" }; + return languages; + } + + + void LocaleTests::testTranslatableLanguages() +{ + QStringList availableLanguages = QString( CALAMARES_TRANSLATION_LANGUAGES ).split( ';' ); + cDebug() << "Translation languages:" << availableLanguages; + for ( const auto& language: someLanguages() ) + { + // Could be QVERIFY, but then we don't see what language code fails + QCOMPARE( availableLanguages.contains( language ) ? language : QString(), language ); + } +} + +void LocaleTests::testTranslatableConfig1() +{ + CalamaresUtils::Locale::TranslatedString ts1( "Hello" ); + QCOMPARE( ts1.count(), 1 ); + + QVariantMap map; + map.insert( "description", "description (no language)" ); + CalamaresUtils::Locale::TranslatedString ts2(map, "description"); + QCOMPARE( ts2.count(), 1 ); +} + +void LocaleTests::testTranslatableConfig2() +{ + QVariantMap map; + + for ( const auto& language: someLanguages() ) + { + map.insert( QString("description[%1]").arg(language), QString("description (language %1)").arg(language) ); + } + + CalamaresUtils::Locale::TranslatedString s(map, "description"); + // The +1 is because "" is always also inserted + QCOMPARE( s.count(), someLanguages().count()+1 ); +} diff --git a/src/libcalamares/locale/Tests.h b/src/libcalamares/locale/Tests.h index be712388f..c6949f3e4 100644 --- a/src/libcalamares/locale/Tests.h +++ b/src/libcalamares/locale/Tests.h @@ -33,6 +33,9 @@ private Q_SLOTS: void testLanguageModelCount(); void testEsperanto(); + void testTranslatableLanguages(); + void testTranslatableConfig1(); + void testTranslatableConfig2(); }; #endif diff --git a/src/libcalamares/locale/TranslatableConfiguration.cpp b/src/libcalamares/locale/TranslatableConfiguration.cpp index 6d4684121..d6c078303 100644 --- a/src/libcalamares/locale/TranslatableConfiguration.cpp +++ b/src/libcalamares/locale/TranslatableConfiguration.cpp @@ -44,7 +44,7 @@ TranslatedString::TranslatedString(const QVariantMap& map, const QString& key) } m_strings[QString()] = value; - for ( auto it = m_strings.constKeyValueBegin(); it != m_strings.constKeyValueEnd(); ++it ) + for ( auto it = map.constKeyValueBegin(); it != map.constKeyValueEnd(); ++it ) { QString subkey = (*it).first; if ( subkey == key ) @@ -53,11 +53,12 @@ TranslatedString::TranslatedString(const QVariantMap& map, const QString& key) } else if ( subkey.startsWith( key ) ) { + cDebug() << "Checking" << subkey; QRegularExpressionMatch match; if ( subkey.indexOf( QRegularExpression("\\[([a-zA-Z_@]*)\\]"), 0, &match ) > 0 ) { QString language = match.captured(1); - cDebug() << "Found translation" << key << '[' << language << ']'; + m_strings[language] = (*it).second.toString(); } } } diff --git a/src/libcalamares/locale/TranslatableConfiguration.h b/src/libcalamares/locale/TranslatableConfiguration.h index 8cc02fadd..01bdf8ed6 100644 --- a/src/libcalamares/locale/TranslatableConfiguration.h +++ b/src/libcalamares/locale/TranslatableConfiguration.h @@ -44,6 +44,9 @@ namespace Locale /** @brief Not-actually-translated string. */ TranslatedString( const QString& string ); + + int count() const { return m_strings.count(); } + private: // Maps locale name to human-readable string, "" is English QMap< QString, QString > m_strings; From 83df41ef069cf58a3d32b1645d009be3e9a9d990 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 5 Aug 2019 18:24:31 +0200 Subject: [PATCH 099/302] CMake: bump required CMake to 3.3, enable Esperanto - Require CMake 3.3 for the IN_LIST operator in if() statements - It looks like Qt 5.12.2 (possibly earlier) supports a QLocale("eo") so enable Esperanto if that Qt version or later is detected. --- CMakeLists.txt | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 153def42a..e38c1db9b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,7 +35,7 @@ # One special target is "show-version", which can be built # to obtain the version number from here. -cmake_minimum_required( VERSION 3.2 FATAL_ERROR ) +cmake_minimum_required( VERSION 3.3 FATAL_ERROR ) project( CALAMARES VERSION 3.2.12 LANGUAGES C CXX ) @@ -96,10 +96,10 @@ set( CALAMARES_DESCRIPTION_SUMMARY # (sr@latin in particular) may need special handling in CalamaresUtils.cpp. # # TODO: drop the es_ES translation from Transifex -# TODO: move eo (Esperanto) to _ok once Qt can actually create a -# locale for it. # -# NOTE: when updating the list from Transifex, copy these four lines +# NOTE: move eo (Esperanto) to _ok once Qt can actually create a +# locale for it. (Qt 5.12.2 can, see check later on). +# NOTE: update these lines by running txstats.py, or copy these four lines # and prefix each variable name with "p", so that the automatic # checks for new languages and misspelled ones are done (that is, # copy these four lines to four backup lines, add "p", and then update @@ -128,6 +128,10 @@ set( BOOSTPYTHON_VERSION 1.55.0 ) # set( CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeModules" ) +# Enable IN_LIST +if( POLICY CMP0057 ) + cmake_policy( SET CMP0057 NEW ) +endif() # CMake 3.9, 3.10 compatibility if( POLICY CMP0071 ) cmake_policy( SET CMP0071 NEW ) @@ -249,6 +253,15 @@ include( CMakeColors ) ### DEPENDENCIES # find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED Concurrent Core Gui Widgets LinguistTools Svg Quick QuickWidgets ) +if( Qt5_VERSION VERSION_GREATER 5.12.1 ) + # At least Qt 5.12.2 seems to support Esperanto in QLocale + if( "eo" IN_LIST _tx_incomplete ) + message(STATUS "Esperanto support since Qt 5.12.2, enabling Esperanto locale") + list( REMOVE_ITEM _tx_incomplete "eo" ) + list( APPEND _tx_ok "eo" ) + endif() +endif() + find_package( YAMLCPP ${YAMLCPP_VERSION} REQUIRED ) if( INSTALL_POLKIT ) find_package( PolkitQt5-1 REQUIRED ) From 5d6ccfe8fcd8be77fd43de798ff0963066c5efcf Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 5 Aug 2019 18:30:50 +0200 Subject: [PATCH 100/302] [libcalamares] Adjust tests for new Esperanto support --- src/libcalamares/locale/Tests.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libcalamares/locale/Tests.cpp b/src/libcalamares/locale/Tests.cpp index 9e2071a31..166154fbb 100644 --- a/src/libcalamares/locale/Tests.cpp +++ b/src/libcalamares/locale/Tests.cpp @@ -78,6 +78,9 @@ LocaleTests::testEsperanto() QVERIFY( locale.language() == QLocale::Lithuanian ? locale.country() == QLocale::Lithuania : true ); QVERIFY( locale.language() != QLocale::C ); } - +#if QT_VERSION < QT_VERSION_CHECK( 5, 12, 2 ) QCOMPARE( QLocale( "eo" ).language(), QLocale::C ); +#else + QCOMPARE( QLocale( "eo" ).language(), QLocale::Esperanto ); +#endif } From 28293ef77a607d3b694e8d86b0dffbca9f0d1827 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 5 Aug 2019 23:30:51 +0200 Subject: [PATCH 101/302] [libcalamares] Expand tests of TranslatableString --- src/libcalamares/locale/Tests.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/libcalamares/locale/Tests.cpp b/src/libcalamares/locale/Tests.cpp index a87de8a98..46b1df150 100644 --- a/src/libcalamares/locale/Tests.cpp +++ b/src/libcalamares/locale/Tests.cpp @@ -122,9 +122,17 @@ void LocaleTests::testTranslatableConfig2() for ( const auto& language: someLanguages() ) { map.insert( QString("description[%1]").arg(language), QString("description (language %1)").arg(language) ); + if ( language != "nl" ) + { + map.insert( QString("name[%1]").arg(language), QString("name (language %1)").arg(language) ); + } } - CalamaresUtils::Locale::TranslatedString s(map, "description"); + CalamaresUtils::Locale::TranslatedString ts1(map, "description"); // The +1 is because "" is always also inserted - QCOMPARE( s.count(), someLanguages().count()+1 ); + QCOMPARE( ts1.count(), someLanguages().count()+1 ); + + CalamaresUtils::Locale::TranslatedString ts2(map, "name"); + // We skipped dutch this time + QCOMPARE( ts2.count(), someLanguages().count() ); } From e0edd1f3e2bc57f826acd9b9713110dacbd107be Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 5 Aug 2019 23:32:13 +0200 Subject: [PATCH 102/302] [libcalamares] Fix misleading comment, add accessor - the sort order is not English-at-the-top - add accessor for the locale ID. --- src/libcalamares/locale/Label.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libcalamares/locale/Label.h b/src/libcalamares/locale/Label.h index ab3e80ad0..0fe61d909 100644 --- a/src/libcalamares/locale/Label.h +++ b/src/libcalamares/locale/Label.h @@ -58,7 +58,7 @@ public: /** @brief Define a sorting order. * - * English (@see isEnglish() -- it means en_US) is sorted at the top. + * Locales are sorted by their id, which means the ISO 2-letter code + country. */ bool operator<( const Label& other ) const { return m_localeId < other.m_localeId; } @@ -78,6 +78,7 @@ public: QLocale locale() const { return m_locale; } QString name() const { return m_locale.name(); } + QString id() const { return m_localeId; } /// @brief Convenience accessor to the language part of the locale QLocale::Language language() const { return m_locale.language(); } From 50d74c4eca3e919b9bd7f769d2381e3f4432ccc0 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 5 Aug 2019 23:37:25 +0200 Subject: [PATCH 103/302] [libcalamares] Add get() to the string - Look up the translation of the requested string with the current or a specific locale. This implementation is a stub. - Add tests for the getter. --- src/libcalamares/locale/Tests.cpp | 9 +++++++++ .../locale/TranslatableConfiguration.cpp | 13 ++++++++++++- src/libcalamares/locale/TranslatableConfiguration.h | 6 ++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/libcalamares/locale/Tests.cpp b/src/libcalamares/locale/Tests.cpp index 46b1df150..1cfd733a0 100644 --- a/src/libcalamares/locale/Tests.cpp +++ b/src/libcalamares/locale/Tests.cpp @@ -109,10 +109,16 @@ void LocaleTests::testTranslatableConfig1() CalamaresUtils::Locale::TranslatedString ts1( "Hello" ); QCOMPARE( ts1.count(), 1 ); + QCOMPARE( ts1.get(), "Hello" ); + QCOMPARE( ts1.get( QLocale("nl")), "Hello" ); + QVariantMap map; map.insert( "description", "description (no language)" ); CalamaresUtils::Locale::TranslatedString ts2(map, "description"); QCOMPARE( ts2.count(), 1 ); + + QCOMPARE( ts2.get(), "description (no language)"); + QCOMPARE( ts2.get( QLocale( "nl" ) ), "description (no language)"); } void LocaleTests::testTranslatableConfig2() @@ -131,6 +137,9 @@ void LocaleTests::testTranslatableConfig2() CalamaresUtils::Locale::TranslatedString ts1(map, "description"); // The +1 is because "" is always also inserted QCOMPARE( ts1.count(), someLanguages().count()+1 ); + + QCOMPARE( ts1.get(), "description"); // it wasn't set + QCOMPARE( ts1.get( QLocale( "nl" ) ), "description (language nl)"); CalamaresUtils::Locale::TranslatedString ts2(map, "name"); // We skipped dutch this time diff --git a/src/libcalamares/locale/TranslatableConfiguration.cpp b/src/libcalamares/locale/TranslatableConfiguration.cpp index d6c078303..d7066a57c 100644 --- a/src/libcalamares/locale/TranslatableConfiguration.cpp +++ b/src/libcalamares/locale/TranslatableConfiguration.cpp @@ -53,7 +53,6 @@ TranslatedString::TranslatedString(const QVariantMap& map, const QString& key) } else if ( subkey.startsWith( key ) ) { - cDebug() << "Checking" << subkey; QRegularExpressionMatch match; if ( subkey.indexOf( QRegularExpression("\\[([a-zA-Z_@]*)\\]"), 0, &match ) > 0 ) { @@ -64,5 +63,17 @@ TranslatedString::TranslatedString(const QVariantMap& map, const QString& key) } } +QString TranslatedString::get() const +{ + return get( QLocale() ); +} + +QString TranslatedString::get(const QLocale& locale) const +{ + cDebug() << "Getting locale" << locale.name(); + return m_strings[QString()]; +} + + } // namespace Locale } // namespace CalamaresUtils diff --git a/src/libcalamares/locale/TranslatableConfiguration.h b/src/libcalamares/locale/TranslatableConfiguration.h index 01bdf8ed6..b5a18ee73 100644 --- a/src/libcalamares/locale/TranslatableConfiguration.h +++ b/src/libcalamares/locale/TranslatableConfiguration.h @@ -47,6 +47,12 @@ namespace Locale int count() const { return m_strings.count(); } + /// @brief Gets the string in the current locale + QString get() const; + + /// @brief Gets the string from the given locale + QString get(const QLocale&) const; + private: // Maps locale name to human-readable string, "" is English QMap< QString, QString > m_strings; From a9292d0c75316d2956ea70df0ce0aae7222c583f Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 5 Aug 2019 23:54:53 +0200 Subject: [PATCH 104/302] [libcalamares] Implement getting the string --- src/libcalamares/locale/Tests.cpp | 58 ++++++++++--------- .../locale/TranslatableConfiguration.cpp | 53 ++++++++++++----- .../locale/TranslatableConfiguration.h | 54 ++++++++--------- 3 files changed, 98 insertions(+), 67 deletions(-) diff --git a/src/libcalamares/locale/Tests.cpp b/src/libcalamares/locale/Tests.cpp index 1cfd733a0..6f8310233 100644 --- a/src/libcalamares/locale/Tests.cpp +++ b/src/libcalamares/locale/Tests.cpp @@ -21,8 +21,8 @@ #include "locale/LabelModel.h" #include "locale/TranslatableConfiguration.h" -#include "utils/Logger.h" #include "CalamaresVersion.h" +#include "utils/Logger.h" #include @@ -88,60 +88,64 @@ LocaleTests::testEsperanto() static const QStringList& someLanguages() { - static QStringList languages{ "nl", "de", "da", "nb", "sr@latin", "ar", "ru" }; + static QStringList languages { "nl", "de", "da", "nb", "sr@latin", "ar", "ru" }; return languages; - } +} - - void LocaleTests::testTranslatableLanguages() + +void +LocaleTests::testTranslatableLanguages() { QStringList availableLanguages = QString( CALAMARES_TRANSLATION_LANGUAGES ).split( ';' ); cDebug() << "Translation languages:" << availableLanguages; - for ( const auto& language: someLanguages() ) + for ( const auto& language : someLanguages() ) { // Could be QVERIFY, but then we don't see what language code fails QCOMPARE( availableLanguages.contains( language ) ? language : QString(), language ); } } -void LocaleTests::testTranslatableConfig1() +void +LocaleTests::testTranslatableConfig1() { CalamaresUtils::Locale::TranslatedString ts1( "Hello" ); QCOMPARE( ts1.count(), 1 ); - + QCOMPARE( ts1.get(), "Hello" ); - QCOMPARE( ts1.get( QLocale("nl")), "Hello" ); - + QCOMPARE( ts1.get( QLocale( "nl" ) ), "Hello" ); + QVariantMap map; map.insert( "description", "description (no language)" ); - CalamaresUtils::Locale::TranslatedString ts2(map, "description"); + CalamaresUtils::Locale::TranslatedString ts2( map, "description" ); QCOMPARE( ts2.count(), 1 ); - - QCOMPARE( ts2.get(), "description (no language)"); - QCOMPARE( ts2.get( QLocale( "nl" ) ), "description (no language)"); + + QCOMPARE( ts2.get(), "description (no language)" ); + QCOMPARE( ts2.get( QLocale( "nl" ) ), "description (no language)" ); } -void LocaleTests::testTranslatableConfig2() +void +LocaleTests::testTranslatableConfig2() { QVariantMap map; - - for ( const auto& language: someLanguages() ) + + for ( const auto& language : someLanguages() ) { - map.insert( QString("description[%1]").arg(language), QString("description (language %1)").arg(language) ); + map.insert( QString( "description[%1]" ).arg( language ), + QString( "description (language %1)" ).arg( language ) ); if ( language != "nl" ) { - map.insert( QString("name[%1]").arg(language), QString("name (language %1)").arg(language) ); + map.insert( QString( "name[%1]" ).arg( language ), QString( "name (language %1)" ).arg( language ) ); } } - - CalamaresUtils::Locale::TranslatedString ts1(map, "description"); - // The +1 is because "" is always also inserted - QCOMPARE( ts1.count(), someLanguages().count()+1 ); - QCOMPARE( ts1.get(), "description"); // it wasn't set - QCOMPARE( ts1.get( QLocale( "nl" ) ), "description (language nl)"); - - CalamaresUtils::Locale::TranslatedString ts2(map, "name"); + CalamaresUtils::Locale::TranslatedString ts1( map, "description" ); + // The +1 is because "" is always also inserted + QCOMPARE( ts1.count(), someLanguages().count() + 1 ); + + QCOMPARE( ts1.get(), "description" ); // it wasn't set + QCOMPARE( ts1.get( QLocale( "nl" ) ), "description (language nl)" ); + + CalamaresUtils::Locale::TranslatedString ts2( map, "name" ); // We skipped dutch this time QCOMPARE( ts2.count(), someLanguages().count() ); } diff --git a/src/libcalamares/locale/TranslatableConfiguration.cpp b/src/libcalamares/locale/TranslatableConfiguration.cpp index d7066a57c..0b4a6ff71 100644 --- a/src/libcalamares/locale/TranslatableConfiguration.cpp +++ b/src/libcalamares/locale/TranslatableConfiguration.cpp @@ -30,11 +30,11 @@ namespace CalamaresUtils { namespace Locale { -TranslatedString::TranslatedString(const QString& string) +TranslatedString::TranslatedString( const QString& string ) { - m_strings[QString()]=string; + m_strings[ QString() ] = string; } -TranslatedString::TranslatedString(const QVariantMap& map, const QString& key) +TranslatedString::TranslatedString( const QVariantMap& map, const QString& key ) { // Get the un-decorated value for the key QString value = CalamaresUtils::getString( map, key ); @@ -42,11 +42,11 @@ TranslatedString::TranslatedString(const QVariantMap& map, const QString& key) { value = key; } - m_strings[QString()] = value; - + m_strings[ QString() ] = value; + for ( auto it = map.constKeyValueBegin(); it != map.constKeyValueEnd(); ++it ) { - QString subkey = (*it).first; + QString subkey = ( *it ).first; if ( subkey == key ) { // Already obtained, above @@ -54,24 +54,51 @@ TranslatedString::TranslatedString(const QVariantMap& map, const QString& key) else if ( subkey.startsWith( key ) ) { QRegularExpressionMatch match; - if ( subkey.indexOf( QRegularExpression("\\[([a-zA-Z_@]*)\\]"), 0, &match ) > 0 ) + if ( subkey.indexOf( QRegularExpression( "\\[([a-zA-Z_@]*)\\]" ), 0, &match ) > 0 ) { - QString language = match.captured(1); - m_strings[language] = (*it).second.toString(); + QString language = match.captured( 1 ); + m_strings[ language ] = ( *it ).second.toString(); } } } } -QString TranslatedString::get() const +QString +TranslatedString::get() const { return get( QLocale() ); } -QString TranslatedString::get(const QLocale& locale) const +QString +TranslatedString::get( const QLocale& locale ) const { - cDebug() << "Getting locale" << locale.name(); - return m_strings[QString()]; + QString localeName = locale.name(); + cDebug() << "Getting locale" << localeName; + if ( m_strings.contains( localeName ) ) + { + return m_strings[ localeName ]; + } + int index = localeName.indexOf( '@' ); + if ( index > 0 ) + { + localeName.truncate( index ); + if ( m_strings.contains( localeName ) ) + { + return m_strings[ localeName ]; + } + } + + index = localeName.indexOf( '_' ); + if ( index > 0 ) + { + localeName.truncate( index ); + if ( m_strings.contains( localeName ) ) + { + return m_strings[ localeName ]; + } + } + + return m_strings[ QString() ]; } diff --git a/src/libcalamares/locale/TranslatableConfiguration.h b/src/libcalamares/locale/TranslatableConfiguration.h index b5a18ee73..0735a2274 100644 --- a/src/libcalamares/locale/TranslatableConfiguration.h +++ b/src/libcalamares/locale/TranslatableConfiguration.h @@ -29,34 +29,34 @@ namespace CalamaresUtils { namespace Locale { - /** @brief A human-readable string from a configuration file - * - * The configuration files can contain human-readable strings, - * but those need their own translations and are not supported - * by QObject::tr or anything else. +/** @brief A human-readable string from a configuration file + * + * The configuration files can contain human-readable strings, + * but those need their own translations and are not supported + * by QObject::tr or anything else. + */ +class DLLEXPORT TranslatedString +{ +public: + /** @brief Get all the translations connected to @p key */ - class DLLEXPORT TranslatedString - { - public: - /** @brief Get all the translations connected to @p key - */ - TranslatedString( const QVariantMap& map, const QString& key ); - /** @brief Not-actually-translated string. - */ - TranslatedString( const QString& string ); - - int count() const { return m_strings.count(); } - - /// @brief Gets the string in the current locale - QString get() const; - - /// @brief Gets the string from the given locale - QString get(const QLocale&) const; - - private: - // Maps locale name to human-readable string, "" is English - QMap< QString, QString > m_strings; - }; + TranslatedString( const QVariantMap& map, const QString& key ); + /** @brief Not-actually-translated string. + */ + TranslatedString( const QString& string ); + + int count() const { return m_strings.count(); } + + /// @brief Gets the string in the current locale + QString get() const; + + /// @brief Gets the string from the given locale + QString get( const QLocale& ) const; + +private: + // Maps locale name to human-readable string, "" is English + QMap< QString, QString > m_strings; +}; } // namespace Locale } // namespace CalamaresUtils From 764c775f08e77a3eb66209edc2a6bb1e54dafa77 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 00:05:24 +0200 Subject: [PATCH 105/302] [libcalamares] Tighten tests, add special case - The tests should be run in C locale, otherwise the plain get() function uses the current locale, which will fail (e.g. running LANG=nl ./libcalamareslocaletest returns the Dutch strings for plain get, which isn't what we expect). - sr@latin is still special. --- src/libcalamares/locale/Tests.cpp | 16 ++++++++++++++++ .../locale/TranslatableConfiguration.cpp | 6 ++++++ 2 files changed, 22 insertions(+) diff --git a/src/libcalamares/locale/Tests.cpp b/src/libcalamares/locale/Tests.cpp index 6f8310233..241d66bbd 100644 --- a/src/libcalamares/locale/Tests.cpp +++ b/src/libcalamares/locale/Tests.cpp @@ -108,6 +108,7 @@ LocaleTests::testTranslatableLanguages() void LocaleTests::testTranslatableConfig1() { + QCOMPARE( QLocale().name(), "C" ); // Otherwise plain get() is dubious CalamaresUtils::Locale::TranslatedString ts1( "Hello" ); QCOMPARE( ts1.count(), 1 ); @@ -126,6 +127,7 @@ LocaleTests::testTranslatableConfig1() void LocaleTests::testTranslatableConfig2() { + QCOMPARE( QLocale().name(), "C" ); // Otherwise plain get() is dubious QVariantMap map; for ( const auto& language : someLanguages() ) @@ -144,6 +146,20 @@ LocaleTests::testTranslatableConfig2() QCOMPARE( ts1.get(), "description" ); // it wasn't set QCOMPARE( ts1.get( QLocale( "nl" ) ), "description (language nl)" ); + for ( const auto& language : someLanguages() ) + { + // Skip Serbian (latin) because QLocale() constructed with it + // doesn't retain the @latin part. + if ( language == "sr@latin" ) + { + continue; + } + // Could be QVERIFY, but then we don't see what language code fails + QCOMPARE( ts1.get( language ) == QString( "description (language %1)" ).arg( language ) ? language : QString(), + language ); + } + QCOMPARE( ts1.get( QLocale( QLocale::Language::Serbian, QLocale::Script::LatinScript, QLocale::Country::Serbia ) ), + "description (language sr@latin)" ); CalamaresUtils::Locale::TranslatedString ts2( map, "name" ); // We skipped dutch this time diff --git a/src/libcalamares/locale/TranslatableConfiguration.cpp b/src/libcalamares/locale/TranslatableConfiguration.cpp index 0b4a6ff71..82923a5fa 100644 --- a/src/libcalamares/locale/TranslatableConfiguration.cpp +++ b/src/libcalamares/locale/TranslatableConfiguration.cpp @@ -73,6 +73,12 @@ QString TranslatedString::get( const QLocale& locale ) const { QString localeName = locale.name(); + // Special case, sr@latin doesn't have the @latin reflected in the name + if ( locale.language() == QLocale::Language::Serbian && locale.script() == QLocale::Script::LatinScript ) + { + localeName = QStringLiteral( "sr@latin" ); + } + cDebug() << "Getting locale" << localeName; if ( m_strings.contains( localeName ) ) { From fd75b3378418efd3106d8b6b874b3fef96447454 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 00:17:30 +0200 Subject: [PATCH 106/302] [libcalamares] Add default constructor to TranslatedString --- src/libcalamares/locale/TranslatableConfiguration.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libcalamares/locale/TranslatableConfiguration.h b/src/libcalamares/locale/TranslatableConfiguration.h index 0735a2274..b2f598069 100644 --- a/src/libcalamares/locale/TranslatableConfiguration.h +++ b/src/libcalamares/locale/TranslatableConfiguration.h @@ -44,6 +44,9 @@ public: /** @brief Not-actually-translated string. */ TranslatedString( const QString& string ); + /// @brief Empty string + TranslatedString() + : TranslatedString( QString() ) {} int count() const { return m_strings.count(); } From 56db9e93412c897bc86be85b2c99ab5379617360 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 00:17:50 +0200 Subject: [PATCH 107/302] [packagechooser] Use translated strings --- src/modules/packagechooser/PackageChooserPage.cpp | 4 ++-- src/modules/packagechooser/PackageModel.cpp | 4 ++-- src/modules/packagechooser/PackageModel.h | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index 60becf64f..0587af190 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -54,9 +54,9 @@ PackageChooserPage::currentChanged( const QModelIndex& index ) { if ( !index.isValid() || !ui->products->selectionModel()->hasSelection() ) { - ui->productName->setText( m_introduction.name ); + ui->productName->setText( m_introduction.name.get() ); ui->productScreenshot->setPixmap( m_introduction.screenshot ); - ui->productDescription->setText( m_introduction.description ); + ui->productDescription->setText( m_introduction.description.get() ); } else { diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index aa8dd39fc..f133f4fbd 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -118,11 +118,11 @@ PackageListModel::data( const QModelIndex& index, int role ) const if ( role == Qt::DisplayRole /* Also PackageNameRole */ ) { - return m_packages[ row ].name; + return m_packages[ row ].name.get(); } else if ( role == DescriptionRole ) { - return m_packages[ row ].description; + return m_packages[ row ].description.get(); } else if ( role == ScreenshotRole ) { diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index 7f8fff8ec..68e19a25d 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -19,6 +19,7 @@ #ifndef PACKAGEMODEL_H #define PACKAGEMODEL_H +#include "locale/TranslatableConfiguration.h" #include "utils/NamedEnum.h" #include @@ -41,9 +42,8 @@ struct PackageItem QString id; // TODO: may need more than one QString package; - // TODO: name and description are localized - QString name; - QString description; + CalamaresUtils::Locale::TranslatedString name; + CalamaresUtils::Locale::TranslatedString description; // TODO: may be more than one QPixmap screenshot; From fee2297e67639cdcd0a10f4889fec87cc747237c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 00:24:53 +0200 Subject: [PATCH 108/302] [packagechooser] Fix fallthrough situation - Add a FALLTHRU macro to annotate fallthrough situations in both Clang and GCC, - Annotate intentional fallthroughs. - Add missing break which meant that the selection mode was always multiple-selection. --- CMakeLists.txt | 4 ++-- src/modules/packagechooser/PackageChooserPage.cpp | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e38c1db9b..e28d28f38 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -198,7 +198,7 @@ if( CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) ) string( APPEND CMAKE_CXX_FLAGS " ${CLANG_WARNINGS}" ) endforeach() - set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNOTREACHED='//'" ) + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNOTREACHED='//' -DFALLTHRU='[[clang::fallthrough]]'") # Third-party code where we don't care so much about compiler warnings # (because it's uncomfortable to patch) get different flags; use @@ -225,7 +225,7 @@ else() set( SUPPRESS_3RDPARTY_WARNINGS "" ) set( SUPPRESS_BOOST_WARNINGS "" ) - set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNOTREACHED='__builtin_unreachable();'" ) + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNOTREACHED='__builtin_unreachable();' -DFALLTHRU='/* */'" ) endif() # Use mark_thirdparty_code() to reduce warnings from the compiler diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index 0587af190..6f565c914 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -41,9 +41,12 @@ PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent switch ( mode ) { case PackageChooserMode::Optional: + FALLTHRU; case PackageChooserMode::Required: ui->products->setSelectionMode( QAbstractItemView::SingleSelection ); + break; case PackageChooserMode::OptionalMultiple: + FALLTHRU; case PackageChooserMode::RequiredMultiple: ui->products->setSelectionMode( QAbstractItemView::ExtendedSelection ); } From 6a8e10837d044dc892804a5120ae4b462556f625 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 00:26:04 +0200 Subject: [PATCH 109/302] [libcalamares] Drop unneeded debugging --- src/libcalamares/locale/TranslatableConfiguration.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libcalamares/locale/TranslatableConfiguration.cpp b/src/libcalamares/locale/TranslatableConfiguration.cpp index 82923a5fa..b3b5259c9 100644 --- a/src/libcalamares/locale/TranslatableConfiguration.cpp +++ b/src/libcalamares/locale/TranslatableConfiguration.cpp @@ -79,7 +79,6 @@ TranslatedString::get( const QLocale& locale ) const localeName = QStringLiteral( "sr@latin" ); } - cDebug() << "Getting locale" << localeName; if ( m_strings.contains( localeName ) ) { return m_strings[ localeName ]; From 8d3546f0b3a4c1b8ceeb4467f8e80a2b9f8ea503 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 00:31:05 +0200 Subject: [PATCH 110/302] [packagechooser] Expand the example config with translated entries --- src/modules/packagechooser/packagechooser.conf | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/modules/packagechooser/packagechooser.conf b/src/modules/packagechooser/packagechooser.conf index 391e1f325..7d60b50a4 100644 --- a/src/modules/packagechooser/packagechooser.conf +++ b/src/modules/packagechooser/packagechooser.conf @@ -44,12 +44,14 @@ items: - id: "" package: "" name: "No Desktop" + name[nl]: "Geen desktop" description: "Please pick a desktop environment from the list. If you don't want to install a desktop, that's fine, your system will start up in text-only mode and you can install a desktop environment later." + description[nl]: "Kies eventueel een desktop-omgeving uit deze lijst. Als u geen desktop-omgeving wenst te gebruiken, kies er dan geen. In dat geval start het systeem straks op in tekst-modus en kunt u later alsnog een desktop-omgeving installeren." screenshot: ":/images/no-selection.png" - id: kde package: kde name: Plasma Desktop - description: "KDE Plasma Desktop, DERP" + description: "KDE Plasma Desktop, simple by default, a clean work area for real-world usage which intends to stay out of your way. Plasma is powerful when needed, enabling the user to create the workflow that makes them more effective to complete their tasks." screenshot: ":/images/kde.png" - id: gnome package: gnome From 4febe477cf82e1cf27f0c27a7a07822d8ba08131 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 11:53:35 +0200 Subject: [PATCH 111/302] [libcalamares] Add isEmpty() to TranslatedString - Massage the implementation a bit, don't insert a meaningless copy of the key as the untranslated message. - Add isEmpty() to check for presence of the untranslated message. - Document API. - Update tests. --- src/libcalamares/locale/Tests.cpp | 33 ++++++++++++++++++- .../locale/TranslatableConfiguration.cpp | 4 --- .../locale/TranslatableConfiguration.h | 16 ++++++++- 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/libcalamares/locale/Tests.cpp b/src/libcalamares/locale/Tests.cpp index 664390511..fa84cd2fb 100644 --- a/src/libcalamares/locale/Tests.cpp +++ b/src/libcalamares/locale/Tests.cpp @@ -96,6 +96,10 @@ someLanguages() } +/** @brief Check consistency of test data + * Check that all the languages used in testing, are actually enabled + * in Calamares translations. + */ void LocaleTests::testTranslatableLanguages() { @@ -108,12 +112,19 @@ LocaleTests::testTranslatableLanguages() } } +/** @brief Test strings with no translations + */ void LocaleTests::testTranslatableConfig1() { + CalamaresUtils::Locale::TranslatedString ts0; + QVERIFY( ts0.isEmpty() ); + QCOMPARE( ts0.count(), 1 ); // the empty string + QCOMPARE( QLocale().name(), "C" ); // Otherwise plain get() is dubious CalamaresUtils::Locale::TranslatedString ts1( "Hello" ); QCOMPARE( ts1.count(), 1 ); + QVERIFY( !ts1.isEmpty() ); QCOMPARE( ts1.get(), "Hello" ); QCOMPARE( ts1.get( QLocale( "nl" ) ), "Hello" ); @@ -122,11 +133,14 @@ LocaleTests::testTranslatableConfig1() map.insert( "description", "description (no language)" ); CalamaresUtils::Locale::TranslatedString ts2( map, "description" ); QCOMPARE( ts2.count(), 1 ); + QVERIFY( !ts2.isEmpty() ); QCOMPARE( ts2.get(), "description (no language)" ); QCOMPARE( ts2.get( QLocale( "nl" ) ), "description (no language)" ); } +/** @bref Test strings with translations. + */ void LocaleTests::testTranslatableConfig2() { @@ -143,11 +157,22 @@ LocaleTests::testTranslatableConfig2() } } + // If there's no untranslated string in the map, it is considered empty + CalamaresUtils::Locale::TranslatedString ts0( map, "description" ); + QVERIFY( ts0.isEmpty() ); // Because no untranslated string + QCOMPARE( ts0.count(), + someLanguages().count() + 1 ); // But there are entries for the translations, plus an empty string + + // expand the map with untranslated entries + map.insert( QString( "description" ), "description (no language)" ); + map.insert( QString( "name" ), "name (no language)" ); + CalamaresUtils::Locale::TranslatedString ts1( map, "description" ); // The +1 is because "" is always also inserted QCOMPARE( ts1.count(), someLanguages().count() + 1 ); + QVERIFY( !ts1.isEmpty() ); - QCOMPARE( ts1.get(), "description" ); // it wasn't set + QCOMPARE( ts1.get(), "description (no language)" ); // it wasn't set QCOMPARE( ts1.get( QLocale( "nl" ) ), "description (language nl)" ); for ( const auto& language : someLanguages() ) { @@ -167,4 +192,10 @@ LocaleTests::testTranslatableConfig2() CalamaresUtils::Locale::TranslatedString ts2( map, "name" ); // We skipped dutch this time QCOMPARE( ts2.count(), someLanguages().count() ); + QVERIFY( !ts2.isEmpty() ); + + // This key doesn't exist + CalamaresUtils::Locale::TranslatedString ts3( map, "front" ); + QVERIFY( ts3.isEmpty() ); + QCOMPARE( ts3.count(), 1 ); // The empty string } diff --git a/src/libcalamares/locale/TranslatableConfiguration.cpp b/src/libcalamares/locale/TranslatableConfiguration.cpp index b3b5259c9..7493c836c 100644 --- a/src/libcalamares/locale/TranslatableConfiguration.cpp +++ b/src/libcalamares/locale/TranslatableConfiguration.cpp @@ -38,10 +38,6 @@ TranslatedString::TranslatedString( const QVariantMap& map, const QString& key ) { // Get the un-decorated value for the key QString value = CalamaresUtils::getString( map, key ); - if ( value.isEmpty() ) - { - value = key; - } m_strings[ QString() ] = value; for ( auto it = map.constKeyValueBegin(); it != map.constKeyValueEnd(); ++it ) diff --git a/src/libcalamares/locale/TranslatableConfiguration.h b/src/libcalamares/locale/TranslatableConfiguration.h index b2f598069..a055cbfbd 100644 --- a/src/libcalamares/locale/TranslatableConfiguration.h +++ b/src/libcalamares/locale/TranslatableConfiguration.h @@ -46,9 +46,23 @@ public: TranslatedString( const QString& string ); /// @brief Empty string TranslatedString() - : TranslatedString( QString() ) {} + : TranslatedString( QString() ) + { + } + /** @brief How many strings (translations) are there? + * + * This is always at least 1 (for the untranslated string), + * but may be more than 1 even when isEmpty() is true -- + * if there is no untranslated version, for instance. + */ int count() const { return m_strings.count(); } + /** @brief Consider this string empty? + * + * Only the state of the untranslated string is considered, + * so count() may be more than 1 even while the string is empty. + */ + bool isEmpty() const { return m_strings[ QString() ].isEmpty(); } /// @brief Gets the string in the current locale QString get() const; From 6e05a1ef0550e6f8026334383fb2b46754581920 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 12:02:29 +0200 Subject: [PATCH 112/302] [packagechooser] Load translated strings as well - This makes it possible to put the translations into the config file, and have them displayed when the Calamares language changes. --- .../packagechooser/PackageChooserViewStep.cpp | 26 +------------ src/modules/packagechooser/PackageModel.cpp | 38 +++++++++++++++++-- src/modules/packagechooser/PackageModel.h | 18 +++++++++ 3 files changed, 53 insertions(+), 29 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 4476eb9e6..a3b853b39 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -232,31 +232,7 @@ PackageChooserViewStep::fillModel( const QVariantList& items ) continue; } - QString id = CalamaresUtils::getString( item_map, "id" ); - QString package = CalamaresUtils::getString( item_map, "package" ); - QString name = CalamaresUtils::getString( item_map, "name" ); - QString description = CalamaresUtils::getString( item_map, "description" ); - QString screenshot = CalamaresUtils::getString( item_map, "screenshot" ); - - if ( name.isEmpty() && id.isEmpty() ) - { - name = tr( "No product" ); - } - else if ( name.isEmpty() ) - { - cWarning() << "PackageChooser item" << id << "has an empty name."; - continue; - } - if ( description.isEmpty() ) - { - description = tr( "No description provided." ); - } - if ( screenshot.isEmpty() ) - { - screenshot = QStringLiteral( ":/images/no-selection.png" ); - } - - m_model->addPackage( PackageItem { id, package, name, description, screenshot } ); + m_model->addPackage( PackageItem( item_map ) ); } } diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index f133f4fbd..3283cbe6f 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -19,6 +19,7 @@ #include "PackageModel.h" #include "utils/Logger.h" +#include "utils/Variant.h" const NamedEnumTable< PackageChooserMode >& roleNames() @@ -73,6 +74,31 @@ PackageItem::PackageItem( const QString& a_id, { } +PackageItem::PackageItem::PackageItem( const QVariantMap& item_map ) + : id( CalamaresUtils::getString( item_map, "id" ) ) + , package( CalamaresUtils::getString( item_map, "package" ) ) + , name( CalamaresUtils::Locale::TranslatedString( item_map, "name" ) ) + , description( CalamaresUtils::Locale::TranslatedString( item_map, "description" ) ) + , screenshot( CalamaresUtils::getString( item_map, "screenshot" ) ) +{ + if ( name.isEmpty() && id.isEmpty() ) + { + name = QObject::tr( "No product" ); + } + else if ( name.isEmpty() ) + { + cWarning() << "PackageChooser item" << id << "has an empty name."; + } + if ( description.isEmpty() ) + { + description = QObject::tr( "No description provided." ); + } + if ( screenshot.isNull() ) + { + screenshot = QPixmap( QStringLiteral( ":/images/no-selection.png" ) ); + } +} + PackageListModel::PackageListModel( QObject* parent ) : QAbstractListModel( parent ) @@ -90,10 +116,14 @@ PackageListModel::~PackageListModel() {} void PackageListModel::addPackage( PackageItem&& p ) { - int c = m_packages.count(); - beginInsertRows( QModelIndex(), c, c ); - m_packages.append( p ); - endInsertRows(); + // Only add valid packages + if ( !p.name.isEmpty() ) + { + int c = m_packages.count(); + beginInsertRows( QModelIndex(), c, c ); + m_packages.append( p ); + endInsertRows(); + } } int diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index 68e19a25d..f42ff3123 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -56,12 +56,26 @@ struct PackageItem */ PackageItem( const QString& id, const QString& package, const QString& name, const QString& description ); + /** @brief Creates a PackageItem from given strings. + * + * Set all the text members and load the screenshot from the given + * @p screenshotPath, which may be a QRC path (:/path/in/qrc) or + * a filesystem path, whatever QPixmap understands. + */ PackageItem( const QString& id, const QString& package, const QString& name, const QString& description, const QString& screenshotPath ); + /** @brief Creates a PackageItem from a QVariantMap + * + * This is intended for use when loading PackageItems from a + * configuration map. It will look up the various keys in the map + * and handle translation strings as well. + */ + PackageItem( const QVariantMap& map ); + // TODO: implement this PackageItem fromAppStream( const QString& filename ); }; @@ -75,6 +89,10 @@ public: PackageListModel( QObject* parent ); virtual ~PackageListModel() override; + /** @brief Add a package @p to the model + * + * Only valid packages are added -- that is, they must have a name. + */ void addPackage( PackageItem&& p ); int rowCount( const QModelIndex& index ) const override; From 6c41151f80dcc9d41553a4f80ed4d4f6de989d88 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 12:38:28 +0200 Subject: [PATCH 113/302] [packagechooser] Just one screenshot, and mark package unused --- src/modules/packagechooser/PackageModel.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index f42ff3123..ce384096c 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -40,11 +40,10 @@ const NamedEnumTable< PackageChooserMode >& roleNames(); struct PackageItem { QString id; - // TODO: may need more than one + // FIXME: unused QString package; CalamaresUtils::Locale::TranslatedString name; CalamaresUtils::Locale::TranslatedString description; - // TODO: may be more than one QPixmap screenshot; /// @brief Create blank PackageItem From 8329d7d7dc8072d958fc460785d57f53b646acf3 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 13:34:32 +0200 Subject: [PATCH 114/302] CI: Add an AppData file --- io.calamares.calamares.appdata.xml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 io.calamares.calamares.appdata.xml diff --git a/io.calamares.calamares.appdata.xml b/io.calamares.calamares.appdata.xml new file mode 100644 index 000000000..355f485c2 --- /dev/null +++ b/io.calamares.calamares.appdata.xml @@ -0,0 +1,29 @@ + + + io.calamares.calamares.desktop + CC0-1.0 + GPL-3.0+ + Calamares + Calamares + Calamares + Calamares + Calamares Linux Installer + Calamares Linux Installer + Linux Installatieprogramma Calamares + +

Calamares is an installer program for Linux distributions.

+

Calamares is een installatieprogramma voor Linux distributies.

+
+ https://calamares.io + https://https://github.com/calamares/calamares/issues/ + https://github.com/calamares/calamares/wiki + + + Calamares Welcome + https://calamares.io/images/cal_640.png + + + + calamares + +
From beb5896fa237f3b6bf8045ee94a8fa7b0d7fcc11 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 14:33:57 +0200 Subject: [PATCH 115/302] [packagechooser] Start implementation of AppData loading - Doing a manual read of the XML, since existing appdata libraries don't seem to have a convenient entry for what I need. - Expand tests to loading AppData (currently, they fail). --- src/modules/packagechooser/CMakeLists.txt | 15 +++++ src/modules/packagechooser/PackageModel.cpp | 64 ++++++++++++++++++--- src/modules/packagechooser/PackageModel.h | 14 ++++- src/modules/packagechooser/Tests.cpp | 17 ++++++ src/modules/packagechooser/Tests.h | 1 + 5 files changed, 101 insertions(+), 10 deletions(-) diff --git a/src/modules/packagechooser/CMakeLists.txt b/src/modules/packagechooser/CMakeLists.txt index 4663ccce7..70a86a3bb 100644 --- a/src/modules/packagechooser/CMakeLists.txt +++ b/src/modules/packagechooser/CMakeLists.txt @@ -1,4 +1,15 @@ find_package( Qt5 COMPONENTS Core Gui Widgets REQUIRED ) +set( _extra_libraries "" ) + +### OPTIONAL AppData XML support in PackageModel +# +# +find_package(Qt5 COMPONENTS Xml) +if ( Qt5Xml_FOUND ) + add_definitions( -DHAVE_XML ) + list( APPEND _extra_libraries Qt5::Xml ) +endif() + calamares_add_plugin( packagechooser TYPE viewmodule @@ -13,6 +24,7 @@ calamares_add_plugin( packagechooser page_package.ui LINK_PRIVATE_LIBRARIES calamaresui + ${_extra_libraries} SHARED_LIB ) @@ -23,8 +35,11 @@ if( ECM_FOUND AND BUILD_TESTING ) packagechoosertest LINK_LIBRARIES ${CALAMARES_LIBRARIES} + calamares_viewmodule_packagechooser Qt5::Core Qt5::Test + Qt5::Gui + ${_extra_libraries} ) calamares_automoc( packagechoosertest) endif() diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index 3283cbe6f..f13564d5e 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -21,6 +21,11 @@ #include "utils/Logger.h" #include "utils/Variant.h" +#ifdef HAVE_XML +#include +#include +#endif + const NamedEnumTable< PackageChooserMode >& roleNames() { @@ -41,13 +46,6 @@ roleNames() return names; } -PackageItem -PackageItem::fromAppStream( const QString& filename ) -{ - // TODO: implement this - return PackageItem {}; -} - PackageItem::PackageItem() {} PackageItem::PackageItem( const QString& a_id, @@ -99,6 +97,56 @@ PackageItem::PackageItem::PackageItem( const QVariantMap& item_map ) } } +#ifdef HAVE_XML +QDomDocument +loadAppData( const QString& fileName ) +{ + QFile file( fileName ); + if ( !file.open( QIODevice::ReadOnly ) ) + { + return QDomDocument(); + } + QDomDocument doc( "AppData" ); + if ( !doc.setContent( &file ) ) + { + file.close(); + return QDomDocument(); + } + file.close(); + return doc; +} + +QString +getChildText( const QDomNode& n, const QString& tagName ) +{ + QDomElement e = n.firstChildElement( tagName ); + return e.isNull() ? QString() : e.text(); +} +#endif + +PackageItem +PackageItem::fromAppData( const QString& fileName ) +{ +#ifdef HAVE_XML + QDomDocument doc = loadAppData( fileName ); + if ( doc.isNull() ) + { + return PackageItem(); + } + + QDomElement componentNode = doc.documentElement(); + if ( !componentNode.isNull() && componentNode.tagName() == "component" ) + { + QString id = getChildText( componentNode, "id" ); + cDebug() << "Got AppData id" << id; + } + + return PackageItem(); +#else + return PackageItem(); +#endif +} + PackageListModel::PackageListModel( QObject* parent ) : QAbstractListModel( parent ) @@ -117,7 +165,7 @@ void PackageListModel::addPackage( PackageItem&& p ) { // Only add valid packages - if ( !p.name.isEmpty() ) + if ( p.isValid() ) { int c = m_packages.count(); beginInsertRows( QModelIndex(), c, c ); diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index ce384096c..7e79b98f1 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -75,8 +75,18 @@ struct PackageItem */ PackageItem( const QVariantMap& map ); - // TODO: implement this - PackageItem fromAppStream( const QString& filename ); + /** @brief Is this item valid? + * + * A valid item has an untranslated name available. + */ + bool isValid() const { return !name.isEmpty(); } + + /** @brief Loads an AppData XML file and returns a PackageItem + * + * Requires XML support in libcalamares, if not present will + * return invalid PackageItems. + */ + static PackageItem fromAppData( const QString& filename ); }; using PackageList = QVector< PackageItem >; diff --git a/src/modules/packagechooser/Tests.cpp b/src/modules/packagechooser/Tests.cpp index c016f1808..6cbab8e38 100644 --- a/src/modules/packagechooser/Tests.cpp +++ b/src/modules/packagechooser/Tests.cpp @@ -18,6 +18,8 @@ #include "Tests.h" +#include "PackageModel.h" + #include QTEST_GUILESS_MAIN( PackageChooserTests ) @@ -36,3 +38,18 @@ PackageChooserTests::testBogus() { QVERIFY( true ); } + +void +PackageChooserTests::testAppData() +{ + // Path from the build-dir + QString appdataName( "../io.calamares.calamares.appdata.xml" ); + QVERIFY( QFile::exists( appdataName ) ); + + PackageItem p = PackageItem::fromAppData( appdataName ); +#ifdef HAVE_XML + QVERIFY( p.isValid() ); +#else + QVERIFY( !p.isValid() ); +#endif +} diff --git a/src/modules/packagechooser/Tests.h b/src/modules/packagechooser/Tests.h index bc257f5a5..62efe92cc 100644 --- a/src/modules/packagechooser/Tests.h +++ b/src/modules/packagechooser/Tests.h @@ -31,6 +31,7 @@ public: private Q_SLOTS: void initTestCase(); void testBogus(); + void testAppData(); }; #endif From 6821b14d009b92d956f9178232eb24ca3bf4f8cc Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 14:41:40 +0200 Subject: [PATCH 116/302] [packagechooser] Enable logging in tests --- src/modules/packagechooser/PackageModel.cpp | 4 ++++ src/modules/packagechooser/Tests.cpp | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index f13564d5e..9a572f036 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -128,6 +128,8 @@ PackageItem PackageItem::fromAppData( const QString& fileName ) { #ifdef HAVE_XML + cDebug() << "Loading AppData XML from" << fileName; + QDomDocument doc = loadAppData( fileName ); if ( doc.isNull() ) { @@ -143,6 +145,8 @@ PackageItem::fromAppData( const QString& fileName ) return PackageItem(); #else + cWarning() << "Loading AppData XML is not supported."; + return PackageItem(); #endif } diff --git a/src/modules/packagechooser/Tests.cpp b/src/modules/packagechooser/Tests.cpp index 6cbab8e38..d9cbbf4ed 100644 --- a/src/modules/packagechooser/Tests.cpp +++ b/src/modules/packagechooser/Tests.cpp @@ -20,6 +20,8 @@ #include "PackageModel.h" +#include "utils/Logger.h" + #include QTEST_GUILESS_MAIN( PackageChooserTests ) @@ -31,6 +33,7 @@ PackageChooserTests::~PackageChooserTests() {} void PackageChooserTests::initTestCase() { + Logger::setupLogLevel( Logger::LOGDEBUG ); } void From 431c4de77fe2c7d7647be00e5051694c5a2b7805 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 15:19:20 +0200 Subject: [PATCH 117/302] [packagechooser] Use GUI for tests - Because we'll be creating Pixmaps, we need to have a GUI main. --- src/modules/packagechooser/Tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/packagechooser/Tests.cpp b/src/modules/packagechooser/Tests.cpp index d9cbbf4ed..e15397613 100644 --- a/src/modules/packagechooser/Tests.cpp +++ b/src/modules/packagechooser/Tests.cpp @@ -24,7 +24,7 @@ #include -QTEST_GUILESS_MAIN( PackageChooserTests ) +QTEST_MAIN( PackageChooserTests ) PackageChooserTests::PackageChooserTests() {} From fb547364c73c8d36e5b6ed0d2c74ded1e3447513 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 15:36:34 +0200 Subject: [PATCH 118/302] [packagechooser] Complete parsing of AppData - Document all the static inline methods that do the work - Fill up a QVariantMap from , and

elements, and use that to initialize the PackageItem. --- src/modules/packagechooser/PackageModel.cpp | 152 +++++++++++++++++++- 1 file changed, 147 insertions(+), 5 deletions(-) diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index 9a572f036..29890ee9b 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -23,6 +23,7 @@ #ifdef HAVE_XML #include +#include #include #endif @@ -98,7 +99,12 @@ PackageItem::PackageItem::PackageItem( const QVariantMap& item_map ) } #ifdef HAVE_XML -QDomDocument +/** @brief try to load the given @p fileName XML document + * + * Returns a QDomDocument, which will be valid iff the file can + * be read and contains valid XML data. + */ +static inline QDomDocument loadAppData( const QString& fileName ) { QFile file( fileName ); @@ -116,12 +122,138 @@ loadAppData( const QString& fileName ) return doc; } -QString +/** @brief gets the text of child element @p tagName + */ +static inline QString getChildText( const QDomNode& n, const QString& tagName ) { QDomElement e = n.firstChildElement( tagName ); return e.isNull() ? QString() : e.text(); } + +/** @brief Gets a suitable screenshot path + * + * The element contains zero or more + * elements, which can have a *type* associated with them. + * Scan the screenshot elements, return the path + * for the one labeled with type=default or, if there is no + * default, the first element. + */ +static inline QString +getScreenshotPath( const QDomNode& n ) +{ + QDomElement shotsNode = n.firstChildElement( "screenshots" ); + if ( shotsNode.isNull() ) + { + return QString(); + } + + const QDomNodeList shotList = shotsNode.childNodes(); + int firstScreenshot = -1; // Use which screenshot node? + for ( int i = 0; i < shotList.count(); ++i ) + { + if ( !shotList.at( i ).isElement() ) + { + continue; + } + QDomElement e = shotList.at( i ).toElement(); + if ( e.tagName() != "screenshot" ) + { + continue; + } + // If none has the "type=default" attribute, use the first one + if ( firstScreenshot < 0 ) + { + firstScreenshot = i; + } + // But type=default takes precedence. + if ( e.hasAttribute( "type" ) && e.attribute( "type" ) == "default" ) + { + firstScreenshot = i; + break; + } + } + + if ( firstScreenshot >= 0 ) + { + return shotList.at( firstScreenshot ).firstChildElement( "image" ).text(); + } + + return QString(); +} + +/** @brief Returns language of the given element @p e + * + * Transforms the attribute value for xml:lang to something + * suitable for TranslatedString (e.g. [lang]). + */ +static inline QString +getLanguage( const QDomElement& e ) +{ + QString language = e.attribute( "xml:lang" ); + if ( !language.isEmpty() ) + { + language.replace( '-', '_' ); + language.prepend( '[' ); + language.append( ']' ); + } + return language; +} + +/** @brief Scan the list of @p children for @p tagname elements and add them to the map + * + * Uses @p mapname instead of @p tagname for the entries in map @p m + * to allow renaming from XML to map keys (in particular for + * TranslatedString). Also transforms xml:lang attributes to suitable + * key-decorations on @p mapname. + */ +static inline void +fillMap( QVariantMap& m, const QDomNodeList& children, const QString& tagname, const QString& mapname ) +{ + for ( int i = 0; i < children.count(); ++i ) + { + if ( !children.at( i ).isElement() ) + { + continue; + } + + QDomElement e = children.at( i ).toElement(); + if ( e.tagName() != tagname ) + { + continue; + } + + m[ mapname + getLanguage( e ) ] = e.text(); + } +} + +/** @brief gets the and elements +* +* Builds up a map of the elements (which may have a *lang* +* attribute to indicate translations and paragraphs of the +* element (also with lang). Uses the

+* elements to supplement the description if no description +* is available for a given language. +* +* Returns a map with keys suitable for use by TranslatedString. +*/ +static inline QVariantMap +getNameAndSummary( const QDomNode& n ) +{ + QVariantMap m; + + const QDomNodeList children = n.childNodes(); + fillMap( m, children, "name", "name" ); + fillMap( m, children, "summary", "description" ); + + const QDomElement description = n.firstChildElement( "description" ); + if ( !description.isNull() ) + { + fillMap( m, description.childNodes(), "p", "description" ); + } + + return m; +} #endif PackageItem @@ -129,7 +261,7 @@ PackageItem::fromAppData( const QString& fileName ) { #ifdef HAVE_XML cDebug() << "Loading AppData XML from" << fileName; - + QDomDocument doc = loadAppData( fileName ); if ( doc.isNull() ) { @@ -140,13 +272,23 @@ PackageItem::fromAppData( const QString& fileName ) if ( !componentNode.isNull() && componentNode.tagName() == "component" ) { QString id = getChildText( componentNode, "id" ); - cDebug() << "Got AppData id" << id; + if ( id.isEmpty() ) + { + return PackageItem(); + } + + QString screenshotPath = getScreenshotPath( componentNode ); + + QVariantMap map = getNameAndSummary( componentNode ); + map.insert( "id", id ); + map.insert( "screenshot", screenshotPath ); + return PackageItem( map ); } return PackageItem(); #else cWarning() << "Loading AppData XML is not supported."; - + return PackageItem(); #endif } From 9a8b2c5a1e189a1870b7ccec49f01b7fedc1d254 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 15:45:14 +0200 Subject: [PATCH 119/302] [packagechooser] CHeck that AppData load was succesful --- src/modules/packagechooser/Tests.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/modules/packagechooser/Tests.cpp b/src/modules/packagechooser/Tests.cpp index e15397613..5dec8a288 100644 --- a/src/modules/packagechooser/Tests.cpp +++ b/src/modules/packagechooser/Tests.cpp @@ -52,6 +52,13 @@ PackageChooserTests::testAppData() PackageItem p = PackageItem::fromAppData( appdataName ); #ifdef HAVE_XML QVERIFY( p.isValid() ); + QCOMPARE( p.id, "io.calamares.calamares.desktop" ); + QCOMPARE( p.name.get(), "Calamares" ); + // The entry has precedence + QCOMPARE( p.description.get(), "Calamares is an installer program for Linux distributions." ); + // .. but en_GB doesn't have an entry in description, so uses + QCOMPARE( p.description.get( QLocale( "en_GB" ) ), "Calamares Linux Installer" ); + QCOMPARE( p.description.get( QLocale( "nl" ) ), "Calamares is een installatieprogramma voor Linux distributies." ); #else QVERIFY( !p.isValid() ); #endif From d72391942ffe6c0bf34482fd1c55566061b45618 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 15:55:27 +0200 Subject: [PATCH 120/302] [packagechooser] Implement AppData loading - An item can refer to *appdata* and load that, or provide the data in the config file itself. - Fix documentation about translations. --- .../packagechooser/PackageChooserViewStep.cpp | 9 ++++++- .../packagechooser/packagechooser.conf | 24 +++++++++++++++---- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index a3b853b39..fadacf8d4 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -232,7 +232,14 @@ PackageChooserViewStep::fillModel( const QVariantList& items ) continue; } - m_model->addPackage( PackageItem( item_map ) ); + if ( item_map.contains( "appdata" ) ) + { + m_model->addPackage( PackageItem::fromAppData( CalamaresUtils::getString( item_map, "appdata" ) ) ); + } + else + { + m_model->addPackage( PackageItem( item_map ) ); + } } } diff --git a/src/modules/packagechooser/packagechooser.conf b/src/modules/packagechooser/packagechooser.conf index 7d60b50a4..f20d1da77 100644 --- a/src/modules/packagechooser/packagechooser.conf +++ b/src/modules/packagechooser/packagechooser.conf @@ -24,8 +24,11 @@ mode: required # pretty short list to avoid overwhelming the UI. This is a list # of objects, and the items are displayed in list order. # -# Each item has an id, which is used in setting # the value of -# *packagechooser_*). The following fields +# Either provide the data for an item in the list (using the keys +# below), or use existing AppData XML files as a source for the data. +# +# For data provided by the list: the item has an id, which is used in +# setting the value of *packagechooser_*). The following fields # are mandatory: # # - *id* ID for the product. The ID "" is special, and is used for @@ -33,13 +36,24 @@ mode: required # selecting none. # - *package* Package name for the product. While mandatory, this is # not actually used anywhere. -# - *name* Human-readable, but untranslated, name of the product. -# - *description* Human-readable, but untranslated, description. +# - *name* Human-readable name of the product. To provide translations, +# add a *[lang]* decoration as part of the key name, e.g. `name[nl]` +# for Dutch. The list of usable languages can be found in +# `CMakeLists.txt` or as part of the debug output of Calamares. +# - *description* Human-readable description. These can be translated +# as well. # - *screenshot* Path to a single screenshot of the product. May be # a filesystem path or a QRC path (e.g. ":/images/no-selection.png"). # # Use the empty string "" as ID / key for the "no selection" item if # you want to customize the display of that item as well. +# +# For data provided by AppData XML: the item has an *appdata* +# key which points to an AppData XML file in the local filesystem. +# This file is parsed to provide the id (from AppData id), name +# (from AppData name), description (from AppData description paragraphs +# or the summary entries), and a screenshot (the defautl screenshot +# from AppData). No package is set (but that is unused anyway). items: - id: "" package: "" @@ -58,5 +72,5 @@ items: name: GNOME description: GNU Networked Object Modeling Environment Desktop screenshot: ":/images/gnome.png" - + - appdata: ../io.calamares.calamares.appdata.xml From 6ddae94628d3c3b9cbae028306c3896727477cde Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 22:36:35 +0200 Subject: [PATCH 121/302] [packagechooser] Allow to override some of AppData - The ID and Screenshot entries might be weird in AppData (in particular, a remove URL) so put those back under the control of Calamares even when using AppData as the source of descriptions. --- .../packagechooser/PackageChooserViewStep.cpp | 2 +- src/modules/packagechooser/PackageModel.cpp | 23 ++++++++++++++++--- src/modules/packagechooser/PackageModel.h | 8 ++++++- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index fadacf8d4..6df785a06 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -234,7 +234,7 @@ PackageChooserViewStep::fillModel( const QVariantList& items ) if ( item_map.contains( "appdata" ) ) { - m_model->addPackage( PackageItem::fromAppData( CalamaresUtils::getString( item_map, "appdata" ) ) ); + m_model->addPackage( PackageItem::fromAppData( item_map ) ); } else { diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index 29890ee9b..bddc26c7c 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -257,9 +257,15 @@ getNameAndSummary( const QDomNode& n ) #endif PackageItem -PackageItem::fromAppData( const QString& fileName ) +PackageItem::fromAppData( const QVariantMap& item_map ) { #ifdef HAVE_XML + QString fileName = CalamaresUtils::getString( item_map, "appdata" ); + if ( fileName.isEmpty() ) + { + cWarning() << "Can't load AppData without a suitable key."; + return PackageItem(); + } cDebug() << "Loading AppData XML from" << fileName; QDomDocument doc = loadAppData( fileName ); @@ -271,17 +277,28 @@ PackageItem::fromAppData( const QString& fileName ) QDomElement componentNode = doc.documentElement(); if ( !componentNode.isNull() && componentNode.tagName() == "component" ) { - QString id = getChildText( componentNode, "id" ); + // An "id" entry in the Calamares config overrides ID in the AppData + QString id = CalamaresUtils::getString( item_map, "id" ); + if ( id.isEmpty() ) + { + id = getChildText( componentNode, "id" ); + } if ( id.isEmpty() ) { return PackageItem(); } - QString screenshotPath = getScreenshotPath( componentNode ); + // A "screenshot" entry in the Calamares config overrides AppData + QString screenshotPath = CalamaresUtils::getString( item_map, "screenshot" ); + if ( screenshotPath.isEmpty() ) + { + screenshotPath = getScreenshotPath( componentNode ); + } QVariantMap map = getNameAndSummary( componentNode ); map.insert( "id", id ); map.insert( "screenshot", screenshotPath ); + return PackageItem( map ); } diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index 7e79b98f1..869e124f0 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -82,11 +82,17 @@ struct PackageItem bool isValid() const { return !name.isEmpty(); } /** @brief Loads an AppData XML file and returns a PackageItem + * + * The @p map must have a key *appdata*. That is used as the + * primary source of information, but keys *id* and *screenshotPath* + * may be used to override parts of the AppData -- so that the + * ID is under the control of Calamares, and the screenshot can be + * forced to a local path available on the installation medium. * * Requires XML support in libcalamares, if not present will * return invalid PackageItems. */ - static PackageItem fromAppData( const QString& filename ); + static PackageItem fromAppData( const QVariantMap& map ); }; using PackageList = QVector< PackageItem >; From 0b72006ffb53fa7ad31a865eb145d8ca5eea34d0 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 22:41:50 +0200 Subject: [PATCH 122/302] [packagechooser] Use overrides on AppData for example --- src/modules/packagechooser/images/calamares.png | Bin 0 -> 8313 bytes src/modules/packagechooser/packagechooser.conf | 10 +++++++++- src/modules/packagechooser/packagechooser.qrc | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 src/modules/packagechooser/images/calamares.png diff --git a/src/modules/packagechooser/images/calamares.png b/src/modules/packagechooser/images/calamares.png new file mode 100644 index 0000000000000000000000000000000000000000..452e4450c56c10cda33dcc9c5d03753ace458862 GIT binary patch literal 8313 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 zXkLEnN@images/no-selection.png images/kde.png images/gnome.png + images/calamares.png From 5d4c3ea92c028b7e102cc81dc31ba33e271863a4 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 22:46:36 +0200 Subject: [PATCH 123/302] [packagechooser] Don't give a default pixmap --- src/modules/packagechooser/PackageModel.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index bddc26c7c..59c6973ba 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -92,10 +92,6 @@ PackageItem::PackageItem::PackageItem( const QVariantMap& item_map ) { description = QObject::tr( "No description provided." ); } - if ( screenshot.isNull() ) - { - screenshot = QPixmap( QStringLiteral( ":/images/no-selection.png" ) ); - } } #ifdef HAVE_XML From a4362dac654b154e837d4035027c6980ce47101f Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 22:47:37 +0200 Subject: [PATCH 124/302] [packagechooser] Change tests for modified API --- src/modules/packagechooser/Tests.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/modules/packagechooser/Tests.cpp b/src/modules/packagechooser/Tests.cpp index 5dec8a288..15b5792bb 100644 --- a/src/modules/packagechooser/Tests.cpp +++ b/src/modules/packagechooser/Tests.cpp @@ -49,7 +49,10 @@ PackageChooserTests::testAppData() QString appdataName( "../io.calamares.calamares.appdata.xml" ); QVERIFY( QFile::exists( appdataName ) ); - PackageItem p = PackageItem::fromAppData( appdataName ); + QVariantMap m; + m.insert( "appdata", appdataName ); + + PackageItem p = PackageItem::fromAppData( m ); #ifdef HAVE_XML QVERIFY( p.isValid() ); QCOMPARE( p.id, "io.calamares.calamares.desktop" ); @@ -59,6 +62,15 @@ PackageChooserTests::testAppData() // .. but en_GB doesn't have an entry in description, so uses QCOMPARE( p.description.get( QLocale( "en_GB" ) ), "Calamares Linux Installer" ); QCOMPARE( p.description.get( QLocale( "nl" ) ), "Calamares is een installatieprogramma voor Linux distributies." ); + QVERIFY( p.screenshot.isNull() ); + + m.insert( "id", "calamares" ); + m.insert( "screenshot", ":/images/calamares.png" ); + PackageItem p_self = PackageItem::fromAppData( m ); + QVERIFY( p.isValid() ); + QCOMPARE( p.id, "calamares" ); + QCOMPARE( p.description.get( QLocale( "nl" ) ), "Calamares is een installatieprogramma voor Linux distributies." ); + QVERIFY( !p.screenshot.isNull() ); #else QVERIFY( !p.isValid() ); #endif From 194a562727e347a32b246613e05836cc405264e4 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 22:51:14 +0200 Subject: [PATCH 125/302] [packagechooser] Expand tests with override features --- src/modules/packagechooser/Tests.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/modules/packagechooser/Tests.cpp b/src/modules/packagechooser/Tests.cpp index 15b5792bb..3e7961b92 100644 --- a/src/modules/packagechooser/Tests.cpp +++ b/src/modules/packagechooser/Tests.cpp @@ -52,26 +52,26 @@ PackageChooserTests::testAppData() QVariantMap m; m.insert( "appdata", appdataName ); - PackageItem p = PackageItem::fromAppData( m ); + PackageItem p1 = PackageItem::fromAppData( m ); #ifdef HAVE_XML - QVERIFY( p.isValid() ); - QCOMPARE( p.id, "io.calamares.calamares.desktop" ); - QCOMPARE( p.name.get(), "Calamares" ); + QVERIFY( p1.isValid() ); + QCOMPARE( p1.id, "io.calamares.calamares.desktop" ); + QCOMPARE( p1.name.get(), "Calamares" ); // The entry has precedence - QCOMPARE( p.description.get(), "Calamares is an installer program for Linux distributions." ); + QCOMPARE( p1.description.get(), "Calamares is an installer program for Linux distributions." ); // .. but en_GB doesn't have an entry in description, so uses - QCOMPARE( p.description.get( QLocale( "en_GB" ) ), "Calamares Linux Installer" ); - QCOMPARE( p.description.get( QLocale( "nl" ) ), "Calamares is een installatieprogramma voor Linux distributies." ); - QVERIFY( p.screenshot.isNull() ); + QCOMPARE( p1.description.get( QLocale( "en_GB" ) ), "Calamares Linux Installer" ); + QCOMPARE( p1.description.get( QLocale( "nl" ) ), "Calamares is een installatieprogramma voor Linux distributies." ); + QVERIFY( p1.screenshot.isNull() ); m.insert( "id", "calamares" ); m.insert( "screenshot", ":/images/calamares.png" ); - PackageItem p_self = PackageItem::fromAppData( m ); - QVERIFY( p.isValid() ); - QCOMPARE( p.id, "calamares" ); - QCOMPARE( p.description.get( QLocale( "nl" ) ), "Calamares is een installatieprogramma voor Linux distributies." ); - QVERIFY( !p.screenshot.isNull() ); + PackageItem p2= PackageItem::fromAppData( m ); + QVERIFY( p2.isValid() ); + QCOMPARE( p2.id, "calamares" ); + QCOMPARE( p2.description.get( QLocale( "nl" ) ), "Calamares is een installatieprogramma voor Linux distributies." ); + QVERIFY( !p2.screenshot.isNull() ); #else - QVERIFY( !p.isValid() ); + QVERIFY( !p1.isValid() ); #endif } From 1b29ca5697515e0b369d87539d990620c70cdfe5 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 23:43:29 +0200 Subject: [PATCH 126/302] Changes: document packagechooser and others --- CHANGES | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGES b/CHANGES index c84f245b0..d41d4b8fa 100644 --- a/CHANGES +++ b/CHANGES @@ -18,12 +18,25 @@ This release contains contributions from (alphabetically by first name): number of jobs. (Thanks to Bill Auger) - Preliminary work has been added to post the installation log to a pastebin for bug reporting. (Thanks to Bill Auger) + - Support for translated human-readable strings in Calamares + config files has been added. This is used only in the *packagechooser* + module (see below) but will expand to those modules that need + user-visible strings from the configuration file (existing + solutions need either gettext or Qt support). + - Esperanto is now available when Qt version 5.12.2 or later is used. ## Modules ## - *fstab* A new configuration key *efiMountOptions* has been added, to allow setting filesystem options specifically for the EFI partition. (Thanks to apt-ghetto) + - *packagechooser* is a new module for low-density package choices, + e.g. for selecting a default desktop environment, or adding some + proprietary drivers, or chosing browsers of office suites. It presents + **one** collection of items -- at most ten or so, because of the UI -- + and the user can select zero or more of them. The behavior is + configurable, and package information can be set through the Calamares + configuration file or by reading AppData files for the packages. #426 # 3.2.11 (2019-07-06) # From 51ec85fdd54f59bf4b9ede92eca74f0899fcd825 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Wed, 7 Aug 2019 07:38:12 +0200 Subject: [PATCH 127/302] [officechooser] merge with upstream --- src/modules/officechooser/CMakeLists.txt | 19 +- .../officechooser/PackageChooserPage.cpp | 14 +- .../officechooser/PackageChooserViewStep.cpp | 80 ++++-- .../officechooser/PackageChooserViewStep.h | 1 + src/modules/officechooser/PackageModel.cpp | 263 +++++++++++++++++- src/modules/officechooser/PackageModel.h | 47 +++- src/modules/officechooser/Tests.cpp | 41 ++- src/modules/officechooser/Tests.h | 1 + src/modules/officechooser/officechooser.conf | 58 ++++ src/modules/officechooser/packagechooser.qrc | 7 +- src/modules/officechooser/page_package.ui | 9 - .../packagechooser/PackageChooserPage.cpp | 7 +- .../packagechooser/PackageChooserViewStep.cpp | 31 ++- src/modules/packagechooser/packagechooser.qrc | 7 +- 14 files changed, 502 insertions(+), 83 deletions(-) diff --git a/src/modules/officechooser/CMakeLists.txt b/src/modules/officechooser/CMakeLists.txt index a632f6750..4a839aad8 100644 --- a/src/modules/officechooser/CMakeLists.txt +++ b/src/modules/officechooser/CMakeLists.txt @@ -1,4 +1,15 @@ find_package( Qt5 COMPONENTS Core Gui Widgets REQUIRED ) +set( _extra_libraries "" ) + +### OPTIONAL AppData XML support in PackageModel +# +# +find_package(Qt5 COMPONENTS Xml) +if ( Qt5Xml_FOUND ) + add_definitions( -DHAVE_XML ) + list( APPEND _extra_libraries Qt5::Xml ) +endif() + calamares_add_plugin( officechooser TYPE viewmodule @@ -13,6 +24,7 @@ calamares_add_plugin( officechooser page_package.ui LINK_PRIVATE_LIBRARIES calamaresui + ${_extra_libraries} SHARED_LIB ) @@ -20,11 +32,14 @@ if( ECM_FOUND AND BUILD_TESTING ) ecm_add_test( Tests.cpp TEST_NAME - packagechooosertest + packagechoosertest LINK_LIBRARIES ${CALAMARES_LIBRARIES} + calamares_viewmodule_packagechooser Qt5::Core Qt5::Test + Qt5::Gui + ${_extra_libraries} ) - calamares_automoc( packagechooosertest) + calamares_automoc( packagechoosertest) endif() diff --git a/src/modules/officechooser/PackageChooserPage.cpp b/src/modules/officechooser/PackageChooserPage.cpp index c3d1ba3d0..6f565c914 100644 --- a/src/modules/officechooser/PackageChooserPage.cpp +++ b/src/modules/officechooser/PackageChooserPage.cpp @@ -1,7 +1,6 @@ /* === This file is part of Calamares - === * * Copyright 2019, Adriaan de Groot - * Copyright 2019, Philip MÜller * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,10 +30,10 @@ PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent , ui( new Ui::PackageChooserPage ) , m_introduction( QString(), QString(), - tr( "Office Suite" ), - tr( "Please pick an office suite from the list. The selected product will be installed." ) ) + tr( "Package Selection" ), + tr( "Please pick a product from the list. The selected product will be installed." ) ) { - m_introduction.screenshot = QPixmap( QStringLiteral( ":/images/choose-office.jpg" ) ); + m_introduction.screenshot = QPixmap( QStringLiteral( ":/images/no-selection.png" ) ); ui->setupUi( this ); CALAMARES_RETRANSLATE( updateLabels(); ) @@ -42,9 +41,12 @@ PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent switch ( mode ) { case PackageChooserMode::Optional: + FALLTHRU; case PackageChooserMode::Required: ui->products->setSelectionMode( QAbstractItemView::SingleSelection ); + break; case PackageChooserMode::OptionalMultiple: + FALLTHRU; case PackageChooserMode::RequiredMultiple: ui->products->setSelectionMode( QAbstractItemView::ExtendedSelection ); } @@ -55,9 +57,9 @@ PackageChooserPage::currentChanged( const QModelIndex& index ) { if ( !index.isValid() || !ui->products->selectionModel()->hasSelection() ) { - ui->productName->setText( m_introduction.name ); + ui->productName->setText( m_introduction.name.get() ); ui->productScreenshot->setPixmap( m_introduction.screenshot ); - ui->productDescription->setText( m_introduction.description ); + ui->productDescription->setText( m_introduction.description.get() ); } else { diff --git a/src/modules/officechooser/PackageChooserViewStep.cpp b/src/modules/officechooser/PackageChooserViewStep.cpp index faafa9951..6df785a06 100644 --- a/src/modules/officechooser/PackageChooserViewStep.cpp +++ b/src/modules/officechooser/PackageChooserViewStep.cpp @@ -1,7 +1,6 @@ /* === This file is part of Calamares - === * * Copyright 2019, Adriaan de Groot - * Copyright 2019, Philip MÜller * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -57,7 +56,7 @@ PackageChooserViewStep::~PackageChooserViewStep() QString PackageChooserViewStep::prettyName() const { - return tr( "Office Suite" ); + return tr( "Packages" ); } @@ -77,7 +76,7 @@ PackageChooserViewStep::widget() } else { - cWarning() << "OfficeChooser Widget created before model."; + cWarning() << "PackageChooser Widget created before model."; } } return m_widget; @@ -146,7 +145,7 @@ PackageChooserViewStep::onLeave() } Calamares::JobQueue::instance()->globalStorage()->insert( key, value ); - cDebug() << "OfficeChooser" << key << "selected" << value; + cDebug() << "PackageChooser" << key << "selected" << value; } Calamares::JobList @@ -178,35 +177,68 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap m_id = moduleInstanceKey().split( '@' ).last(); } + bool first_time = !m_model; + if ( configurationMap.contains( "items" ) ) + { + fillModel( configurationMap.value( "items" ).toList() ); + } + // TODO: replace this hard-coded model if ( !m_model ) { m_model = new PackageListModel( nullptr ); m_model->addPackage( PackageItem { QString(), QString(), - "No Office Suite", - "Please pick an office suite from the list. " - "If you don't want to install an office suite, that's fine, " - "you can install one later as needed.", - ":/images/choose-office.jpg" } ); - m_model->addPackage( PackageItem { "libreoffice-still", - "libreoffice-still", - "LibreOffice", - "LibreOffice is a powerful and free office suite, used by millions of people around the world. " - "Its clean interface and feature-rich tools help you unleash your creativity and enhance your productivity.", - ":/images/LibreOffice.jpg" } ); + "No Desktop", + "Please pick a desktop environment from the list. " + "If you don't want to install a desktop, that's fine, " + "your system will start up in text-only mode and you can " + "install a desktop environment later.", + ":/images/no-selection.png" } ); + m_model->addPackage( PackageItem { "kde", "kde", "Plasma", "Plasma Desktop", ":/images/kde.png" } ); + m_model->addPackage( PackageItem { + "gnome", "gnome", "GNOME", "GNU Networked Object Modeling Environment Desktop", ":/images/gnome.png" } ); + } - m_model->addPackage( PackageItem { "freeoffice", - "freeoffice", - "FreeOffice", - "FreeOffice 2018 is a full-featured Office suite with word processing, " - "spreadsheet and presentation software. It is seamlessly compatible with Microsoft Office. " - "(Note: You need to register the product for free longterm usage)", - ":/images/FreeOffice.jpg" } ); + if ( first_time && m_widget && m_model ) + { + hookupModel(); + } +} - if ( m_widget ) +void +PackageChooserViewStep::fillModel( const QVariantList& items ) +{ + if ( !m_model ) + { + m_model = new PackageListModel( nullptr ); + } + + if ( items.isEmpty() ) + { + cWarning() << "No *items* for PackageChooser module."; + return; + } + + cDebug() << "Loading PackageChooser model items from config"; + int item_index = 0; + for ( const auto& item_it : items ) + { + ++item_index; + QVariantMap item_map = item_it.toMap(); + if ( item_map.isEmpty() ) { - hookupModel(); + cWarning() << "PackageChooser entry" << item_index << "is not valid."; + continue; + } + + if ( item_map.contains( "appdata" ) ) + { + m_model->addPackage( PackageItem::fromAppData( item_map ) ); + } + else + { + m_model->addPackage( PackageItem( item_map ) ); } } } diff --git a/src/modules/officechooser/PackageChooserViewStep.h b/src/modules/officechooser/PackageChooserViewStep.h index 55ed2d4d5..e3ffc1d5b 100644 --- a/src/modules/officechooser/PackageChooserViewStep.h +++ b/src/modules/officechooser/PackageChooserViewStep.h @@ -56,6 +56,7 @@ public: void setConfigurationMap( const QVariantMap& configurationMap ) override; private: + void fillModel( const QVariantList& items ); void hookupModel(); PackageChooserPage* m_widget; diff --git a/src/modules/officechooser/PackageModel.cpp b/src/modules/officechooser/PackageModel.cpp index aa8dd39fc..59c6973ba 100644 --- a/src/modules/officechooser/PackageModel.cpp +++ b/src/modules/officechooser/PackageModel.cpp @@ -19,6 +19,13 @@ #include "PackageModel.h" #include "utils/Logger.h" +#include "utils/Variant.h" + +#ifdef HAVE_XML +#include +#include +#include +#endif const NamedEnumTable< PackageChooserMode >& roleNames() @@ -40,13 +47,6 @@ roleNames() return names; } -PackageItem -PackageItem::fromAppStream( const QString& filename ) -{ - // TODO: implement this - return PackageItem {}; -} - PackageItem::PackageItem() {} PackageItem::PackageItem( const QString& a_id, @@ -73,6 +73,239 @@ PackageItem::PackageItem( const QString& a_id, { } +PackageItem::PackageItem::PackageItem( const QVariantMap& item_map ) + : id( CalamaresUtils::getString( item_map, "id" ) ) + , package( CalamaresUtils::getString( item_map, "package" ) ) + , name( CalamaresUtils::Locale::TranslatedString( item_map, "name" ) ) + , description( CalamaresUtils::Locale::TranslatedString( item_map, "description" ) ) + , screenshot( CalamaresUtils::getString( item_map, "screenshot" ) ) +{ + if ( name.isEmpty() && id.isEmpty() ) + { + name = QObject::tr( "No product" ); + } + else if ( name.isEmpty() ) + { + cWarning() << "PackageChooser item" << id << "has an empty name."; + } + if ( description.isEmpty() ) + { + description = QObject::tr( "No description provided." ); + } +} + +#ifdef HAVE_XML +/** @brief try to load the given @p fileName XML document + * + * Returns a QDomDocument, which will be valid iff the file can + * be read and contains valid XML data. + */ +static inline QDomDocument +loadAppData( const QString& fileName ) +{ + QFile file( fileName ); + if ( !file.open( QIODevice::ReadOnly ) ) + { + return QDomDocument(); + } + QDomDocument doc( "AppData" ); + if ( !doc.setContent( &file ) ) + { + file.close(); + return QDomDocument(); + } + file.close(); + return doc; +} + +/** @brief gets the text of child element @p tagName + */ +static inline QString +getChildText( const QDomNode& n, const QString& tagName ) +{ + QDomElement e = n.firstChildElement( tagName ); + return e.isNull() ? QString() : e.text(); +} + +/** @brief Gets a suitable screenshot path + * + * The element contains zero or more + * elements, which can have a *type* associated with them. + * Scan the screenshot elements, return the path + * for the one labeled with type=default or, if there is no + * default, the first element. + */ +static inline QString +getScreenshotPath( const QDomNode& n ) +{ + QDomElement shotsNode = n.firstChildElement( "screenshots" ); + if ( shotsNode.isNull() ) + { + return QString(); + } + + const QDomNodeList shotList = shotsNode.childNodes(); + int firstScreenshot = -1; // Use which screenshot node? + for ( int i = 0; i < shotList.count(); ++i ) + { + if ( !shotList.at( i ).isElement() ) + { + continue; + } + QDomElement e = shotList.at( i ).toElement(); + if ( e.tagName() != "screenshot" ) + { + continue; + } + // If none has the "type=default" attribute, use the first one + if ( firstScreenshot < 0 ) + { + firstScreenshot = i; + } + // But type=default takes precedence. + if ( e.hasAttribute( "type" ) && e.attribute( "type" ) == "default" ) + { + firstScreenshot = i; + break; + } + } + + if ( firstScreenshot >= 0 ) + { + return shotList.at( firstScreenshot ).firstChildElement( "image" ).text(); + } + + return QString(); +} + +/** @brief Returns language of the given element @p e + * + * Transforms the attribute value for xml:lang to something + * suitable for TranslatedString (e.g. [lang]). + */ +static inline QString +getLanguage( const QDomElement& e ) +{ + QString language = e.attribute( "xml:lang" ); + if ( !language.isEmpty() ) + { + language.replace( '-', '_' ); + language.prepend( '[' ); + language.append( ']' ); + } + return language; +} + +/** @brief Scan the list of @p children for @p tagname elements and add them to the map + * + * Uses @p mapname instead of @p tagname for the entries in map @p m + * to allow renaming from XML to map keys (in particular for + * TranslatedString). Also transforms xml:lang attributes to suitable + * key-decorations on @p mapname. + */ +static inline void +fillMap( QVariantMap& m, const QDomNodeList& children, const QString& tagname, const QString& mapname ) +{ + for ( int i = 0; i < children.count(); ++i ) + { + if ( !children.at( i ).isElement() ) + { + continue; + } + + QDomElement e = children.at( i ).toElement(); + if ( e.tagName() != tagname ) + { + continue; + } + + m[ mapname + getLanguage( e ) ] = e.text(); + } +} + +/** @brief gets the and elements +* +* Builds up a map of the elements (which may have a *lang* +* attribute to indicate translations and paragraphs of the +* element (also with lang). Uses the +* elements to supplement the description if no description +* is available for a given language. +* +* Returns a map with keys suitable for use by TranslatedString. +*/ +static inline QVariantMap +getNameAndSummary( const QDomNode& n ) +{ + QVariantMap m; + + const QDomNodeList children = n.childNodes(); + fillMap( m, children, "name", "name" ); + fillMap( m, children, "summary", "description" ); + + const QDomElement description = n.firstChildElement( "description" ); + if ( !description.isNull() ) + { + fillMap( m, description.childNodes(), "p", "description" ); + } + + return m; +} +#endif + +PackageItem +PackageItem::fromAppData( const QVariantMap& item_map ) +{ +#ifdef HAVE_XML + QString fileName = CalamaresUtils::getString( item_map, "appdata" ); + if ( fileName.isEmpty() ) + { + cWarning() << "Can't load AppData without a suitable key."; + return PackageItem(); + } + cDebug() << "Loading AppData XML from" << fileName; + + QDomDocument doc = loadAppData( fileName ); + if ( doc.isNull() ) + { + return PackageItem(); + } + + QDomElement componentNode = doc.documentElement(); + if ( !componentNode.isNull() && componentNode.tagName() == "component" ) + { + // An "id" entry in the Calamares config overrides ID in the AppData + QString id = CalamaresUtils::getString( item_map, "id" ); + if ( id.isEmpty() ) + { + id = getChildText( componentNode, "id" ); + } + if ( id.isEmpty() ) + { + return PackageItem(); + } + + // A "screenshot" entry in the Calamares config overrides AppData + QString screenshotPath = CalamaresUtils::getString( item_map, "screenshot" ); + if ( screenshotPath.isEmpty() ) + { + screenshotPath = getScreenshotPath( componentNode ); + } + + QVariantMap map = getNameAndSummary( componentNode ); + map.insert( "id", id ); + map.insert( "screenshot", screenshotPath ); + + return PackageItem( map ); + } + + return PackageItem(); +#else + cWarning() << "Loading AppData XML is not supported."; + + return PackageItem(); +#endif +} + PackageListModel::PackageListModel( QObject* parent ) : QAbstractListModel( parent ) @@ -90,10 +323,14 @@ PackageListModel::~PackageListModel() {} void PackageListModel::addPackage( PackageItem&& p ) { - int c = m_packages.count(); - beginInsertRows( QModelIndex(), c, c ); - m_packages.append( p ); - endInsertRows(); + // Only add valid packages + if ( p.isValid() ) + { + int c = m_packages.count(); + beginInsertRows( QModelIndex(), c, c ); + m_packages.append( p ); + endInsertRows(); + } } int @@ -118,11 +355,11 @@ PackageListModel::data( const QModelIndex& index, int role ) const if ( role == Qt::DisplayRole /* Also PackageNameRole */ ) { - return m_packages[ row ].name; + return m_packages[ row ].name.get(); } else if ( role == DescriptionRole ) { - return m_packages[ row ].description; + return m_packages[ row ].description.get(); } else if ( role == ScreenshotRole ) { diff --git a/src/modules/officechooser/PackageModel.h b/src/modules/officechooser/PackageModel.h index 7f8fff8ec..869e124f0 100644 --- a/src/modules/officechooser/PackageModel.h +++ b/src/modules/officechooser/PackageModel.h @@ -19,6 +19,7 @@ #ifndef PACKAGEMODEL_H #define PACKAGEMODEL_H +#include "locale/TranslatableConfiguration.h" #include "utils/NamedEnum.h" #include @@ -39,12 +40,10 @@ const NamedEnumTable< PackageChooserMode >& roleNames(); struct PackageItem { QString id; - // TODO: may need more than one + // FIXME: unused QString package; - // TODO: name and description are localized - QString name; - QString description; - // TODO: may be more than one + CalamaresUtils::Locale::TranslatedString name; + CalamaresUtils::Locale::TranslatedString description; QPixmap screenshot; /// @brief Create blank PackageItem @@ -56,14 +55,44 @@ struct PackageItem */ PackageItem( const QString& id, const QString& package, const QString& name, const QString& description ); + /** @brief Creates a PackageItem from given strings. + * + * Set all the text members and load the screenshot from the given + * @p screenshotPath, which may be a QRC path (:/path/in/qrc) or + * a filesystem path, whatever QPixmap understands. + */ PackageItem( const QString& id, const QString& package, const QString& name, const QString& description, const QString& screenshotPath ); - // TODO: implement this - PackageItem fromAppStream( const QString& filename ); + /** @brief Creates a PackageItem from a QVariantMap + * + * This is intended for use when loading PackageItems from a + * configuration map. It will look up the various keys in the map + * and handle translation strings as well. + */ + PackageItem( const QVariantMap& map ); + + /** @brief Is this item valid? + * + * A valid item has an untranslated name available. + */ + bool isValid() const { return !name.isEmpty(); } + + /** @brief Loads an AppData XML file and returns a PackageItem + * + * The @p map must have a key *appdata*. That is used as the + * primary source of information, but keys *id* and *screenshotPath* + * may be used to override parts of the AppData -- so that the + * ID is under the control of Calamares, and the screenshot can be + * forced to a local path available on the installation medium. + * + * Requires XML support in libcalamares, if not present will + * return invalid PackageItems. + */ + static PackageItem fromAppData( const QVariantMap& map ); }; using PackageList = QVector< PackageItem >; @@ -75,6 +104,10 @@ public: PackageListModel( QObject* parent ); virtual ~PackageListModel() override; + /** @brief Add a package @p to the model + * + * Only valid packages are added -- that is, they must have a name. + */ void addPackage( PackageItem&& p ); int rowCount( const QModelIndex& index ) const override; diff --git a/src/modules/officechooser/Tests.cpp b/src/modules/officechooser/Tests.cpp index c016f1808..3e7961b92 100644 --- a/src/modules/officechooser/Tests.cpp +++ b/src/modules/officechooser/Tests.cpp @@ -18,9 +18,13 @@ #include "Tests.h" +#include "PackageModel.h" + +#include "utils/Logger.h" + #include -QTEST_GUILESS_MAIN( PackageChooserTests ) +QTEST_MAIN( PackageChooserTests ) PackageChooserTests::PackageChooserTests() {} @@ -29,6 +33,7 @@ PackageChooserTests::~PackageChooserTests() {} void PackageChooserTests::initTestCase() { + Logger::setupLogLevel( Logger::LOGDEBUG ); } void @@ -36,3 +41,37 @@ PackageChooserTests::testBogus() { QVERIFY( true ); } + +void +PackageChooserTests::testAppData() +{ + // Path from the build-dir + QString appdataName( "../io.calamares.calamares.appdata.xml" ); + QVERIFY( QFile::exists( appdataName ) ); + + QVariantMap m; + m.insert( "appdata", appdataName ); + + PackageItem p1 = PackageItem::fromAppData( m ); +#ifdef HAVE_XML + QVERIFY( p1.isValid() ); + QCOMPARE( p1.id, "io.calamares.calamares.desktop" ); + QCOMPARE( p1.name.get(), "Calamares" ); + // The entry has precedence + QCOMPARE( p1.description.get(), "Calamares is an installer program for Linux distributions." ); + // .. but en_GB doesn't have an entry in description, so uses + QCOMPARE( p1.description.get( QLocale( "en_GB" ) ), "Calamares Linux Installer" ); + QCOMPARE( p1.description.get( QLocale( "nl" ) ), "Calamares is een installatieprogramma voor Linux distributies." ); + QVERIFY( p1.screenshot.isNull() ); + + m.insert( "id", "calamares" ); + m.insert( "screenshot", ":/images/calamares.png" ); + PackageItem p2= PackageItem::fromAppData( m ); + QVERIFY( p2.isValid() ); + QCOMPARE( p2.id, "calamares" ); + QCOMPARE( p2.description.get( QLocale( "nl" ) ), "Calamares is een installatieprogramma voor Linux distributies." ); + QVERIFY( !p2.screenshot.isNull() ); +#else + QVERIFY( !p1.isValid() ); +#endif +} diff --git a/src/modules/officechooser/Tests.h b/src/modules/officechooser/Tests.h index bc257f5a5..62efe92cc 100644 --- a/src/modules/officechooser/Tests.h +++ b/src/modules/officechooser/Tests.h @@ -31,6 +31,7 @@ public: private Q_SLOTS: void initTestCase(); void testBogus(); + void testAppData(); }; #endif diff --git a/src/modules/officechooser/officechooser.conf b/src/modules/officechooser/officechooser.conf index b4e48c995..b90571a85 100644 --- a/src/modules/officechooser/officechooser.conf +++ b/src/modules/officechooser/officechooser.conf @@ -19,3 +19,61 @@ # or "optionalmultiple", "requiredmultiple" (for zero-or-more # or one-or-more). mode: required + +# Items to display in the chooser. In general, this should be a +# pretty short list to avoid overwhelming the UI. This is a list +# of objects, and the items are displayed in list order. +# +# Either provide the data for an item in the list (using the keys +# below), or use existing AppData XML files as a source for the data. +# +# For data provided by the list: the item has an id, which is used in +# setting the value of *packagechooser_*). The following fields +# are mandatory: +# +# - *id* ID for the product. The ID "" is special, and is used for +# "no package selected". Only include this if the mode allows +# selecting none. +# - *package* Package name for the product. While mandatory, this is +# not actually used anywhere. +# - *name* Human-readable name of the product. To provide translations, +# add a *[lang]* decoration as part of the key name, e.g. `name[nl]` +# for Dutch. The list of usable languages can be found in +# `CMakeLists.txt` or as part of the debug output of Calamares. +# - *description* Human-readable description. These can be translated +# as well. +# - *screenshot* Path to a single screenshot of the product. May be +# a filesystem path or a QRC path (e.g. ":/images/no-selection.png"). +# +# Use the empty string "" as ID / key for the "no selection" item if +# you want to customize the display of that item as well. +# +# For data provided by AppData XML: the item has an *appdata* +# key which points to an AppData XML file in the local filesystem. +# This file is parsed to provide the id (from AppData id), name +# (from AppData name), description (from AppData description paragraphs +# or the summary entries), and a screenshot (the defautl screenshot +# from AppData). No package is set (but that is unused anyway). +# +# AppData may contain IDs that are not useful inside Calamares, +# and the screenshot URL may be remote -- a remote URL will not +# be loaded and the screenshot will be missing. An item with *appdata* +# **may** specify an ID or screenshot path, as above. This will override +# the settings from AppData. +items: + - id: "" + package: "" + name: "No Office Suite" + description: "Please pick an office suite from the list. If you don't want to install an office suite, that's fine, you can install one later as needed." + screenshot: ":/images/choose-office.jpg" + - id: libreoffice-still + package: libreoffice-still + name: LibreOffice + description: "LibreOffice is a powerful and free office suite, used by millions of people around the world. Its clean interface and feature-rich tools help you unleash your creativity and enhance your productivity." + screenshot: ":/images/LibreOffice.jpg" + - id: freeoffice + package: freeoffice + name: FreeOffice + description: "FreeOffice 2018 is a full-featured Office suite with word processing, spreadsheet and presentation software. It is seamlessly compatible with Microsoft Office. (Note: You need to register the product for free longterm usage) + screenshot: ":/images/FreeOffice.jpg" + diff --git a/src/modules/officechooser/packagechooser.qrc b/src/modules/officechooser/packagechooser.qrc index f0b5e03fb..8f211c1bb 100644 --- a/src/modules/officechooser/packagechooser.qrc +++ b/src/modules/officechooser/packagechooser.qrc @@ -1,7 +1,8 @@ - images/choose-office.jpg - images/LibreOffice.jpg - images/FreeOffice.jpg + images/no-selection.png + images/kde.png + images/gnome.png + images/calamares.png diff --git a/src/modules/officechooser/page_package.ui b/src/modules/officechooser/page_package.ui index ea85acff3..17a960549 100644 --- a/src/modules/officechooser/page_package.ui +++ b/src/modules/officechooser/page_package.ui @@ -39,9 +39,6 @@ TextLabel - - Qt::AlignCenter - @@ -49,9 +46,6 @@ TextLabel - - Qt::AlignCenter - @@ -59,9 +53,6 @@ TextLabel - - Qt::AlignCenter - true diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index 6f565c914..37c1a2156 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -1,6 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2019, Adriaan de Groot + * Copyright 2019, Philip MÜller * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,10 +31,10 @@ PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent , ui( new Ui::PackageChooserPage ) , m_introduction( QString(), QString(), - tr( "Package Selection" ), - tr( "Please pick a product from the list. The selected product will be installed." ) ) + tr( "Office Suite" ), + tr( "Please pick an office suite from the list. The selected product will be installed." ) ) { - m_introduction.screenshot = QPixmap( QStringLiteral( ":/images/no-selection.png" ) ); + m_introduction.screenshot = QPixmap( QStringLiteral( ":/images/choose-office.jpg" ) ); ui->setupUi( this ); CALAMARES_RETRANSLATE( updateLabels(); ) diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 6df785a06..74b0c5693 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -1,6 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2019, Adriaan de Groot + * Copyright 2019, Philip MÜller * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -76,7 +77,7 @@ PackageChooserViewStep::widget() } else { - cWarning() << "PackageChooser Widget created before model."; + cWarning() << "OfficeChooser Widget created before model."; } } return m_widget; @@ -189,16 +190,24 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap m_model = new PackageListModel( nullptr ); m_model->addPackage( PackageItem { QString(), QString(), - "No Desktop", - "Please pick a desktop environment from the list. " - "If you don't want to install a desktop, that's fine, " - "your system will start up in text-only mode and you can " - "install a desktop environment later.", - ":/images/no-selection.png" } ); - m_model->addPackage( PackageItem { "kde", "kde", "Plasma", "Plasma Desktop", ":/images/kde.png" } ); - m_model->addPackage( PackageItem { - "gnome", "gnome", "GNOME", "GNU Networked Object Modeling Environment Desktop", ":/images/gnome.png" } ); - } + "No Office Suite", + "Please pick an office suite from the list. " + "If you don't want to install an office suite, that's fine, " + "you can install one later as needed.", + ":/images/choose-office.jpg" } ); + m_model->addPackage( PackageItem { "libreoffice-still", + "libreoffice-still", + "LibreOffice", + "LibreOffice is a powerful and free office suite, used by millions of people around the world. " + "Its clean interface and feature-rich tools help you unleash your creativity and enhance your productivity.", + ":/images/LibreOffice.jpg" } ); + m_model->addPackage( PackageItem { "freeoffice", + "freeoffice", + "FreeOffice", + "FreeOffice 2018 is a full-featured Office suite with word processing, " + "spreadsheet and presentation software. It is seamlessly compatible with Microsoft Office. " + "(Note: You need to register the product for free longterm usage)", + ":/images/FreeOffice.jpg" } ); if ( first_time && m_widget && m_model ) { diff --git a/src/modules/packagechooser/packagechooser.qrc b/src/modules/packagechooser/packagechooser.qrc index 8f211c1bb..f0b5e03fb 100644 --- a/src/modules/packagechooser/packagechooser.qrc +++ b/src/modules/packagechooser/packagechooser.qrc @@ -1,8 +1,7 @@ - images/no-selection.png - images/kde.png - images/gnome.png - images/calamares.png + images/choose-office.jpg + images/LibreOffice.jpg + images/FreeOffice.jpg From d0a64e173658b5d6132e71a2de3d04809b438b73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Wed, 7 Aug 2019 07:39:25 +0200 Subject: [PATCH 128/302] [officechooser] center fonts --- src/modules/officechooser/page_package.ui | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/modules/officechooser/page_package.ui b/src/modules/officechooser/page_package.ui index 17a960549..3914697d8 100644 --- a/src/modules/officechooser/page_package.ui +++ b/src/modules/officechooser/page_package.ui @@ -39,6 +39,12 @@ TextLabel + + Qt::AlignCenter + + + true + @@ -46,6 +52,9 @@ TextLabel + + Qt::AlignCenter + @@ -53,6 +62,9 @@ TextLabel + + Qt::AlignCenter + true From 76d79d8cd0f025abd650497ccc8b386a86b6a7d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Wed, 7 Aug 2019 07:44:00 +0200 Subject: [PATCH 129/302] [officechooser] fix ccp files --- .../officechooser/PackageChooserPage.cpp | 7 +++-- .../officechooser/PackageChooserViewStep.cpp | 31 ++++++++++++------- .../packagechooser/PackageChooserPage.cpp | 7 ++--- .../packagechooser/PackageChooserViewStep.cpp | 31 +++++++------------ 4 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/modules/officechooser/PackageChooserPage.cpp b/src/modules/officechooser/PackageChooserPage.cpp index 6f565c914..37c1a2156 100644 --- a/src/modules/officechooser/PackageChooserPage.cpp +++ b/src/modules/officechooser/PackageChooserPage.cpp @@ -1,6 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2019, Adriaan de Groot + * Copyright 2019, Philip MÜller * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,10 +31,10 @@ PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent , ui( new Ui::PackageChooserPage ) , m_introduction( QString(), QString(), - tr( "Package Selection" ), - tr( "Please pick a product from the list. The selected product will be installed." ) ) + tr( "Office Suite" ), + tr( "Please pick an office suite from the list. The selected product will be installed." ) ) { - m_introduction.screenshot = QPixmap( QStringLiteral( ":/images/no-selection.png" ) ); + m_introduction.screenshot = QPixmap( QStringLiteral( ":/images/choose-office.jpg" ) ); ui->setupUi( this ); CALAMARES_RETRANSLATE( updateLabels(); ) diff --git a/src/modules/officechooser/PackageChooserViewStep.cpp b/src/modules/officechooser/PackageChooserViewStep.cpp index 6df785a06..74b0c5693 100644 --- a/src/modules/officechooser/PackageChooserViewStep.cpp +++ b/src/modules/officechooser/PackageChooserViewStep.cpp @@ -1,6 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2019, Adriaan de Groot + * Copyright 2019, Philip MÜller * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -76,7 +77,7 @@ PackageChooserViewStep::widget() } else { - cWarning() << "PackageChooser Widget created before model."; + cWarning() << "OfficeChooser Widget created before model."; } } return m_widget; @@ -189,16 +190,24 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap m_model = new PackageListModel( nullptr ); m_model->addPackage( PackageItem { QString(), QString(), - "No Desktop", - "Please pick a desktop environment from the list. " - "If you don't want to install a desktop, that's fine, " - "your system will start up in text-only mode and you can " - "install a desktop environment later.", - ":/images/no-selection.png" } ); - m_model->addPackage( PackageItem { "kde", "kde", "Plasma", "Plasma Desktop", ":/images/kde.png" } ); - m_model->addPackage( PackageItem { - "gnome", "gnome", "GNOME", "GNU Networked Object Modeling Environment Desktop", ":/images/gnome.png" } ); - } + "No Office Suite", + "Please pick an office suite from the list. " + "If you don't want to install an office suite, that's fine, " + "you can install one later as needed.", + ":/images/choose-office.jpg" } ); + m_model->addPackage( PackageItem { "libreoffice-still", + "libreoffice-still", + "LibreOffice", + "LibreOffice is a powerful and free office suite, used by millions of people around the world. " + "Its clean interface and feature-rich tools help you unleash your creativity and enhance your productivity.", + ":/images/LibreOffice.jpg" } ); + m_model->addPackage( PackageItem { "freeoffice", + "freeoffice", + "FreeOffice", + "FreeOffice 2018 is a full-featured Office suite with word processing, " + "spreadsheet and presentation software. It is seamlessly compatible with Microsoft Office. " + "(Note: You need to register the product for free longterm usage)", + ":/images/FreeOffice.jpg" } ); if ( first_time && m_widget && m_model ) { diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index 37c1a2156..6f565c914 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -1,7 +1,6 @@ /* === This file is part of Calamares - === * * Copyright 2019, Adriaan de Groot - * Copyright 2019, Philip MÜller * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,10 +30,10 @@ PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent , ui( new Ui::PackageChooserPage ) , m_introduction( QString(), QString(), - tr( "Office Suite" ), - tr( "Please pick an office suite from the list. The selected product will be installed." ) ) + tr( "Package Selection" ), + tr( "Please pick a product from the list. The selected product will be installed." ) ) { - m_introduction.screenshot = QPixmap( QStringLiteral( ":/images/choose-office.jpg" ) ); + m_introduction.screenshot = QPixmap( QStringLiteral( ":/images/no-selection.png" ) ); ui->setupUi( this ); CALAMARES_RETRANSLATE( updateLabels(); ) diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 74b0c5693..6df785a06 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -1,7 +1,6 @@ /* === This file is part of Calamares - === * * Copyright 2019, Adriaan de Groot - * Copyright 2019, Philip MÜller * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -77,7 +76,7 @@ PackageChooserViewStep::widget() } else { - cWarning() << "OfficeChooser Widget created before model."; + cWarning() << "PackageChooser Widget created before model."; } } return m_widget; @@ -190,24 +189,16 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap m_model = new PackageListModel( nullptr ); m_model->addPackage( PackageItem { QString(), QString(), - "No Office Suite", - "Please pick an office suite from the list. " - "If you don't want to install an office suite, that's fine, " - "you can install one later as needed.", - ":/images/choose-office.jpg" } ); - m_model->addPackage( PackageItem { "libreoffice-still", - "libreoffice-still", - "LibreOffice", - "LibreOffice is a powerful and free office suite, used by millions of people around the world. " - "Its clean interface and feature-rich tools help you unleash your creativity and enhance your productivity.", - ":/images/LibreOffice.jpg" } ); - m_model->addPackage( PackageItem { "freeoffice", - "freeoffice", - "FreeOffice", - "FreeOffice 2018 is a full-featured Office suite with word processing, " - "spreadsheet and presentation software. It is seamlessly compatible with Microsoft Office. " - "(Note: You need to register the product for free longterm usage)", - ":/images/FreeOffice.jpg" } ); + "No Desktop", + "Please pick a desktop environment from the list. " + "If you don't want to install a desktop, that's fine, " + "your system will start up in text-only mode and you can " + "install a desktop environment later.", + ":/images/no-selection.png" } ); + m_model->addPackage( PackageItem { "kde", "kde", "Plasma", "Plasma Desktop", ":/images/kde.png" } ); + m_model->addPackage( PackageItem { + "gnome", "gnome", "GNOME", "GNU Networked Object Modeling Environment Desktop", ":/images/gnome.png" } ); + } if ( first_time && m_widget && m_model ) { From e635454ebd7a86b603a21b40282457d00a6bfbf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Wed, 7 Aug 2019 07:47:18 +0200 Subject: [PATCH 130/302] [officechooser] update debug lines --- src/modules/officechooser/PackageChooserViewStep.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/modules/officechooser/PackageChooserViewStep.cpp b/src/modules/officechooser/PackageChooserViewStep.cpp index 74b0c5693..184253809 100644 --- a/src/modules/officechooser/PackageChooserViewStep.cpp +++ b/src/modules/officechooser/PackageChooserViewStep.cpp @@ -57,7 +57,7 @@ PackageChooserViewStep::~PackageChooserViewStep() QString PackageChooserViewStep::prettyName() const { - return tr( "Packages" ); + return tr( "Office Suite" ); } @@ -146,7 +146,7 @@ PackageChooserViewStep::onLeave() } Calamares::JobQueue::instance()->globalStorage()->insert( key, value ); - cDebug() << "PackageChooser" << key << "selected" << value; + cDebug() << "OfficeChooser" << key << "selected" << value; } Calamares::JobList @@ -225,11 +225,11 @@ PackageChooserViewStep::fillModel( const QVariantList& items ) if ( items.isEmpty() ) { - cWarning() << "No *items* for PackageChooser module."; + cWarning() << "No *items* for OfficeChooser module."; return; } - cDebug() << "Loading PackageChooser model items from config"; + cDebug() << "Loading OfficeeChooser model items from config"; int item_index = 0; for ( const auto& item_it : items ) { @@ -237,7 +237,7 @@ PackageChooserViewStep::fillModel( const QVariantList& items ) QVariantMap item_map = item_it.toMap(); if ( item_map.isEmpty() ) { - cWarning() << "PackageChooser entry" << item_index << "is not valid."; + cWarning() << "OfficeChooser entry" << item_index << "is not valid."; continue; } From d5653c0215d1794901353bb12ffbe29e6a76c394 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Wed, 7 Aug 2019 08:06:50 +0200 Subject: [PATCH 131/302] [officechooser] fix Makefile --- src/modules/officechooser/CMakeLists.txt | 2 +- src/modules/officechooser/PackageChooserViewStep.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/officechooser/CMakeLists.txt b/src/modules/officechooser/CMakeLists.txt index 4a839aad8..59e3e928a 100644 --- a/src/modules/officechooser/CMakeLists.txt +++ b/src/modules/officechooser/CMakeLists.txt @@ -35,7 +35,7 @@ if( ECM_FOUND AND BUILD_TESTING ) packagechoosertest LINK_LIBRARIES ${CALAMARES_LIBRARIES} - calamares_viewmodule_packagechooser + calamares_viewmodule_officechooser Qt5::Core Qt5::Test Qt5::Gui diff --git a/src/modules/officechooser/PackageChooserViewStep.cpp b/src/modules/officechooser/PackageChooserViewStep.cpp index 184253809..b4b41929f 100644 --- a/src/modules/officechooser/PackageChooserViewStep.cpp +++ b/src/modules/officechooser/PackageChooserViewStep.cpp @@ -229,7 +229,7 @@ PackageChooserViewStep::fillModel( const QVariantList& items ) return; } - cDebug() << "Loading OfficeeChooser model items from config"; + cDebug() << "Loading OfficeChooser model items from config"; int item_index = 0; for ( const auto& item_it : items ) { From 8255966384078bad9c4c1f098fc3f87e56f6a9b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Wed, 7 Aug 2019 08:11:23 +0200 Subject: [PATCH 132/302] [officechooser] fix qrc file --- src/modules/officechooser/packagechooser.qrc | 7 +++---- src/modules/packagechooser/packagechooser.qrc | 7 ++++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/modules/officechooser/packagechooser.qrc b/src/modules/officechooser/packagechooser.qrc index 8f211c1bb..f0b5e03fb 100644 --- a/src/modules/officechooser/packagechooser.qrc +++ b/src/modules/officechooser/packagechooser.qrc @@ -1,8 +1,7 @@ - images/no-selection.png - images/kde.png - images/gnome.png - images/calamares.png + images/choose-office.jpg + images/LibreOffice.jpg + images/FreeOffice.jpg diff --git a/src/modules/packagechooser/packagechooser.qrc b/src/modules/packagechooser/packagechooser.qrc index f0b5e03fb..8f211c1bb 100644 --- a/src/modules/packagechooser/packagechooser.qrc +++ b/src/modules/packagechooser/packagechooser.qrc @@ -1,7 +1,8 @@ - images/choose-office.jpg - images/LibreOffice.jpg - images/FreeOffice.jpg + images/no-selection.png + images/kde.png + images/gnome.png + images/calamares.png From 332c8801da3b36bdad0915709137ef6633a51142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Wed, 7 Aug 2019 08:15:49 +0200 Subject: [PATCH 133/302] [officechooser] fix cpp file --- src/modules/officechooser/PackageChooserViewStep.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/officechooser/PackageChooserViewStep.cpp b/src/modules/officechooser/PackageChooserViewStep.cpp index b4b41929f..6c559e94c 100644 --- a/src/modules/officechooser/PackageChooserViewStep.cpp +++ b/src/modules/officechooser/PackageChooserViewStep.cpp @@ -208,6 +208,7 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap "spreadsheet and presentation software. It is seamlessly compatible with Microsoft Office. " "(Note: You need to register the product for free longterm usage)", ":/images/FreeOffice.jpg" } ); + } if ( first_time && m_widget && m_model ) { From f3de3202882dd2c120a979f093478c29a0857c40 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 7 Aug 2019 11:51:56 +0200 Subject: [PATCH 134/302] [packagechooser] Drop hard-coded data - Now that the configuration can do all the things, we don't need a hard-coded model with bogus entries. --- .../packagechooser/PackageChooserViewStep.cpp | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 6df785a06..c2e849d5f 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -183,23 +183,6 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap fillModel( configurationMap.value( "items" ).toList() ); } - // TODO: replace this hard-coded model - if ( !m_model ) - { - m_model = new PackageListModel( nullptr ); - m_model->addPackage( PackageItem { QString(), - QString(), - "No Desktop", - "Please pick a desktop environment from the list. " - "If you don't want to install a desktop, that's fine, " - "your system will start up in text-only mode and you can " - "install a desktop environment later.", - ":/images/no-selection.png" } ); - m_model->addPackage( PackageItem { "kde", "kde", "Plasma", "Plasma Desktop", ":/images/kde.png" } ); - m_model->addPackage( PackageItem { - "gnome", "gnome", "GNOME", "GNU Networked Object Modeling Environment Desktop", ":/images/gnome.png" } ); - } - if ( first_time && m_widget && m_model ) { hookupModel(); From 781be3368e6c0a469c65170a9abd61026753187b Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 7 Aug 2019 11:57:02 +0200 Subject: [PATCH 135/302] [packagechooser] Remove bogus images - KDE and GNOME selection images were drawn by me for the bogus package model, and should not be used. - Keep Calamares logo though, even if it doesn't make much sense to use it in package selection. - Keep the no-selection image since it might be used more often, but it's not very good. --- src/modules/packagechooser/images/gnome.png | Bin 5739 -> 0 bytes src/modules/packagechooser/images/kde.png | Bin 4678 -> 0 bytes src/modules/packagechooser/packagechooser.qrc | 2 -- 3 files changed, 2 deletions(-) delete mode 100644 src/modules/packagechooser/images/gnome.png delete mode 100644 src/modules/packagechooser/images/kde.png diff --git a/src/modules/packagechooser/images/gnome.png b/src/modules/packagechooser/images/gnome.png deleted file mode 100644 index f9f3901e14aeafc94babdf08bb5ffeb99af836a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5739 zcmeI0XHb*hw#HwIfKnq!kzTDdK|s0z1Bi$esnU@m7>aZhkQO?Eq5=Yn2>3^O2^}O< zsY(egKnO*8@9plK^Xc6C`F^=`XOc-~&s+9hd#&gBtsVL3p&IRl%NHOBqSa7W)rBAu z@RtOlq5wZn+;i=~&v{pM;};M_*G&A9B;BB6hahH74b{8)KA%=_uUwhzIVsoIR_m@* zX^N}~p64Z(3(aoMy(h-h!4t#O8D`QKHN^Wh#sqPlif_=%S&icdpKKYYXO`^H{l^|3 zE2J#1>*_kfNVDEar}Ajg+-dh$Z<=-A+eZngTod)Js+-?UU$eJ6vkV`bT&o%naPfB8 zGuEQwRaU+K=c%-^>ZTYJ!PE-z=(3Upsaw%Nd|~4MTLX4UIOxPeQ#fz+2ks5j4dOMb$GPeHYXpi7zadf#SO%9cwp03lNcmFPOt-8b zy!lz*?A2@6BEefnift%|3N7M){=5s;5sJaX8Vs;BHOlw+OXYLYllE|znqfxp(hg*z%Y9HvV{d zzQnh0Y1svPGn^X=olMc^Uuv@E+t{O5T+UsP~Ru{yo;Mbt6%l* z-PcqojBaa@=h9Hb%3<7Gs@qt_bKO?CnXlX@e?P+gZ$@|9F+P3zRJYB^PMjTTX=#BS zy?KzKsIYi~#bTp_gM)LC$10s!8gHAcUd(4I+VO@Ol{qB1Rz1<-EbN@U2y*rPE%Vao z4#=p~PD{1nuCr9C5gKWx-}cDZ_)g{vX2i|vg6O0hh6vAEIMqfoqc&?m0Ra&`w!)k$ z^*rkEW4Fj$0EM%YlZt@>GyKaVRczjp?C987!lzFhzjr3u`mKs>ki_SEvtL491H zrv8n^vXrM_-DT5=`QztTUB=ZVG`D(ge;`Nk(nc&d)Pxsf7B*qp*fH-tJvqX=%4F&; zA)KYyPY-$n5&07*dz0LQjaBK&JV8fm4HnPn?HKh)iv0JGpA=t>7VR{g?2h^D3>wm! zp1mox??ueOGd8FwLUIcWj+%Uu_q|x+EfmI(o0q3zW|lUf*d>rnYT5Z-`0wAp zV$LUNX=%eHPou4t8mi;EaDfmjE32}Dr#COE*3{rr+6z6l#Z>q%BF>5lO-K5a=qHt0X2(pGV4a72^($PYDgqfe^F3KsCE1f zgu=kesq4E$>_~YeBqXl0N8^z3qvL*g2Kh~+7mWd z&8)L&H{ra&s7S^uzy2KTe|_UP=i;FXnr0*CKpi;IOW2*&-UA3W@`>NE$Zc;q3)oqi;dR9L|@+ZVxQxcdtFdr-^-N%@?cn6<^KIB zV%|Qb*BclZi0JC-a?|ok1fDVBL!cc|fx)TV_SdZv-oF<*N#zbw*V4M=>FHTAd6Afb zKv0ZJ?bvql9~Jy7mhp9Jo}T4EYuVC|8W%h+cy4Qt&Fp&eaAS7T2+`$+YAbW7C2g$e2+4rV%ZmBY+ zWPd3tVmLe9Yv3Q}#62)JW~1Yhj{shSaWc*~=t{XwU0Ao9f-j%ed2mAGb6czbk%dLP zpyvCSh5Hhz-Qn7ShyCOGf<7lZ*o~5{r-Kp zws!BjTXz3KXdB_@H_Z?0RlTq1Owq{Ls-^zNo-^$*eSQ7URaJNRP~=E7`@zA%K5i`l zwa}lV_F1JoSqLid0$x^ov|59Ct2i?|%d4cs?Tz#NFw^rF5wMeIfybk`TN@i8;Jdj! zOAaaFF)=g(LPFDON{6u3nl(i-xyRAh$b!0@j&@guE1t7Y_$>(oxgrm_`?s2omz;u< z@{8l;o6OYkFAPsaSZd8h-;0=C$mm7I2Obkj#^U8@pu{WPtk~Tkx71^Cnp#LnhlrXKwM>li?KF?;E=wCL@erK z>gyG^cXt8xSf3sr5UK5t~N}@ zr=(mS7#yT^`Flk>UDeA=>Q8?^sH)#%W6_{uWI)Qxd5dK3pmv$u-Q8UeHlKnGXtFN; zj7GDptgKW5cOueIW+oqSX-;5JaZ5|P-mBx0y#c$Wn6n{CTG85dQX)MR=WWHdiAMiWqpFBLPEz1l)aEQ_vWywnBSMHSt0>o`JG?9__+K(=e5!v=2W`kgO@ARVp&Mpco?WYXJ(RC7uaCJX)Ap; z_yEu7bH9fzfpP$!-Q|&x^Nd0~a&qiIA~I~zx19krd`%gW=jA0at#B4E;s=S!=K!#M zYrYo+L<%6UAr&v*X$;0^cJGKNkpP8$n4%vZ7IGFgoF3-(bZqbJe96vkZH%Mg^Jft- z{{d{rAw??Fp2fB5;MTSxaYZ)lwuD>>-YIURMtx~ zPH5m%p%|+X;pBzI-8BSXlTPV1__YfFh&)+b%;BB>oJEY#sQn zhu=Ero19ddn`ikG8wTeEzF6WMyUFeE1-}h@G9C{gR*G9TXRXfmpxEtyYq0E9|`6 zeye}|0y(MA;X)250A~lzLTvQz?ygQlL0uiEqoX5*hb_khtqi=buCBekT{$qYVcFmv zGZpzd&=!8sxa8;Ohs(eA*_`RX7&^uw)YMQ5tM6vG8mR_`hMEW)u7r4AaI3nyy0V#> zSu<9_cXLKO%|#~gRGy4yqIUa_=G7ZF2qPz~0-=q>eExN#P}QRjjq_rUijD>er8JG5 znV)R+WH|)7{dO&6~5GzUM4xsL4t9yX+N1R8VyHJnDe_qwqU^YR6}F=Aw$5 z3Gu3BD2FLrkn|%{)9B4jcMosxPGlIOamCB#?DT}#^0Xfw2PlE2Lu&f%>yC~NfTGek z4dqpm@kZdGRU4`5+S>Gr80YN0LW){cOEN$Bo z3>|}`qfx(p{ffwU0U8dtR{G={QU5sT2rLcz_nH?GjPxW0ZeWXmyx?jX<*)VtHS9qj#{9(lyq9wF<@F5J^izV~KAHgPGX_ySM92r-h1) zZuae*xkwQSXQ!2344NQR&8K5pqFJ7z?-B<7{0Zii^HTLl8yp<0^jNrPP-q_O@{+(# z{10S>&qRfSi}cCU)$uAKATLW@C7tU|MJ+Bq8+qO=PtkY@9)UNLyQQSn@3S#PwayrL zPfLpya0<8(?qSvj_}CT=+hTA&Y? zj7D=SM#55njnxi+l^%OAKl#_8v9VWl9?BNFicFQ@jg+D_lKm{3joSRR)`;rgGxmKl>&)c06N(au*DmOscutuf?#0R9e_O4`fkZQ zH=+R+3S?6mbotV!ZqqrwO#kHN6}u4-6B0ZLIAoi5{TAox5I3(pIco@5($s58uEyVA z)$YU^z581o_veo;pg1zU><00=H-i0Q@8-Ca!~11S>*oZ0)uQDTVSo4h26Zb}46K!`25* zBWgIm%X86#3S1B2K86GZ1;N8ElPL#dQ1muLsw#J4Nl8s51oT=ugil08UHD;COv-)O zhq6Vh8j3;I#OQ1c=xO7>eJ~H6TthLCrer6Ju!j2q;~yCr0lhiQAm60L<$$#nin!}i zyFqcf-=>tAolUV;yF~|_)Oy!W05pU%GqyzJ^`3ks4Gv4f*(B`RkTp2waWcB-uoW_`2Pd{3B>=G<56@*V%BsHyKKUj4^EFEje8GO J3*eT){{=a!jIsa# diff --git a/src/modules/packagechooser/images/kde.png b/src/modules/packagechooser/images/kde.png deleted file mode 100644 index 02f3e70ea21282afa79d367f05d602c33cb5ddd3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4678 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 diff --git a/src/modules/packagechooser/packagechooser.qrc b/src/modules/packagechooser/packagechooser.qrc index 8f211c1bb..3b9c96a5b 100644 --- a/src/modules/packagechooser/packagechooser.qrc +++ b/src/modules/packagechooser/packagechooser.qrc @@ -1,8 +1,6 @@ images/no-selection.png - images/kde.png - images/gnome.png images/calamares.png From 20f43225b55170bf95f549208e1a4f862423703d Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 7 Aug 2019 12:02:03 +0200 Subject: [PATCH 136/302] [packagechooser] Adjust AppData path for tests - running tests by hand or from "make test" uses different paths. --- src/modules/packagechooser/Tests.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/modules/packagechooser/Tests.cpp b/src/modules/packagechooser/Tests.cpp index 3e7961b92..7e2552c28 100644 --- a/src/modules/packagechooser/Tests.cpp +++ b/src/modules/packagechooser/Tests.cpp @@ -47,6 +47,14 @@ PackageChooserTests::testAppData() { // Path from the build-dir QString appdataName( "../io.calamares.calamares.appdata.xml" ); + if ( !QFile::exists( appdataName ) ) + { + // Running the tests by hand from the build-dir uses the + // path above, but ctest, used by "make test", runs them in + // the module build dir (e.g. build/src/modules/packagechooser) + // so we need to adjust the path some. + appdataName.prepend( "../../../" ); + } QVERIFY( QFile::exists( appdataName ) ); QVariantMap m; From 729616ac6a20eb9a341b5fde9cd969abd8ea2499 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 7 Aug 2019 12:14:37 +0200 Subject: [PATCH 137/302] Changes: pre-release housekeeping --- CHANGES | 2 +- CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index d41d4b8fa..855bf8fb8 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.12 (unreleased) # +# 3.2.12 (2019-08-07) # This release contains contributions from (alphabetically by first name): - apt-ghetto diff --git a/CMakeLists.txt b/CMakeLists.txt index e28d28f38..3e5dde2c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,7 +40,7 @@ project( CALAMARES VERSION 3.2.12 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 6c5d0e9d3d76c9abdfdb319b4ebe493b0786c201 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 7 Aug 2019 12:18:26 +0200 Subject: [PATCH 138/302] CI: make scripts executable --- ci/AppImage.sh | 0 ci/RELEASE.sh | 0 ci/txstats.py | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 ci/AppImage.sh mode change 100644 => 100755 ci/RELEASE.sh mode change 100644 => 100755 ci/txstats.py diff --git a/ci/AppImage.sh b/ci/AppImage.sh old mode 100644 new mode 100755 diff --git a/ci/RELEASE.sh b/ci/RELEASE.sh old mode 100644 new mode 100755 diff --git a/ci/txstats.py b/ci/txstats.py old mode 100644 new mode 100755 index 2edf1dd5b..34ef4fc97 --- a/ci/txstats.py +++ b/ci/txstats.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#! /usr/bin/env python3 # # Uses the Transifex API to get a list of enabled languages, # and outputs CMake settings for inclusion into CMakeLists.txt. From 251e16e72c69784aaf5c9f00b9fd4dcfdf63b6ed Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 7 Aug 2019 12:31:52 +0200 Subject: [PATCH 139/302] [libcalamares] Allow en_US locale for tests as well --- src/libcalamares/locale/Tests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcalamares/locale/Tests.cpp b/src/libcalamares/locale/Tests.cpp index fa84cd2fb..a9e5e7399 100644 --- a/src/libcalamares/locale/Tests.cpp +++ b/src/libcalamares/locale/Tests.cpp @@ -35,6 +35,8 @@ LocaleTests::~LocaleTests() {} void LocaleTests::initTestCase() { + // Otherwise plain get() is dubious in the TranslatableConfiguration tests + QVERIFY( ( QLocale().name() == "C" ) || ( QLocale().name() == "en_US" ) ); } void @@ -121,7 +123,6 @@ LocaleTests::testTranslatableConfig1() QVERIFY( ts0.isEmpty() ); QCOMPARE( ts0.count(), 1 ); // the empty string - QCOMPARE( QLocale().name(), "C" ); // Otherwise plain get() is dubious CalamaresUtils::Locale::TranslatedString ts1( "Hello" ); QCOMPARE( ts1.count(), 1 ); QVERIFY( !ts1.isEmpty() ); @@ -144,7 +145,6 @@ LocaleTests::testTranslatableConfig1() void LocaleTests::testTranslatableConfig2() { - QCOMPARE( QLocale().name(), "C" ); // Otherwise plain get() is dubious QVariantMap map; for ( const auto& language : someLanguages() ) From e2cb2690bd7a140097a4118cf376e91e416f0607 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 7 Aug 2019 12:50:46 +0200 Subject: [PATCH 140/302] CI: tell where if the release builds fail --- ci/RELEASE.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/RELEASE.sh b/ci/RELEASE.sh index dfb65cfeb..78fc1f7ce 100755 --- a/ci/RELEASE.sh +++ b/ci/RELEASE.sh @@ -54,7 +54,7 @@ if test "x$BUILD_CLANG" = "xtrue" ; then rm -rf "$BUILDDIR" mkdir "$BUILDDIR" || { echo "Could not create build directory." ; exit 1 ; } ( cd "$BUILDDIR" && CC=clang CXX=clang++ cmake .. && make -j4 ) || { echo "Could not perform test-build in $BUILDDIR." ; exit 1 ; } - ( cd "$BUILDDIR" && make test ) || { echo "Tests failed in $BUILDDIR." ; exit 1 ; } + ( cd "$BUILDDIR" && make test ) || { echo "Tests failed in $BUILDDIR (clang)." ; exit 1 ; } fi fi @@ -93,7 +93,7 @@ TMPDIR=$(mktemp -d --suffix="-calamares-$D") test -d "$TMPDIR" || { echo "Could not create tarball-build directory." ; exit 1 ; } tar xzf "$TAR_FILE" -C "$TMPDIR" || { echo "Could not unpack tarball." ; exit 1 ; } test -d "$TMPDIR/$TAR_V" || { echo "Tarball did not contain source directory." ; exit 1 ; } -( cd "$TMPDIR/$TAR_V" && cmake . && make -j4 && make test ) || { echo "Tarball build failed." ; exit 1 ; } +( cd "$TMPDIR/$TAR_V" && cmake . && make -j4 && make test ) || { echo "Tarball build failed in $TMPDIR." ; exit 1 ; } ### Cleanup # From 8636689ceacefd940cbc4f8ab75eea3bba7870e9 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 7 Aug 2019 12:54:03 +0200 Subject: [PATCH 141/302] [packagechooser] Fix tests when run from in-source build --- src/modules/packagechooser/Tests.cpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/modules/packagechooser/Tests.cpp b/src/modules/packagechooser/Tests.cpp index 7e2552c28..537ecbd3c 100644 --- a/src/modules/packagechooser/Tests.cpp +++ b/src/modules/packagechooser/Tests.cpp @@ -45,21 +45,23 @@ PackageChooserTests::testBogus() void PackageChooserTests::testAppData() { - // Path from the build-dir - QString appdataName( "../io.calamares.calamares.appdata.xml" ); - if ( !QFile::exists( appdataName ) ) + // Path from the build-dir and from the running-the-test varies, + // for in-source build, for build/, and for tests-in-build/, + // so look in multiple places. + QString appdataName( "io.calamares.calamares.appdata.xml" ); + for ( const auto& prefix : QStringList { "", "../", "../../../", "../../../../" } ) { - // Running the tests by hand from the build-dir uses the - // path above, but ctest, used by "make test", runs them in - // the module build dir (e.g. build/src/modules/packagechooser) - // so we need to adjust the path some. - appdataName.prepend( "../../../" ); + if ( QFile::exists( prefix + appdataName ) ) + { + appdataName = prefix + appdataName; + break; + } } QVERIFY( QFile::exists( appdataName ) ); QVariantMap m; m.insert( "appdata", appdataName ); - + PackageItem p1 = PackageItem::fromAppData( m ); #ifdef HAVE_XML QVERIFY( p1.isValid() ); @@ -71,10 +73,10 @@ PackageChooserTests::testAppData() QCOMPARE( p1.description.get( QLocale( "en_GB" ) ), "Calamares Linux Installer" ); QCOMPARE( p1.description.get( QLocale( "nl" ) ), "Calamares is een installatieprogramma voor Linux distributies." ); QVERIFY( p1.screenshot.isNull() ); - + m.insert( "id", "calamares" ); m.insert( "screenshot", ":/images/calamares.png" ); - PackageItem p2= PackageItem::fromAppData( m ); + PackageItem p2 = PackageItem::fromAppData( m ); QVERIFY( p2.isValid() ); QCOMPARE( p2.id, "calamares" ); QCOMPARE( p2.description.get( QLocale( "nl" ) ), "Calamares is een installatieprogramma voor Linux distributies." ); From 2bb1474ebb9373b3660918bb937a164dcc7a85d9 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 7 Aug 2019 22:15:08 +0200 Subject: [PATCH 142/302] Changes: post-release housekeeping --- CHANGES | 9 +++++++++ CMakeLists.txt | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 855bf8fb8..9879043dc 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,15 @@ 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.13 (unreleased) # + +This release contains contributions from (alphabetically by first name): + +## Core ## + +## Modules ## + + # 3.2.12 (2019-08-07) # This release contains contributions from (alphabetically by first name): diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e5dde2c6..36c09abf0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,10 +37,10 @@ cmake_minimum_required( VERSION 3.3 FATAL_ERROR ) project( CALAMARES - VERSION 3.2.12 + VERSION 3.2.13 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 6b659b6f48e57ce5807c7691ebbf57b768af8b1b Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 7 Aug 2019 23:42:33 +0200 Subject: [PATCH 143/302] [libcalamares] Apply current coding standard to locale/ --- src/libcalamares/locale/TranslatableConfiguration.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcalamares/locale/TranslatableConfiguration.h b/src/libcalamares/locale/TranslatableConfiguration.h index a055cbfbd..45679bce0 100644 --- a/src/libcalamares/locale/TranslatableConfiguration.h +++ b/src/libcalamares/locale/TranslatableConfiguration.h @@ -51,14 +51,14 @@ public: } /** @brief How many strings (translations) are there? - * + * * This is always at least 1 (for the untranslated string), * but may be more than 1 even when isEmpty() is true -- * if there is no untranslated version, for instance. */ int count() const { return m_strings.count(); } /** @brief Consider this string empty? - * + * * Only the state of the untranslated string is considered, * so count() may be more than 1 even while the string is empty. */ From 81fa1735b15b26735cde85bae6515b09e60db35c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 7 Aug 2019 23:43:45 +0200 Subject: [PATCH 144/302] [libcalamares] Apply current coding style --- src/libcalamares/CalamaresConfig.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcalamares/CalamaresConfig.h.in b/src/libcalamares/CalamaresConfig.h.in index 6fbab422c..55468cf15 100644 --- a/src/libcalamares/CalamaresConfig.h.in +++ b/src/libcalamares/CalamaresConfig.h.in @@ -12,4 +12,4 @@ #cmakedefine WITH_PYTHON #cmakedefine WITH_PYTHONQT -#endif // CALAMARESCONFIG_H +#endif // CALAMARESCONFIG_H From 6e9f1be9e9245f0b062097f61b36ce8a6f6f4e11 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 8 Aug 2019 11:56:20 +0200 Subject: [PATCH 145/302] [libcalamares] Don't reformat string tables in GeoIP --- src/libcalamares/geoip/Handler.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/libcalamares/geoip/Handler.cpp b/src/libcalamares/geoip/Handler.cpp index df033f476..21b88dd4b 100644 --- a/src/libcalamares/geoip/Handler.cpp +++ b/src/libcalamares/geoip/Handler.cpp @@ -38,11 +38,15 @@ handlerTypes() { using Type = CalamaresUtils::GeoIP::Handler::Type; + // *INDENT-OFF* + // clang-format off static const NamedEnumTable names{ - { QStringLiteral( "none" ), Type::None}, - { QStringLiteral( "json" ), Type::JSON}, - { QStringLiteral( "xml" ), Type::XML} + { QStringLiteral( "none" ), Type::None }, + { QStringLiteral( "json" ), Type::JSON }, + { QStringLiteral( "xml" ), Type::XML } }; + // *INDENT-ON* + // clang-format on return names; } From a2ab91474fa60110bc4af4ab051c00454bd2989b Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 8 Aug 2019 12:29:06 +0200 Subject: [PATCH 146/302] CI: massage the .clang-format file, it's just ASCII --- .clang-format | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/.clang-format b/.clang-format index d76498a3e..e98283194 100644 --- a/.clang-format +++ b/.clang-format @@ -1,34 +1,32 @@ ---- +--- BasedOnStyle: WebKit AlignAfterOpenBracket: Align AlignEscapedNewlines: Left -AllowAllParametersOfDeclarationOnNextLine: 'false' +AllowAllParametersOfDeclarationOnNextLine: "false" AllowShortFunctionsOnASingleLine: Inline -AllowShortIfStatementsOnASingleLine: 'false' -AllowShortLoopsOnASingleLine: 'false' +AllowShortIfStatementsOnASingleLine: "false" +AllowShortLoopsOnASingleLine: "false" AlwaysBreakAfterReturnType: TopLevelDefinitions AlwaysBreakTemplateDeclarations: Yes -BinPackArguments: 'false' -BinPackParameters: 'false' +BinPackArguments: "false" +BinPackParameters: "false" BreakBeforeBraces: Allman -BreakBeforeTernaryOperators: 'true' +BreakBeforeTernaryOperators: "true" BreakConstructorInitializers: BeforeComma ColumnLimit: 120 -Cpp11BracedListStyle: 'false' -FixNamespaceComments: 'true' +Cpp11BracedListStyle: "false" +FixNamespaceComments: "true" IncludeBlocks: Preserve -IndentWidth: '4' -MaxEmptyLinesToKeep: '2' +IndentWidth: "4" +MaxEmptyLinesToKeep: "2" NamespaceIndentation: None PointerAlignment: Left -ReflowComments: 'false' -SortIncludes: 'true' -SpaceAfterCStyleCast: 'false' -SpacesBeforeTrailingComments: '2' -SpacesInAngles: 'true' -SpacesInParentheses: 'true' -SpacesInSquareBrackets: 'true' +ReflowComments: "false" +SortIncludes: "true" +SpaceAfterCStyleCast: "false" +SpacesBeforeTrailingComments: "2" +SpacesInAngles: "true" +SpacesInParentheses: "true" +SpacesInSquareBrackets: "true" Standard: Cpp11 - -... From ec073ee188c40b7430955fb4fc4213a75480b2d9 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 8 Aug 2019 12:32:21 +0200 Subject: [PATCH 147/302] [libcalamares] Apply coding style to geoip/ --- src/libcalamares/geoip/GeoIPJSON.cpp | 28 +++++++++------ src/libcalamares/geoip/GeoIPJSON.h | 8 ++--- src/libcalamares/geoip/GeoIPXML.cpp | 14 ++++++-- src/libcalamares/geoip/GeoIPXML.h | 8 ++--- src/libcalamares/geoip/Handler.cpp | 50 +++++++++++++-------------- src/libcalamares/geoip/Handler.h | 9 +++-- src/libcalamares/geoip/Interface.cpp | 10 +++--- src/libcalamares/geoip/Interface.h | 30 ++++++++++------ src/libcalamares/geoip/test_geoip.cpp | 29 ++++++++++------ 9 files changed, 106 insertions(+), 80 deletions(-) diff --git a/src/libcalamares/geoip/GeoIPJSON.cpp b/src/libcalamares/geoip/GeoIPJSON.cpp index 4b7562d7e..85dc79619 100644 --- a/src/libcalamares/geoip/GeoIPJSON.cpp +++ b/src/libcalamares/geoip/GeoIPJSON.cpp @@ -30,7 +30,7 @@ namespace CalamaresUtils namespace GeoIP { -GeoIPJSON::GeoIPJSON(const QString& attribute) +GeoIPJSON::GeoIPJSON( const QString& attribute ) : Interface( attribute.isEmpty() ? QStringLiteral( "time_zone" ) : attribute ) { } @@ -42,19 +42,25 @@ GeoIPJSON::GeoIPJSON(const QString& attribute) * "foo" of @p m, like a regular JSON lookup would. */ static QString -selectMap( const QVariantMap& m, const QStringList& l, int index) +selectMap( const QVariantMap& m, const QStringList& l, int index ) { if ( index >= l.count() ) + { return QString(); + } - QString attributeName = l[index]; + QString attributeName = l[ index ]; if ( index == l.count() - 1 ) + { return CalamaresUtils::getString( m, attributeName ); + } else { bool success = false; // bogus if ( m.contains( attributeName ) ) - return selectMap( CalamaresUtils::getSubMap( m, attributeName, success ), l, index+1 ); + { + return selectMap( CalamaresUtils::getSubMap( m, attributeName, success ), l, index + 1 ); + } return QString(); } } @@ -67,18 +73,18 @@ GeoIPJSON::rawReply( const QByteArray& data ) YAML::Node doc = YAML::Load( data ); QVariant var = CalamaresUtils::yamlToVariant( doc ); - if ( !var.isNull() && - var.isValid() && - var.type() == QVariant::Map ) + if ( !var.isNull() && var.isValid() && var.type() == QVariant::Map ) { - return selectMap( var.toMap(), m_element.split('.'), 0 ); + return selectMap( var.toMap(), m_element.split( '.' ), 0 ); } else + { cWarning() << "Invalid YAML data for GeoIPJSON"; + } } catch ( YAML::Exception& e ) { - CalamaresUtils::explainYamlException( e, data, "GeoIP data"); + CalamaresUtils::explainYamlException( e, data, "GeoIP data" ); } return QString(); @@ -90,5 +96,5 @@ GeoIPJSON::processReply( const QByteArray& data ) return splitTZString( rawReply( data ) ); } -} -} // namespace +} // namespace GeoIP +} // namespace CalamaresUtils diff --git a/src/libcalamares/geoip/GeoIPJSON.h b/src/libcalamares/geoip/GeoIPJSON.h index 4d7ded631..3f7756dd8 100644 --- a/src/libcalamares/geoip/GeoIPJSON.h +++ b/src/libcalamares/geoip/GeoIPJSON.h @@ -45,9 +45,9 @@ public: explicit GeoIPJSON( const QString& attribute = QString() ); virtual RegionZonePair processReply( const QByteArray& ) override; - virtual QString rawReply(const QByteArray & ) override; -} ; + virtual QString rawReply( const QByteArray& ) override; +}; -} -} // namespace +} // namespace GeoIP +} // namespace CalamaresUtils #endif diff --git a/src/libcalamares/geoip/GeoIPXML.cpp b/src/libcalamares/geoip/GeoIPXML.cpp index b658042bf..d84eb3b21 100644 --- a/src/libcalamares/geoip/GeoIPXML.cpp +++ b/src/libcalamares/geoip/GeoIPXML.cpp @@ -48,10 +48,12 @@ getElementTexts( const QByteArray& data, const QString& tag ) cDebug() << "GeoIP found" << tzElements.length() << "elements"; for ( int it = 0; it < tzElements.length(); ++it ) { - auto e = tzElements.at(it).toElement(); + auto e = tzElements.at( it ).toElement(); auto e_text = e.text(); if ( !e_text.isEmpty() ) + { elements.append( e_text ); + } } } else @@ -60,7 +62,9 @@ getElementTexts( const QByteArray& data, const QString& tag ) } if ( elements.count() < 1 ) + { cWarning() << "GeopIP XML had no non-empty elements" << tag; + } return elements; } @@ -71,7 +75,9 @@ GeoIPXML::rawReply( const QByteArray& data ) { for ( const auto& e : getElementTexts( data, m_element ) ) if ( !e.isEmpty() ) + { return e; + } return QString(); } @@ -83,11 +89,13 @@ GeoIPXML::processReply( const QByteArray& data ) { auto tz = splitTZString( e ); if ( !tz.first.isEmpty() ) + { return tz; + } } return RegionZonePair(); } -} -} // namespace +} // namespace GeoIP +} // namespace CalamaresUtils diff --git a/src/libcalamares/geoip/GeoIPXML.h b/src/libcalamares/geoip/GeoIPXML.h index 356e88b12..73147ff91 100644 --- a/src/libcalamares/geoip/GeoIPXML.h +++ b/src/libcalamares/geoip/GeoIPXML.h @@ -45,9 +45,9 @@ public: explicit GeoIPXML( const QString& element = QString() ); virtual RegionZonePair processReply( const QByteArray& ) override; - virtual QString rawReply(const QByteArray & ) override; -} ; + virtual QString rawReply( const QByteArray& ) override; +}; -} -} // namespace +} // namespace GeoIP +} // namespace CalamaresUtils #endif diff --git a/src/libcalamares/geoip/Handler.cpp b/src/libcalamares/geoip/Handler.cpp index 21b88dd4b..6017c404f 100644 --- a/src/libcalamares/geoip/Handler.cpp +++ b/src/libcalamares/geoip/Handler.cpp @@ -19,7 +19,7 @@ #include "Handler.h" #include "GeoIPJSON.h" -#if defined(QT_XML_LIB) +#if defined( QT_XML_LIB ) #include "GeoIPXML.h" #endif @@ -28,8 +28,8 @@ #include "utils/Variant.h" #include -#include #include +#include #include @@ -76,7 +76,7 @@ Handler::Handler( const QString& implementation, const QString& url, const QStri { cWarning() << "GeoIP style *none* does not do anything."; } -#if !defined(QT_XML_LIB) +#if !defined( QT_XML_LIB ) else if ( m_type == Type::XML ) { m_type = Type::None; @@ -85,9 +85,7 @@ Handler::Handler( const QString& implementation, const QString& url, const QStri #endif } -Handler::~Handler() -{ -} +Handler::~Handler() {} static QByteArray synchronous_get( const QString& urlstring ) @@ -108,17 +106,17 @@ synchronous_get( const QString& urlstring ) static std::unique_ptr< Interface > create_interface( Handler::Type t, const QString& selector ) { - switch( t ) + switch ( t ) { - case Handler::Type::None: - return nullptr; - case Handler::Type::JSON: - return std::make_unique< GeoIPJSON >( selector ); - case Handler::Type::XML: -#if defined(QT_XML_LIB) - return std::make_unique< GeoIPXML >( selector ); + case Handler::Type::None: + return nullptr; + case Handler::Type::JSON: + return std::make_unique< GeoIPJSON >( selector ); + case Handler::Type::XML: +#if defined( QT_XML_LIB ) + return std::make_unique< GeoIPXML >( selector ); #else - return nullptr; + return nullptr; #endif } NOTREACHED return nullptr; @@ -129,7 +127,9 @@ do_query( Handler::Type type, const QString& url, const QString& selector ) { const auto interface = create_interface( type, selector ); if ( !interface ) + { return RegionZonePair(); + } return interface->processReply( synchronous_get( url ) ); } @@ -139,7 +139,9 @@ do_raw_query( Handler::Type type, const QString& url, const QString& selector ) { const auto interface = create_interface( type, selector ); if ( !interface ) + { return QString(); + } return interface->rawReply( synchronous_get( url ) ); } @@ -148,7 +150,9 @@ RegionZonePair Handler::get() const { if ( !isValid() ) + { return RegionZonePair(); + } return do_query( m_type, m_url, m_selector ); } @@ -160,17 +164,16 @@ Handler::query() const QString url = m_url; QString selector = m_selector; - return QtConcurrent::run( [=] - { - return do_query( type, url, selector ); - } ); + return QtConcurrent::run( [=] { return do_query( type, url, selector ); } ); } QString Handler::getRaw() const { if ( !isValid() ) + { return QString(); + } return do_raw_query( m_type, m_url, m_selector ); } @@ -182,11 +185,8 @@ Handler::queryRaw() const QString url = m_url; QString selector = m_selector; - return QtConcurrent::run( [=] - { - return do_raw_query( type, url, selector ); - } ); + return QtConcurrent::run( [=] { return do_raw_query( type, url, selector ); } ); } -} -} // namespace +} // namespace GeoIP +} // namespace CalamaresUtils diff --git a/src/libcalamares/geoip/Handler.h b/src/libcalamares/geoip/Handler.h index 8e435b5b7..518964caf 100644 --- a/src/libcalamares/geoip/Handler.h +++ b/src/libcalamares/geoip/Handler.h @@ -21,9 +21,9 @@ #include "Interface.h" -#include #include #include +#include namespace CalamaresUtils { @@ -46,7 +46,7 @@ public: None, JSON, XML - } ; + }; /** @brief An unconfigured handler; this always returns errors. */ Handler(); @@ -89,7 +89,6 @@ private: const QString m_selector; }; -} -} // namespace +} // namespace GeoIP +} // namespace CalamaresUtils #endif - diff --git a/src/libcalamares/geoip/Interface.cpp b/src/libcalamares/geoip/Interface.cpp index 36e680aab..2cecb63c5 100644 --- a/src/libcalamares/geoip/Interface.cpp +++ b/src/libcalamares/geoip/Interface.cpp @@ -25,14 +25,12 @@ namespace CalamaresUtils namespace GeoIP { -Interface::Interface(const QString& e) +Interface::Interface( const QString& e ) : m_element( e ) { } -Interface::~Interface() -{ -} +Interface::~Interface() {} RegionZonePair splitTZString( const QString& tz ) @@ -53,5 +51,5 @@ splitTZString( const QString& tz ) return RegionZonePair( QString(), QString() ); } -} -} // namespace +} // namespace GeoIP +} // namespace CalamaresUtils diff --git a/src/libcalamares/geoip/Interface.h b/src/libcalamares/geoip/Interface.h index 7db8c4c91..1a9beaa41 100644 --- a/src/libcalamares/geoip/Interface.h +++ b/src/libcalamares/geoip/Interface.h @@ -27,7 +27,7 @@ class QByteArray; -namespace CalamaresUtils +namespace CalamaresUtils { namespace GeoIP { @@ -38,18 +38,27 @@ namespace GeoIP * pasting the strings back together with a "/" is the right thing to * do. The Zone **may** contain a "/" (e.g. "Kentucky/Monticello"). */ -class DLLEXPORT RegionZonePair : public QPair +class DLLEXPORT RegionZonePair : public QPair< QString, QString > { public: /** @brief Construct from an existing pair. */ - explicit RegionZonePair( const QPair& p ) : QPair(p) { } + explicit RegionZonePair( const QPair& p ) + : QPair( p ) + { + } /** @brief Construct from two strings, like qMakePair(). */ - RegionZonePair( const QString& region, const QString& zone ) : QPair( region, zone ) { } + RegionZonePair( const QString& region, const QString& zone ) + : QPair( region, zone ) + { + } /** @brief An invalid zone pair (empty strings). */ - RegionZonePair() : QPair( QString(), QString() ) { } + RegionZonePair() + : QPair( QString(), QString() ) + { + } bool isValid() const { return !first.isEmpty(); } -} ; +}; /** @brief Splits a region/zone string into a pair. * @@ -60,8 +69,7 @@ public: * pair of empty QStrings if it can't. (e.g. America/North Dakota/Beulah * will return "America", "North_Dakota/Beulah"). */ -DLLEXPORT RegionZonePair -splitTZString( const QString& s ); +DLLEXPORT RegionZonePair splitTZString( const QString& s ); /** * @brief Interface for GeoIP retrievers. @@ -93,8 +101,8 @@ protected: Interface( const QString& e = QString() ); QString m_element; // string for selecting from data -} ; +}; -} -} // namespace +} // namespace GeoIP +} // namespace CalamaresUtils #endif diff --git a/src/libcalamares/geoip/test_geoip.cpp b/src/libcalamares/geoip/test_geoip.cpp index 5f7ab935c..32c6f4e24 100644 --- a/src/libcalamares/geoip/test_geoip.cpp +++ b/src/libcalamares/geoip/test_geoip.cpp @@ -30,34 +30,40 @@ using std::cerr; using namespace CalamaresUtils::GeoIP; -int main(int argc, char** argv) +int +main( int argc, char** argv ) { - if (argc != 2) + if ( argc != 2 ) { cerr << "Usage: curl url | test_geoip \n"; return 1; } Interface* handler = nullptr; - if ( QStringLiteral( "json" ) == argv[1] ) + if ( QStringLiteral( "json" ) == argv[ 1 ] ) + { handler = new GeoIPJSON; + } #ifdef QT_XML_LIB - else if ( QStringLiteral( "xml" ) == argv[1] ) + else if ( QStringLiteral( "xml" ) == argv[ 1 ] ) + { handler = new GeoIPXML; + } #endif if ( !handler ) { - cerr << "Unknown format '" << argv[1] << "'\n"; + cerr << "Unknown format '" << argv[ 1 ] << "'\n"; return 1; } QByteArray ba; - while( !std::cin.eof() ) { - char arr[1024]; - std::cin.read(arr, sizeof(arr)); - int s = static_cast( std::cin.gcount() ); - ba.append(arr, s); + while ( !std::cin.eof() ) + { + char arr[ 1024 ]; + std::cin.read( arr, sizeof( arr ) ); + int s = static_cast< int >( std::cin.gcount() ); + ba.append( arr, s ); } auto tz = handler->processReply( ba ); @@ -67,7 +73,8 @@ int main(int argc, char** argv) } else { - std::cout << "TimeZone Region=" << tz.first.toLatin1().constData() << "\nTimeZone Zone=" << tz.second.toLatin1().constData() << '\n'; + std::cout << "TimeZone Region=" << tz.first.toLatin1().constData() + << "\nTimeZone Zone=" << tz.second.toLatin1().constData() << '\n'; } return 0; From 839e496fcb3c6309d4337c6d7828ae11f8a344bb Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 8 Aug 2019 12:40:13 +0200 Subject: [PATCH 148/302] CI: when I said 'left' I meant 'dont' --- .clang-format | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.clang-format b/.clang-format index e98283194..cc430e627 100644 --- a/.clang-format +++ b/.clang-format @@ -2,7 +2,7 @@ BasedOnStyle: WebKit AlignAfterOpenBracket: Align -AlignEscapedNewlines: Left +AlignEscapedNewlines: DontAlign AllowAllParametersOfDeclarationOnNextLine: "false" AllowShortFunctionsOnASingleLine: Inline AllowShortIfStatementsOnASingleLine: "false" From 115f5bfd82e3193d90b257b41880e12cc4660da7 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 8 Aug 2019 12:41:41 +0200 Subject: [PATCH 149/302] [libcalamares] Apply coding style to remainder of geoip/ --- src/libcalamares/geoip/GeoIPTests.cpp | 65 +++++++++++++-------------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/src/libcalamares/geoip/GeoIPTests.cpp b/src/libcalamares/geoip/GeoIPTests.cpp index ec7511370..c24b6d98f 100644 --- a/src/libcalamares/geoip/GeoIPTests.cpp +++ b/src/libcalamares/geoip/GeoIPTests.cpp @@ -34,21 +34,16 @@ QTEST_GUILESS_MAIN( GeoIPTests ) using namespace CalamaresUtils::GeoIP; -GeoIPTests::GeoIPTests() -{ -} +GeoIPTests::GeoIPTests() {} -GeoIPTests::~GeoIPTests() -{ -} +GeoIPTests::~GeoIPTests() {} void GeoIPTests::initTestCase() { } -static const char json_data_attribute[] = - "{\"time_zone\":\"Europe/Amsterdam\"}"; +static const char json_data_attribute[] = "{\"time_zone\":\"Europe/Amsterdam\"}"; void GeoIPTests::testJSON() @@ -67,7 +62,8 @@ GeoIPTests::testJSON() QCOMPARE( tz.first, QStringLiteral( "America" ) ); } -void GeoIPTests::testJSONalt() +void +GeoIPTests::testJSONalt() { GeoIPJSON handler( "zona_de_hora" ); @@ -102,7 +98,7 @@ GeoIPTests::testJSONbad() static const char xml_data_ubiquity[] = - R"( + R"( 85.150.1.1 OK NL @@ -133,8 +129,8 @@ GeoIPTests::testXML() void GeoIPTests::testXML2() { - static const char data[] = - "America/North Dakota/Beulah"; // With a space! + static const char data[] + = "America/North Dakota/Beulah"; // With a space! #ifdef QT_XML_LIB GeoIPXML handler; @@ -146,7 +142,8 @@ GeoIPTests::testXML2() } -void GeoIPTests::testXMLalt() +void +GeoIPTests::testXMLalt() { #ifdef QT_XML_LIB GeoIPXML handler( "ZT" ); @@ -173,29 +170,30 @@ GeoIPTests::testXMLbad() #endif } -void GeoIPTests::testSplitTZ() +void +GeoIPTests::testSplitTZ() { using namespace CalamaresUtils::GeoIP; - auto tz = splitTZString( QStringLiteral("Moon/Dark_side") ); - QCOMPARE( tz.first, QStringLiteral("Moon") ); - QCOMPARE( tz.second, QStringLiteral("Dark_side") ); + auto tz = splitTZString( QStringLiteral( "Moon/Dark_side" ) ); + QCOMPARE( tz.first, QStringLiteral( "Moon" ) ); + QCOMPARE( tz.second, QStringLiteral( "Dark_side" ) ); // Some providers return weirdly escaped data - tz = splitTZString( QStringLiteral("America\\/NewYork") ); - QCOMPARE( tz.first, QStringLiteral("America") ); - QCOMPARE( tz.second, QStringLiteral("NewYork") ); // That's not actually the zone name + tz = splitTZString( QStringLiteral( "America\\/NewYork" ) ); + QCOMPARE( tz.first, QStringLiteral( "America" ) ); + QCOMPARE( tz.second, QStringLiteral( "NewYork" ) ); // That's not actually the zone name // Check that bogus data fails tz = splitTZString( QString() ); QCOMPARE( tz.first, QString() ); - tz = splitTZString( QStringLiteral("America.NewYork") ); + tz = splitTZString( QStringLiteral( "America.NewYork" ) ); QCOMPARE( tz.first, QString() ); // Check that three-level is split properly and space is replaced - tz = splitTZString( QStringLiteral("America/North Dakota/Beulah") ); - QCOMPARE( tz.first, QStringLiteral("America") ); - QCOMPARE( tz.second, QStringLiteral("North_Dakota/Beulah") ); + tz = splitTZString( QStringLiteral( "America/North Dakota/Beulah" ) ); + QCOMPARE( tz.first, QStringLiteral( "America" ) ); + QCOMPARE( tz.second, QStringLiteral( "North_Dakota/Beulah" ) ); } @@ -217,19 +215,20 @@ synchronous_get( const char* urlstring ) return reply->readAll(); } -#define CHECK_GET(t, selector, url) \ +#define CHECK_GET( t, selector, url ) \ { \ auto tz = GeoIP##t( selector ).processReply( synchronous_get( url ) ); \ qDebug() << tz; \ QCOMPARE( default_tz, tz ); \ - auto tz2 = CalamaresUtils::GeoIP::Handler( ""#t, url, selector ).get(); \ + auto tz2 = CalamaresUtils::GeoIP::Handler( "" #t, url, selector ).get(); \ qDebug() << tz2; \ QCOMPARE( default_tz, tz2 ); \ } -void GeoIPTests::testGet() +void +GeoIPTests::testGet() { - if ( !QProcessEnvironment::systemEnvironment().contains( QStringLiteral("TEST_HTTP_GET") ) ) + if ( !QProcessEnvironment::systemEnvironment().contains( QStringLiteral( "TEST_HTTP_GET" ) ) ) { qDebug() << "Skipping HTTP GET tests, set TEST_HTTP_GET environment variable to enable"; return; @@ -248,14 +247,14 @@ void GeoIPTests::testGet() // Each expansion of CHECK_GET does a synchronous GET, then checks that // the TZ data is the same as the default_tz; this is fragile if the // services don't agree on the location of where the test is run. - CHECK_GET( JSON, QString(), "https://geoip.kde.org/v1/calamares" ) // Check it's consistent - CHECK_GET( JSON, QStringLiteral("timezone"), "https://ipapi.co/json" ) // Different JSON - CHECK_GET( JSON, QStringLiteral("timezone"), "http://ip-api.com/json" ) + CHECK_GET( JSON, QString(), "https://geoip.kde.org/v1/calamares" ) // Check it's consistent + CHECK_GET( JSON, QStringLiteral( "timezone" ), "https://ipapi.co/json" ) // Different JSON + CHECK_GET( JSON, QStringLiteral( "timezone" ), "http://ip-api.com/json" ) - CHECK_GET( JSON, QStringLiteral("Location.TimeZone"), "https://geoip.kde.org/debug" ) // 2-level JSON + CHECK_GET( JSON, QStringLiteral( "Location.TimeZone" ), "https://geoip.kde.org/debug" ) // 2-level JSON #ifdef QT_XML_LIB CHECK_GET( XML, QString(), "http://geoip.ubuntu.com/lookup" ) // Ubiquity's XML format - CHECK_GET( XML, QString(), "https://geoip.kde.org/v1/ubiquity" ) // Temporary KDE service + CHECK_GET( XML, QString(), "https://geoip.kde.org/v1/ubiquity" ) // Temporary KDE service #endif } From 05bcf4e85335a85f8f8c670696e2b6bb76d44bba Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 8 Aug 2019 13:14:14 +0200 Subject: [PATCH 150/302] Changes: document Coding Style application --- CHANGES | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES b/CHANGES index 9879043dc..dbdcb3523 100644 --- a/CHANGES +++ b/CHANGES @@ -9,6 +9,11 @@ This release contains contributions from (alphabetically by first name): ## Core ## +- The Calamares standard coding style -- embodied in `ci/calamaresstyle` + has had a few updates and has now been consistently applied across + the core codebase (e.g. libcalamares, libcalamaresui, calamares, but + not the modules). + ## Modules ## From 47dbf9ab0c0adfbbca2bc16eed7aed94def269a8 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 8 Aug 2019 10:23:36 -0400 Subject: [PATCH 151/302] [libcalamares] Move 3rd party code to separate dir --- {src/libcalamaresui/utils => 3rdparty}/qjsonitem.cpp | 0 {src/libcalamaresui/utils => 3rdparty}/qjsonitem.h | 0 {src/libcalamaresui/utils => 3rdparty}/qjsonmodel.cpp | 0 {src/libcalamaresui/utils => 3rdparty}/qjsonmodel.h | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename {src/libcalamaresui/utils => 3rdparty}/qjsonitem.cpp (100%) rename {src/libcalamaresui/utils => 3rdparty}/qjsonitem.h (100%) rename {src/libcalamaresui/utils => 3rdparty}/qjsonmodel.cpp (100%) rename {src/libcalamaresui/utils => 3rdparty}/qjsonmodel.h (100%) diff --git a/src/libcalamaresui/utils/qjsonitem.cpp b/3rdparty/qjsonitem.cpp similarity index 100% rename from src/libcalamaresui/utils/qjsonitem.cpp rename to 3rdparty/qjsonitem.cpp diff --git a/src/libcalamaresui/utils/qjsonitem.h b/3rdparty/qjsonitem.h similarity index 100% rename from src/libcalamaresui/utils/qjsonitem.h rename to 3rdparty/qjsonitem.h diff --git a/src/libcalamaresui/utils/qjsonmodel.cpp b/3rdparty/qjsonmodel.cpp similarity index 100% rename from src/libcalamaresui/utils/qjsonmodel.cpp rename to 3rdparty/qjsonmodel.cpp diff --git a/src/libcalamaresui/utils/qjsonmodel.h b/3rdparty/qjsonmodel.h similarity index 100% rename from src/libcalamaresui/utils/qjsonmodel.h rename to 3rdparty/qjsonmodel.h From e7c66de4dff82cf47df836d84e9cba1aee21efb4 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 8 Aug 2019 10:24:18 -0400 Subject: [PATCH 152/302] [libcalamares] Move kdsingleapplicationguard to 3rdparty --- .../kdsingleapplicationguard/LICENSE.LGPL.txt | 0 .../kdsingleapplicationguard/kdlockedsharedmemorypointer.cpp | 0 .../kdsingleapplicationguard/kdlockedsharedmemorypointer.h | 0 .../kdsingleapplicationguard/kdsharedmemorylocker.cpp | 0 .../kdsingleapplicationguard/kdsharedmemorylocker.h | 0 .../kdsingleapplicationguard/kdsingleapplicationguard.cpp | 0 .../kdsingleapplicationguard/kdsingleapplicationguard.h | 0 .../kdsingleapplicationguard/kdtoolsglobal.cpp | 0 .../kdsingleapplicationguard/kdtoolsglobal.h | 0 .../kdsingleapplicationguard/pimpl_ptr.cpp | 0 .../kdsingleapplicationguard/pimpl_ptr.h | 0 11 files changed, 0 insertions(+), 0 deletions(-) rename {src/libcalamares => 3rdparty}/kdsingleapplicationguard/LICENSE.LGPL.txt (100%) rename {src/libcalamares => 3rdparty}/kdsingleapplicationguard/kdlockedsharedmemorypointer.cpp (100%) rename {src/libcalamares => 3rdparty}/kdsingleapplicationguard/kdlockedsharedmemorypointer.h (100%) rename {src/libcalamares => 3rdparty}/kdsingleapplicationguard/kdsharedmemorylocker.cpp (100%) rename {src/libcalamares => 3rdparty}/kdsingleapplicationguard/kdsharedmemorylocker.h (100%) rename {src/libcalamares => 3rdparty}/kdsingleapplicationguard/kdsingleapplicationguard.cpp (100%) rename {src/libcalamares => 3rdparty}/kdsingleapplicationguard/kdsingleapplicationguard.h (100%) rename {src/libcalamares => 3rdparty}/kdsingleapplicationguard/kdtoolsglobal.cpp (100%) rename {src/libcalamares => 3rdparty}/kdsingleapplicationguard/kdtoolsglobal.h (100%) rename {src/libcalamares => 3rdparty}/kdsingleapplicationguard/pimpl_ptr.cpp (100%) rename {src/libcalamares => 3rdparty}/kdsingleapplicationguard/pimpl_ptr.h (100%) diff --git a/src/libcalamares/kdsingleapplicationguard/LICENSE.LGPL.txt b/3rdparty/kdsingleapplicationguard/LICENSE.LGPL.txt similarity index 100% rename from src/libcalamares/kdsingleapplicationguard/LICENSE.LGPL.txt rename to 3rdparty/kdsingleapplicationguard/LICENSE.LGPL.txt diff --git a/src/libcalamares/kdsingleapplicationguard/kdlockedsharedmemorypointer.cpp b/3rdparty/kdsingleapplicationguard/kdlockedsharedmemorypointer.cpp similarity index 100% rename from src/libcalamares/kdsingleapplicationguard/kdlockedsharedmemorypointer.cpp rename to 3rdparty/kdsingleapplicationguard/kdlockedsharedmemorypointer.cpp diff --git a/src/libcalamares/kdsingleapplicationguard/kdlockedsharedmemorypointer.h b/3rdparty/kdsingleapplicationguard/kdlockedsharedmemorypointer.h similarity index 100% rename from src/libcalamares/kdsingleapplicationguard/kdlockedsharedmemorypointer.h rename to 3rdparty/kdsingleapplicationguard/kdlockedsharedmemorypointer.h diff --git a/src/libcalamares/kdsingleapplicationguard/kdsharedmemorylocker.cpp b/3rdparty/kdsingleapplicationguard/kdsharedmemorylocker.cpp similarity index 100% rename from src/libcalamares/kdsingleapplicationguard/kdsharedmemorylocker.cpp rename to 3rdparty/kdsingleapplicationguard/kdsharedmemorylocker.cpp diff --git a/src/libcalamares/kdsingleapplicationguard/kdsharedmemorylocker.h b/3rdparty/kdsingleapplicationguard/kdsharedmemorylocker.h similarity index 100% rename from src/libcalamares/kdsingleapplicationguard/kdsharedmemorylocker.h rename to 3rdparty/kdsingleapplicationguard/kdsharedmemorylocker.h diff --git a/src/libcalamares/kdsingleapplicationguard/kdsingleapplicationguard.cpp b/3rdparty/kdsingleapplicationguard/kdsingleapplicationguard.cpp similarity index 100% rename from src/libcalamares/kdsingleapplicationguard/kdsingleapplicationguard.cpp rename to 3rdparty/kdsingleapplicationguard/kdsingleapplicationguard.cpp diff --git a/src/libcalamares/kdsingleapplicationguard/kdsingleapplicationguard.h b/3rdparty/kdsingleapplicationguard/kdsingleapplicationguard.h similarity index 100% rename from src/libcalamares/kdsingleapplicationguard/kdsingleapplicationguard.h rename to 3rdparty/kdsingleapplicationguard/kdsingleapplicationguard.h diff --git a/src/libcalamares/kdsingleapplicationguard/kdtoolsglobal.cpp b/3rdparty/kdsingleapplicationguard/kdtoolsglobal.cpp similarity index 100% rename from src/libcalamares/kdsingleapplicationguard/kdtoolsglobal.cpp rename to 3rdparty/kdsingleapplicationguard/kdtoolsglobal.cpp diff --git a/src/libcalamares/kdsingleapplicationguard/kdtoolsglobal.h b/3rdparty/kdsingleapplicationguard/kdtoolsglobal.h similarity index 100% rename from src/libcalamares/kdsingleapplicationguard/kdtoolsglobal.h rename to 3rdparty/kdsingleapplicationguard/kdtoolsglobal.h diff --git a/src/libcalamares/kdsingleapplicationguard/pimpl_ptr.cpp b/3rdparty/kdsingleapplicationguard/pimpl_ptr.cpp similarity index 100% rename from src/libcalamares/kdsingleapplicationguard/pimpl_ptr.cpp rename to 3rdparty/kdsingleapplicationguard/pimpl_ptr.cpp diff --git a/src/libcalamares/kdsingleapplicationguard/pimpl_ptr.h b/3rdparty/kdsingleapplicationguard/pimpl_ptr.h similarity index 100% rename from src/libcalamares/kdsingleapplicationguard/pimpl_ptr.h rename to 3rdparty/kdsingleapplicationguard/pimpl_ptr.h From 937ff608ebc7ab74f3c5a6a17e8849cc6e1b7c9a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 8 Aug 2019 10:27:52 -0400 Subject: [PATCH 153/302] [libcalamaresui] Move spinner widget to 3rd party --- {src/libcalamaresui/widgets => 3rdparty}/waitingspinnerwidget.cpp | 0 {src/libcalamaresui/widgets => 3rdparty}/waitingspinnerwidget.h | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {src/libcalamaresui/widgets => 3rdparty}/waitingspinnerwidget.cpp (100%) rename {src/libcalamaresui/widgets => 3rdparty}/waitingspinnerwidget.h (100%) diff --git a/src/libcalamaresui/widgets/waitingspinnerwidget.cpp b/3rdparty/waitingspinnerwidget.cpp similarity index 100% rename from src/libcalamaresui/widgets/waitingspinnerwidget.cpp rename to 3rdparty/waitingspinnerwidget.cpp diff --git a/src/libcalamaresui/widgets/waitingspinnerwidget.h b/3rdparty/waitingspinnerwidget.h similarity index 100% rename from src/libcalamaresui/widgets/waitingspinnerwidget.h rename to 3rdparty/waitingspinnerwidget.h From 315c0aca1563b31c7da2ae976a8bf09713050342 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 8 Aug 2019 10:29:21 -0400 Subject: [PATCH 154/302] [3rdparty] Not actually part of Calamares --- 3rdparty/qjsonitem.cpp | 3 +-- 3rdparty/qjsonitem.h | 3 +-- 3rdparty/qjsonmodel.cpp | 3 +-- 3rdparty/qjsonmodel.h | 3 +-- 3rdparty/waitingspinnerwidget.cpp | 3 +-- 3rdparty/waitingspinnerwidget.h | 3 +-- 6 files changed, 6 insertions(+), 12 deletions(-) diff --git a/3rdparty/qjsonitem.cpp b/3rdparty/qjsonitem.cpp index cdc4b3b13..6bb1fa4c7 100644 --- a/3rdparty/qjsonitem.cpp +++ b/3rdparty/qjsonitem.cpp @@ -1,5 +1,4 @@ -/* === This file is part of Calamares - === - * +/* * SPDX-License-Identifier: GPL-3.0+ * License-Filename: LICENSES/GPLv3+-QJsonModel */ diff --git a/3rdparty/qjsonitem.h b/3rdparty/qjsonitem.h index 113c9da97..137c59000 100644 --- a/3rdparty/qjsonitem.h +++ b/3rdparty/qjsonitem.h @@ -1,5 +1,4 @@ -/* === This file is part of Calamares - === - * +/* * SPDX-License-Identifier: GPL-3.0+ * License-Filename: LICENSES/GPLv3+-QJsonModel */ diff --git a/3rdparty/qjsonmodel.cpp b/3rdparty/qjsonmodel.cpp index 4238bfd6b..020d27e42 100644 --- a/3rdparty/qjsonmodel.cpp +++ b/3rdparty/qjsonmodel.cpp @@ -1,5 +1,4 @@ -/* === This file is part of Calamares - === - * +/* * SPDX-License-Identifier: GPL-3.0+ * License-Filename: LICENSES/GPLv3+-QJsonModel */ diff --git a/3rdparty/qjsonmodel.h b/3rdparty/qjsonmodel.h index fc2c4abe1..32c062ba8 100644 --- a/3rdparty/qjsonmodel.h +++ b/3rdparty/qjsonmodel.h @@ -1,5 +1,4 @@ -/* === This file is part of Calamares - === - * +/* * SPDX-License-Identifier: GPL-3.0+ * License-Filename: LICENSES/GPLv3+-QJsonModel */ diff --git a/3rdparty/waitingspinnerwidget.cpp b/3rdparty/waitingspinnerwidget.cpp index 317d83807..45c689019 100644 --- a/3rdparty/waitingspinnerwidget.cpp +++ b/3rdparty/waitingspinnerwidget.cpp @@ -1,5 +1,4 @@ -/* === This file is part of Calamares - === - * +/* * SPDX-License-Identifier: MIT * License-Filename: LICENSES/MIT-QtWaitingSpinner */ diff --git a/3rdparty/waitingspinnerwidget.h b/3rdparty/waitingspinnerwidget.h index d71976ef8..b3e8df9a0 100644 --- a/3rdparty/waitingspinnerwidget.h +++ b/3rdparty/waitingspinnerwidget.h @@ -1,5 +1,4 @@ -/* === This file is part of Calamares - === - * +/* * SPDX-License-Identifier: MIT * License-Filename: LICENSES/MIT-QtWaitingSpinner */ From 8050b5d1da405c80910aa5a13781856b14dace2f Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 8 Aug 2019 10:37:02 -0400 Subject: [PATCH 155/302] [3rdparty] Add License information for kdsingleapplicationguard --- .../kdlockedsharedmemorypointer.cpp | 6 + .../kdlockedsharedmemorypointer.h | 8 +- .../kdsharedmemorylocker.cpp | 6 + .../kdsharedmemorylocker.h | 6 + .../kdsingleapplicationguard.cpp | 6 + .../kdsingleapplicationguard.h | 6 + .../kdtoolsglobal.cpp | 6 + .../kdsingleapplicationguard/kdtoolsglobal.h | 6 + .../kdsingleapplicationguard/pimpl_ptr.cpp | 14 +- 3rdparty/kdsingleapplicationguard/pimpl_ptr.h | 6 + LICENSES/LGPLv2-KDAB | 488 ++++++++++++++++++ 11 files changed, 553 insertions(+), 5 deletions(-) create mode 100644 LICENSES/LGPLv2-KDAB diff --git a/3rdparty/kdsingleapplicationguard/kdlockedsharedmemorypointer.cpp b/3rdparty/kdsingleapplicationguard/kdlockedsharedmemorypointer.cpp index 56ab8ebe4..77e95e649 100644 --- a/3rdparty/kdsingleapplicationguard/kdlockedsharedmemorypointer.cpp +++ b/3rdparty/kdsingleapplicationguard/kdlockedsharedmemorypointer.cpp @@ -1,3 +1,9 @@ +/* + * SPDX-License-Identifier: LGPL-2.0-only + * License-Filename: LICENSES/LGPLv2-KDAB + * + * The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. + */ #include "kdlockedsharedmemorypointer.h" #if QT_VERSION >= 0x040400 || defined( DOXYGEN_RUN ) diff --git a/3rdparty/kdsingleapplicationguard/kdlockedsharedmemorypointer.h b/3rdparty/kdsingleapplicationguard/kdlockedsharedmemorypointer.h index df0ea4998..b9c5d588f 100644 --- a/3rdparty/kdsingleapplicationguard/kdlockedsharedmemorypointer.h +++ b/3rdparty/kdsingleapplicationguard/kdlockedsharedmemorypointer.h @@ -1,3 +1,9 @@ +/* + * SPDX-License-Identifier: LGPL-2.0-only + * License-Filename: LICENSES/LGPLv2-KDAB + * + * The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. + */ #ifndef __KDTOOLS__CORE__KDLOCKEDSHAREDMEMORYPOINTER_H__ #define __KDTOOLS__CORE__KDLOCKEDSHAREDMEMORYPOINTER_H__ @@ -74,7 +80,7 @@ public: typedef const T* const_iterator; typedef std::reverse_iterator< const_iterator > const_reverse_iterator; typedef std::reverse_iterator< iterator > reverse_iterator; - + iterator begin() { return get(); } const_iterator begin() const { return get(); } diff --git a/3rdparty/kdsingleapplicationguard/kdsharedmemorylocker.cpp b/3rdparty/kdsingleapplicationguard/kdsharedmemorylocker.cpp index 0c99b8fff..a13a45a27 100644 --- a/3rdparty/kdsingleapplicationguard/kdsharedmemorylocker.cpp +++ b/3rdparty/kdsingleapplicationguard/kdsharedmemorylocker.cpp @@ -1,3 +1,9 @@ +/* + * SPDX-License-Identifier: LGPL-2.0-only + * License-Filename: LICENSES/LGPLv2-KDAB + * + * The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. + */ #include "kdsharedmemorylocker.h" #if QT_VERSION >= 0x040400 || defined( DOXYGEN_RUN ) diff --git a/3rdparty/kdsingleapplicationguard/kdsharedmemorylocker.h b/3rdparty/kdsingleapplicationguard/kdsharedmemorylocker.h index 7ae83e771..82b759283 100644 --- a/3rdparty/kdsingleapplicationguard/kdsharedmemorylocker.h +++ b/3rdparty/kdsingleapplicationguard/kdsharedmemorylocker.h @@ -1,3 +1,9 @@ +/* + * SPDX-License-Identifier: LGPL-2.0-only + * License-Filename: LICENSES/LGPLv2-KDAB + * + * The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. + */ #ifndef __KDTOOLS__CORE__KDSHAREDMEMORYLOCKER_H #define __KDTOOLS__CORE__KDSHAREDMEMORYLOCKER_H diff --git a/3rdparty/kdsingleapplicationguard/kdsingleapplicationguard.cpp b/3rdparty/kdsingleapplicationguard/kdsingleapplicationguard.cpp index ea8ccce33..4c13e1da0 100644 --- a/3rdparty/kdsingleapplicationguard/kdsingleapplicationguard.cpp +++ b/3rdparty/kdsingleapplicationguard/kdsingleapplicationguard.cpp @@ -1,3 +1,9 @@ +/* + * SPDX-License-Identifier: LGPL-2.0-only + * License-Filename: LICENSES/LGPLv2-KDAB + * + * The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. + */ #include "kdsingleapplicationguard.h" #if QT_VERSION >= 0x040400 || defined(DOXYGEN_RUN) diff --git a/3rdparty/kdsingleapplicationguard/kdsingleapplicationguard.h b/3rdparty/kdsingleapplicationguard/kdsingleapplicationguard.h index d529fdb3e..8ac411a68 100644 --- a/3rdparty/kdsingleapplicationguard/kdsingleapplicationguard.h +++ b/3rdparty/kdsingleapplicationguard/kdsingleapplicationguard.h @@ -1,3 +1,9 @@ +/* + * SPDX-License-Identifier: LGPL-2.0-only + * License-Filename: LICENSES/LGPLv2-KDAB + * + * The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. + */ #ifndef KDTOOLSCORE_KDSINGLEAPPLICATIONGUARD_H #define KDTOOLSCORE_KDSINGLEAPPLICATIONGUARD_H diff --git a/3rdparty/kdsingleapplicationguard/kdtoolsglobal.cpp b/3rdparty/kdsingleapplicationguard/kdtoolsglobal.cpp index f530cc85b..d3405e82f 100644 --- a/3rdparty/kdsingleapplicationguard/kdtoolsglobal.cpp +++ b/3rdparty/kdsingleapplicationguard/kdtoolsglobal.cpp @@ -1,3 +1,9 @@ +/* + * SPDX-License-Identifier: LGPL-2.0-only + * License-Filename: LICENSES/LGPLv2-KDAB + * + * The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. + */ #include "kdtoolsglobal.h" #include diff --git a/3rdparty/kdsingleapplicationguard/kdtoolsglobal.h b/3rdparty/kdsingleapplicationguard/kdtoolsglobal.h index c0e37ac76..37ca5857e 100644 --- a/3rdparty/kdsingleapplicationguard/kdtoolsglobal.h +++ b/3rdparty/kdsingleapplicationguard/kdtoolsglobal.h @@ -1,3 +1,9 @@ +/* + * SPDX-License-Identifier: LGPL-2.0-only + * License-Filename: LICENSES/LGPLv2-KDAB + * + * The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. + */ #ifndef KDTOOLS_KDTOOLSGLOBAL_H #define KDTOOLS_KDTOOLSGLOBAL_H diff --git a/3rdparty/kdsingleapplicationguard/pimpl_ptr.cpp b/3rdparty/kdsingleapplicationguard/pimpl_ptr.cpp index 3045ebc2a..35b52d419 100644 --- a/3rdparty/kdsingleapplicationguard/pimpl_ptr.cpp +++ b/3rdparty/kdsingleapplicationguard/pimpl_ptr.cpp @@ -1,3 +1,9 @@ +/* + * SPDX-License-Identifier: LGPL-2.0-only + * License-Filename: LICENSES/LGPLv2-KDAB + * + * The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. + */ #include "pimpl_ptr.h" /*! @@ -9,7 +15,7 @@ (The exception safety of this class has not been evaluated yet.) pimpl_ptr is a smart immutable pointer, which owns the contained object. Unlike other smart pointers, - it creates a standard constructed object when instanciated via the + it creates a standard constructed object when instanciated via the \link pimpl_ptr() standard constructor\endlink. Additionally, pimpl_ptr respects constness of the pointer object and returns \c const \c T* for a const pimpl_ptr object. @@ -126,7 +132,7 @@ */ /*! - \fn T * pimpl_ptr::operator->() + \fn T * pimpl_ptr::operator->() Member-by-pointer operator. Returns get(). */ @@ -163,7 +169,7 @@ KDAB_UNITTEST_SIMPLE( pimpl_ptr, "kdcoretools" ) { } - { + { QPointer< QObject > o; { kdtools::pimpl_ptr< QObject > qobject( new QObject ); @@ -174,7 +180,7 @@ KDAB_UNITTEST_SIMPLE( pimpl_ptr, "kdcoretools" ) { assertNull( o ); } - { + { const kdtools::pimpl_ptr< QObject > qobject( new QObject ); const QObject* o = qobject.get(); assertEqual( o, qobject.operator->() ); diff --git a/3rdparty/kdsingleapplicationguard/pimpl_ptr.h b/3rdparty/kdsingleapplicationguard/pimpl_ptr.h index b66bd11a2..41b33b582 100644 --- a/3rdparty/kdsingleapplicationguard/pimpl_ptr.h +++ b/3rdparty/kdsingleapplicationguard/pimpl_ptr.h @@ -1,3 +1,9 @@ +/* + * SPDX-License-Identifier: LGPL-2.0-only + * License-Filename: LICENSES/LGPLv2-KDAB + * + * The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. + */ #ifndef KDTOOLSCORE_PIMPL_PTR_H #define KDTOOLSCORE_PIMPL_PTR_H diff --git a/LICENSES/LGPLv2-KDAB b/LICENSES/LGPLv2-KDAB new file mode 100644 index 000000000..df942b1ff --- /dev/null +++ b/LICENSES/LGPLv2-KDAB @@ -0,0 +1,488 @@ + + The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. + + You may use, distribute and copy the KD Tools Library under the terms of + GNU Library General Public License version 2, which is displayed below. + +------------------------------------------------------------------------- + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! From 2166eb45116d66020fe1d999ed863ca646e4b2b5 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 8 Aug 2019 10:47:14 -0400 Subject: [PATCH 156/302] [libcalamares] [libcalamaresui] Adjust for moved sources --- src/libcalamares/CMakeLists.txt | 6 +++++- src/libcalamaresui/CMakeLists.txt | 13 ++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/libcalamares/CMakeLists.txt b/src/libcalamares/CMakeLists.txt index 0aca79233..790d4b6ac 100644 --- a/src/libcalamares/CMakeLists.txt +++ b/src/libcalamares/CMakeLists.txt @@ -51,12 +51,16 @@ set( libSources utils/Variant.cpp utils/Yaml.cpp ) -set( kdsagSources +set( _kdsagSources kdsingleapplicationguard/kdsingleapplicationguard.cpp kdsingleapplicationguard/kdsharedmemorylocker.cpp kdsingleapplicationguard/kdtoolsglobal.cpp kdsingleapplicationguard/kdlockedsharedmemorypointer.cpp ) +set( kdsagSources "" ) +foreach( _s ${_kdsagSources} ) + list( APPEND kdsagSources ${CMAKE_SOURCE_DIR}/3rdparty/${_s} ) +endforeach() mark_thirdparty_code( ${kdsagSources} ) include_directories( diff --git a/src/libcalamaresui/CMakeLists.txt b/src/libcalamaresui/CMakeLists.txt index 703a8bbe1..f5389069d 100644 --- a/src/libcalamaresui/CMakeLists.txt +++ b/src/libcalamaresui/CMakeLists.txt @@ -18,16 +18,16 @@ set( calamaresui_SOURCES utils/ImageRegistry.cpp utils/Paste.cpp - utils/qjsonmodel.cpp - utils/qjsonitem.cpp + ${CMAKE_SOURCE_DIR}/3rdparty/qjsonmodel.cpp + ${CMAKE_SOURCE_DIR}/3rdparty/qjsonitem.cpp viewpages/BlankViewStep.cpp viewpages/ViewStep.cpp widgets/ClickableLabel.cpp widgets/FixedAspectRatioLabel.cpp - widgets/waitingspinnerwidget.cpp widgets/WaitingWidget.cpp + ${CMAKE_SOURCE_DIR}/3rdparty/waitingspinnerwidget.cpp ExecutionViewStep.cpp Branding.cpp @@ -36,10 +36,9 @@ set( calamaresui_SOURCES # Don't warn about third-party sources mark_thirdparty_code( - utils/ImageRegistry.cpp - utils/qjsonitem.cpp - utils/qjsonmodel.cpp - widgets/waitingspinnerwidget.cpp + ${CMAKE_SOURCE_DIR}/3rdparty/qjsonitem.cpp + ${CMAKE_SOURCE_DIR}/3rdparty/qjsonmodel.cpp + ${CMAKE_SOURCE_DIR}/3rdparty/waitingspinnerwidget.cpp ) set( calamaresui_UI From c83e95e66a47fa798916a110e98d16ab3bc3bf5b Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 8 Aug 2019 12:42:02 -0400 Subject: [PATCH 157/302] [libcalamaresui] Chase 3rdparty move - Widgets need to #include from different path --- src/libcalamaresui/CMakeLists.txt | 2 +- src/libcalamaresui/utils/DebugWindow.cpp | 5 +++-- src/libcalamaresui/widgets/WaitingWidget.cpp | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libcalamaresui/CMakeLists.txt b/src/libcalamaresui/CMakeLists.txt index f5389069d..04565206e 100644 --- a/src/libcalamaresui/CMakeLists.txt +++ b/src/libcalamaresui/CMakeLists.txt @@ -2,7 +2,7 @@ # view modules, view steps, widgets, and branding. # The UI libs use the non-UI library -include_directories( ${CMAKE_SOURCE_DIR}/src/libcalamares ${CMAKE_BINARY_DIR}/src/libcalamares ) +include_directories( ${CMAKE_SOURCE_DIR}/src/libcalamares ${CMAKE_BINARY_DIR}/src/libcalamares ${CMAKE_SOURCE_DIR} ) set( calamaresui_SOURCES modulesystem/CppJobModule.cpp diff --git a/src/libcalamaresui/utils/DebugWindow.cpp b/src/libcalamaresui/utils/DebugWindow.cpp index ed016dd97..094511be4 100644 --- a/src/libcalamaresui/utils/DebugWindow.cpp +++ b/src/libcalamaresui/utils/DebugWindow.cpp @@ -23,7 +23,6 @@ #include "Branding.h" #include "modulesystem/Module.h" #include "modulesystem/ModuleManager.h" -#include "utils/qjsonmodel.h" #include "GlobalStorage.h" #include "Job.h" @@ -31,11 +30,13 @@ #include "utils/Logger.h" #include "utils/Retranslator.h" +#include "3rdparty/qjsonmodel.h" #ifdef WITH_PYTHONQT -#include #include "ViewManager.h" #include "viewpages/PythonQtViewStep.h" + +#include #endif #include diff --git a/src/libcalamaresui/widgets/WaitingWidget.cpp b/src/libcalamaresui/widgets/WaitingWidget.cpp index 286c611ab..1a658b35b 100644 --- a/src/libcalamaresui/widgets/WaitingWidget.cpp +++ b/src/libcalamaresui/widgets/WaitingWidget.cpp @@ -20,7 +20,8 @@ #include "WaitingWidget.h" #include "utils/CalamaresUtilsGui.h" -#include "waitingspinnerwidget.h" + +#include "3rdparty/waitingspinnerwidget.h" #include #include From b31c6c3a22801e189080929625e00750db720e13 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 8 Aug 2019 12:42:33 -0400 Subject: [PATCH 158/302] [calamares] Chase 3rdparty move --- src/calamares/CMakeLists.txt | 5 +++-- src/calamares/main.cpp | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/calamares/CMakeLists.txt b/src/calamares/CMakeLists.txt index 5159916e8..5dbf137bb 100644 --- a/src/calamares/CMakeLists.txt +++ b/src/calamares/CMakeLists.txt @@ -17,8 +17,9 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/../libcalamares - ../libcalamares - ../libcalamaresui + ${CMAKE_SOURCE_DIR}/src/libcalamares + ${CMAKE_SOURCE_DIR}/src//libcalamaresui + ${CMAKE_SOURCE_DIR} ) # Translations diff --git a/src/calamares/main.cpp b/src/calamares/main.cpp index d463b789d..704c2bf59 100644 --- a/src/calamares/main.cpp +++ b/src/calamares/main.cpp @@ -21,10 +21,11 @@ #include "CalamaresApplication.h" #include "CalamaresConfig.h" -#include "kdsingleapplicationguard/kdsingleapplicationguard.h" #include "utils/Dirs.h" #include "utils/Logger.h" +#include "3rdparty/kdsingleapplicationguard/kdsingleapplicationguard.h" + #ifdef WITH_KF5Crash #include #include From 48a25858f0d08849449754c4dfcc231cdf8e89f2 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 8 Aug 2019 12:42:47 -0400 Subject: [PATCH 159/302] [partition] Chase 3rdparty move --- src/modules/partition/CMakeLists.txt | 2 ++ src/modules/partition/gui/ScanningDialog.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/modules/partition/CMakeLists.txt b/src/modules/partition/CMakeLists.txt index 61953c249..df1588cb2 100644 --- a/src/modules/partition/CMakeLists.txt +++ b/src/modules/partition/CMakeLists.txt @@ -5,6 +5,8 @@ option( DEBUG_PARTITION_UNSAFE "Allow unsafe partitioning choices." OFF ) option( DEBUG_PARTITION_LAME "Unsafe partitioning will error out on exec." ON ) +include_directories( ${CMAKE_SOURCE_DIR} ) # For 3rdparty + set( _partition_defs ) if( DEBUG_PARTITION_UNSAFE ) if( DEBUG_PARTITION_LAME ) diff --git a/src/modules/partition/gui/ScanningDialog.cpp b/src/modules/partition/gui/ScanningDialog.cpp index 9084be2cc..85479fbb3 100644 --- a/src/modules/partition/gui/ScanningDialog.cpp +++ b/src/modules/partition/gui/ScanningDialog.cpp @@ -19,7 +19,7 @@ #include "ScanningDialog.h" -#include "widgets/waitingspinnerwidget.h" +#include "3rdparty/waitingspinnerwidget.h" #include #include From 0d74bd368954b5ac5e40a136999ec506c929cc5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Thu, 8 Aug 2019 23:01:19 +0200 Subject: [PATCH 160/302] [officechooser] fix conf --- src/modules/officechooser/officechooser.conf | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/modules/officechooser/officechooser.conf b/src/modules/officechooser/officechooser.conf index b90571a85..3cfc5ad6a 100644 --- a/src/modules/officechooser/officechooser.conf +++ b/src/modules/officechooser/officechooser.conf @@ -66,14 +66,14 @@ items: name: "No Office Suite" description: "Please pick an office suite from the list. If you don't want to install an office suite, that's fine, you can install one later as needed." screenshot: ":/images/choose-office.jpg" - - id: libreoffice-still - package: libreoffice-still - name: LibreOffice + - id: "libreoffice-still" + package: "libreoffice-still" + name: "LibreOffice" description: "LibreOffice is a powerful and free office suite, used by millions of people around the world. Its clean interface and feature-rich tools help you unleash your creativity and enhance your productivity." screenshot: ":/images/LibreOffice.jpg" - - id: freeoffice - package: freeoffice - name: FreeOffice - description: "FreeOffice 2018 is a full-featured Office suite with word processing, spreadsheet and presentation software. It is seamlessly compatible with Microsoft Office. (Note: You need to register the product for free longterm usage) + - id: "freeoffice" + package: "freeoffice" + name: "FreeOffice" + description: "FreeOffice 2018 is a full-featured Office suite with word processing, spreadsheet and presentation software. It is seamlessly compatible with Microsoft Office. (Note: You need to register the product for free longterm usage)" screenshot: ":/images/FreeOffice.jpg" From dce9b215af6873eca3cf0d6a94c84a114eb71db1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Fri, 9 Aug 2019 06:40:39 +0200 Subject: [PATCH 161/302] [officechooser] Drop hard-coded data --- .../officechooser/PackageChooserViewStep.cpp | 26 ------------------- src/modules/officechooser/Tests.cpp | 20 ++++++++++---- 2 files changed, 15 insertions(+), 31 deletions(-) diff --git a/src/modules/officechooser/PackageChooserViewStep.cpp b/src/modules/officechooser/PackageChooserViewStep.cpp index 6c559e94c..5443992c5 100644 --- a/src/modules/officechooser/PackageChooserViewStep.cpp +++ b/src/modules/officechooser/PackageChooserViewStep.cpp @@ -184,32 +184,6 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap fillModel( configurationMap.value( "items" ).toList() ); } - // TODO: replace this hard-coded model - if ( !m_model ) - { - m_model = new PackageListModel( nullptr ); - m_model->addPackage( PackageItem { QString(), - QString(), - "No Office Suite", - "Please pick an office suite from the list. " - "If you don't want to install an office suite, that's fine, " - "you can install one later as needed.", - ":/images/choose-office.jpg" } ); - m_model->addPackage( PackageItem { "libreoffice-still", - "libreoffice-still", - "LibreOffice", - "LibreOffice is a powerful and free office suite, used by millions of people around the world. " - "Its clean interface and feature-rich tools help you unleash your creativity and enhance your productivity.", - ":/images/LibreOffice.jpg" } ); - m_model->addPackage( PackageItem { "freeoffice", - "freeoffice", - "FreeOffice", - "FreeOffice 2018 is a full-featured Office suite with word processing, " - "spreadsheet and presentation software. It is seamlessly compatible with Microsoft Office. " - "(Note: You need to register the product for free longterm usage)", - ":/images/FreeOffice.jpg" } ); - } - if ( first_time && m_widget && m_model ) { hookupModel(); diff --git a/src/modules/officechooser/Tests.cpp b/src/modules/officechooser/Tests.cpp index 3e7961b92..537ecbd3c 100644 --- a/src/modules/officechooser/Tests.cpp +++ b/src/modules/officechooser/Tests.cpp @@ -45,13 +45,23 @@ PackageChooserTests::testBogus() void PackageChooserTests::testAppData() { - // Path from the build-dir - QString appdataName( "../io.calamares.calamares.appdata.xml" ); + // Path from the build-dir and from the running-the-test varies, + // for in-source build, for build/, and for tests-in-build/, + // so look in multiple places. + QString appdataName( "io.calamares.calamares.appdata.xml" ); + for ( const auto& prefix : QStringList { "", "../", "../../../", "../../../../" } ) + { + if ( QFile::exists( prefix + appdataName ) ) + { + appdataName = prefix + appdataName; + break; + } + } QVERIFY( QFile::exists( appdataName ) ); QVariantMap m; m.insert( "appdata", appdataName ); - + PackageItem p1 = PackageItem::fromAppData( m ); #ifdef HAVE_XML QVERIFY( p1.isValid() ); @@ -63,10 +73,10 @@ PackageChooserTests::testAppData() QCOMPARE( p1.description.get( QLocale( "en_GB" ) ), "Calamares Linux Installer" ); QCOMPARE( p1.description.get( QLocale( "nl" ) ), "Calamares is een installatieprogramma voor Linux distributies." ); QVERIFY( p1.screenshot.isNull() ); - + m.insert( "id", "calamares" ); m.insert( "screenshot", ":/images/calamares.png" ); - PackageItem p2= PackageItem::fromAppData( m ); + PackageItem p2 = PackageItem::fromAppData( m ); QVERIFY( p2.isValid() ); QCOMPARE( p2.id, "calamares" ); QCOMPARE( p2.description.get( QLocale( "nl" ) ), "Calamares is een installatieprogramma voor Linux distributies." ); From 17dfe02d2826e7bb8154f672599978af66844db4 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 05:53:18 -0400 Subject: [PATCH 162/302] [3rdparty] Remove QJsonModel and support --- 3rdparty/qjsonitem.cpp | 140 ---------------------------- 3rdparty/qjsonitem.h | 46 --------- 3rdparty/qjsonmodel.cpp | 186 ------------------------------------- 3rdparty/qjsonmodel.h | 42 --------- LICENSES/GPLv3+-QJsonModel | 18 ---- 5 files changed, 432 deletions(-) delete mode 100644 3rdparty/qjsonitem.cpp delete mode 100644 3rdparty/qjsonitem.h delete mode 100644 3rdparty/qjsonmodel.cpp delete mode 100644 3rdparty/qjsonmodel.h delete mode 100644 LICENSES/GPLv3+-QJsonModel diff --git a/3rdparty/qjsonitem.cpp b/3rdparty/qjsonitem.cpp deleted file mode 100644 index 6bb1fa4c7..000000000 --- a/3rdparty/qjsonitem.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-3.0+ - * License-Filename: LICENSES/GPLv3+-QJsonModel - */ - -/*********************************************** - Copyright (C) 2014 Schutz Sacha - This file is part of QJsonModel (https://github.com/dridk/QJsonmodel). - - QJsonModel 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. - - QJsonModel 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 QJsonModel. If not, see . - -**********************************************/ - -#include "qjsonitem.h" - -QJsonTreeItem::QJsonTreeItem(QJsonTreeItem *parent) - : mParent( parent ) - , mType( QJsonValue::Type::Null ) -{ -} - -QJsonTreeItem::~QJsonTreeItem() -{ - qDeleteAll(mChilds); - -} - -void QJsonTreeItem::appendChild(QJsonTreeItem *item) -{ - mChilds.append(item); -} - -QJsonTreeItem *QJsonTreeItem::child(int row) -{ - return mChilds.value(row); -} - -QJsonTreeItem *QJsonTreeItem::parent() -{ - return mParent; -} - -int QJsonTreeItem::childCount() const -{ - return mChilds.count(); -} - -int QJsonTreeItem::row() const -{ - if (mParent) - return mParent->mChilds.indexOf(const_cast(this)); - - return 0; -} - -void QJsonTreeItem::setKey(const QString &key) -{ - mKey = key; -} - -void QJsonTreeItem::setValue(const QString &value) -{ - mValue = value; -} - -void QJsonTreeItem::setType(const QJsonValue::Type &type) -{ - mType = type; -} - -QString QJsonTreeItem::key() const -{ - return mKey; -} - -QString QJsonTreeItem::value() const -{ - return mValue; -} - -QJsonValue::Type QJsonTreeItem::type() const -{ - return mType; -} - -QJsonTreeItem* QJsonTreeItem::load(const QJsonValue& value, QJsonTreeItem* parent) -{ - - - QJsonTreeItem * rootItem = new QJsonTreeItem(parent); - rootItem->setKey("root"); - - if ( value.isObject()) - { - - //Get all QJsonValue childs - foreach (QString key , value.toObject().keys()){ - QJsonValue v = value.toObject().value(key); - QJsonTreeItem * child = load(v,rootItem); - child->setKey(key); - child->setType(v.type()); - rootItem->appendChild(child); - - } - - } - - else if ( value.isArray()) - { - //Get all QJsonValue childs - int index = 0; - foreach (QJsonValue v , value.toArray()){ - - QJsonTreeItem * child = load(v,rootItem); - child->setKey(QString::number(index)); - child->setType(v.type()); - rootItem->appendChild(child); - ++index; - } - } - else - { - rootItem->setValue(value.toVariant().toString()); - rootItem->setType(value.type()); - } - - return rootItem; -} - diff --git a/3rdparty/qjsonitem.h b/3rdparty/qjsonitem.h deleted file mode 100644 index 137c59000..000000000 --- a/3rdparty/qjsonitem.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-3.0+ - * License-Filename: LICENSES/GPLv3+-QJsonModel - */ - -#ifndef JSONITEM_H -#define JSONITEM_H -#include -#include -#include -#include -class QJsonTreeItem -{ -public: - QJsonTreeItem(QJsonTreeItem * parent = nullptr); - ~QJsonTreeItem(); - void appendChild(QJsonTreeItem * item); - QJsonTreeItem *child(int row); - QJsonTreeItem *parent(); - int childCount() const; - int row() const; - void setKey(const QString& key); - void setValue(const QString& value); - void setType(const QJsonValue::Type& type); - QString key() const; - QString value() const; - QJsonValue::Type type() const; - - - static QJsonTreeItem* load(const QJsonValue& value, QJsonTreeItem * parent = nullptr); - -protected: - - -private: - QString mKey; - QString mValue; - QJsonValue::Type mType; - - QList mChilds; - QJsonTreeItem * mParent; - - -}; - -#endif // JSONITEM_H diff --git a/3rdparty/qjsonmodel.cpp b/3rdparty/qjsonmodel.cpp deleted file mode 100644 index 020d27e42..000000000 --- a/3rdparty/qjsonmodel.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-3.0+ - * License-Filename: LICENSES/GPLv3+-QJsonModel - */ - -/*********************************************** - Copyright (C) 2014 Schutz Sacha - This file is part of QJsonModel (https://github.com/dridk/QJsonmodel). - - QJsonModel 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. - - QJsonModel 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 QJsonModel. If not, see . - -**********************************************/ - -#include "qjsonmodel.h" -#include -#include -#include -#include -#include -#include - -QJsonModel::QJsonModel(QObject *parent) : - QAbstractItemModel(parent) - , mRootItem( new QJsonTreeItem ) -{ - mHeaders.append("key"); - mHeaders.append("value"); - - -} - -QJsonModel::~QJsonModel() -{ - delete mRootItem; -} - -bool QJsonModel::load(const QString &fileName) -{ - QFile file(fileName); - bool success = false; - if (file.open(QIODevice::ReadOnly)) { - success = load(&file); - file.close(); - } - else success = false; - - return success; -} - -bool QJsonModel::load(QIODevice *device) -{ - return loadJson(device->readAll()); -} - -bool QJsonModel::loadJson(const QByteArray &json) -{ - mDocument = QJsonDocument::fromJson(json); - - if (!mDocument.isNull()) - { - beginResetModel(); - delete mRootItem; - if (mDocument.isArray()) { - mRootItem = QJsonTreeItem::load(QJsonValue(mDocument.array())); - } else { - mRootItem = QJsonTreeItem::load(QJsonValue(mDocument.object())); - } - endResetModel(); - return true; - } - return false; -} - - -QVariant QJsonModel::data(const QModelIndex &index, int role) const -{ - - if (!index.isValid()) - return QVariant(); - - - QJsonTreeItem *item = static_cast(index.internalPointer()); - - - if ((role == Qt::DecorationRole) && (index.column() == 0)){ - - return mTypeIcons.value(item->type()); - } - - - if (role == Qt::DisplayRole) { - - if (index.column() == 0) - return QString("%1").arg(item->key()); - - if (index.column() == 1) - return QString("%1").arg(item->value()); - } - - - - return QVariant(); - -} - -QVariant QJsonModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if (role != Qt::DisplayRole) - return QVariant(); - - if (orientation == Qt::Horizontal) { - - return mHeaders.value(section); - } - else - return QVariant(); -} - -QModelIndex QJsonModel::index(int row, int column, const QModelIndex &parent) const -{ - if (!hasIndex(row, column, parent)) - return QModelIndex(); - - QJsonTreeItem *parentItem; - - if (!parent.isValid()) - parentItem = mRootItem; - else - parentItem = static_cast(parent.internalPointer()); - - QJsonTreeItem *childItem = parentItem->child(row); - if (childItem) - return createIndex(row, column, childItem); - else - return QModelIndex(); -} - -QModelIndex QJsonModel::parent(const QModelIndex &index) const -{ - if (!index.isValid()) - return QModelIndex(); - - QJsonTreeItem *childItem = static_cast(index.internalPointer()); - QJsonTreeItem *parentItem = childItem->parent(); - - if (parentItem == mRootItem) - return QModelIndex(); - - return createIndex(parentItem->row(), 0, parentItem); -} - -int QJsonModel::rowCount(const QModelIndex &parent) const -{ - QJsonTreeItem *parentItem; - if (parent.column() > 0) - return 0; - - if (!parent.isValid()) - parentItem = mRootItem; - else - parentItem = static_cast(parent.internalPointer()); - - return parentItem->childCount(); -} - -int QJsonModel::columnCount(const QModelIndex &parent) const -{ - Q_UNUSED(parent) - return 2; -} - -void QJsonModel::setIcon(const QJsonValue::Type &type, const QIcon &icon) -{ - mTypeIcons.insert(type,icon); -} diff --git a/3rdparty/qjsonmodel.h b/3rdparty/qjsonmodel.h deleted file mode 100644 index 32c062ba8..000000000 --- a/3rdparty/qjsonmodel.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-3.0+ - * License-Filename: LICENSES/GPLv3+-QJsonModel - */ - -#ifndef QJSONMODEL_H -#define QJSONMODEL_H - -#include -#include "qjsonitem.h" -#include -#include -#include -class QJsonModel : public QAbstractItemModel -{ - Q_OBJECT -public: - explicit QJsonModel(QObject *parent = nullptr); - ~QJsonModel(); - bool load(const QString& fileName); - bool load(QIODevice * device); - bool loadJson(const QByteArray& json); - QVariant data(const QModelIndex &index, int role) const; - QVariant headerData(int section, Qt::Orientation orientation, int role) const; - QModelIndex index(int row, int column,const QModelIndex &parent = QModelIndex()) const; - QModelIndex parent(const QModelIndex &index) const; - int rowCount(const QModelIndex &parent = QModelIndex()) const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; - void setIcon(const QJsonValue::Type& type, const QIcon& icon); - - - -private: - QJsonTreeItem * mRootItem; - QJsonDocument mDocument; - QStringList mHeaders; - QHash mTypeIcons; - - -}; - -#endif // QJSONMODEL_H diff --git a/LICENSES/GPLv3+-QJsonModel b/LICENSES/GPLv3+-QJsonModel deleted file mode 100644 index 8a8e272c0..000000000 --- a/LICENSES/GPLv3+-QJsonModel +++ /dev/null @@ -1,18 +0,0 @@ -/*********************************************** - Copyright (C) 2014 Schutz Sacha - This file is part of QJsonModel (https://github.com/dridk/QJsonmodel). - - QJsonModel 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. - - QJsonModel 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 QJsonModel. If not, see . - -**********************************************/ From 695e16bb87ae95313ceed206be98df2fd2b25f00 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 06:21:07 -0400 Subject: [PATCH 163/302] [libcalamaresui] Drop QJsonModel from the library --- src/libcalamaresui/CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/libcalamaresui/CMakeLists.txt b/src/libcalamaresui/CMakeLists.txt index 04565206e..89a50e2ec 100644 --- a/src/libcalamaresui/CMakeLists.txt +++ b/src/libcalamaresui/CMakeLists.txt @@ -18,9 +18,6 @@ set( calamaresui_SOURCES utils/ImageRegistry.cpp utils/Paste.cpp - ${CMAKE_SOURCE_DIR}/3rdparty/qjsonmodel.cpp - ${CMAKE_SOURCE_DIR}/3rdparty/qjsonitem.cpp - viewpages/BlankViewStep.cpp viewpages/ViewStep.cpp From 419329ee494faeeff16d6ba08baca4ce75d3bc00 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 06:27:13 -0400 Subject: [PATCH 164/302] [libcalamares] Remove friend, add accessor, make includes explicit --- src/libcalamares/GlobalStorage.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/libcalamares/GlobalStorage.h b/src/libcalamares/GlobalStorage.h index 6fdb43fa0..b070e23f6 100644 --- a/src/libcalamares/GlobalStorage.h +++ b/src/libcalamares/GlobalStorage.h @@ -22,6 +22,8 @@ #include "CalamaresConfig.h" +#include +#include #include #ifdef WITH_PYTHON @@ -87,13 +89,19 @@ public: /// @brief reads settings from the given filename bool loadYaml( const QString& filename ); + /** @brief Get internal mapping as a constant object + * + * Note that the VariantMap underneath may change, because + * it's not constant in itself. Connect to the changed() + * signal for notifications. + */ + const QVariantMap& data() const { return m; } + signals: void changed(); private: QVariantMap m; - - friend DebugWindow; }; } // namespace Calamares From 85d28af1e20768c8dd99cfa8acd424f6d7bcc3d2 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 06:34:38 -0400 Subject: [PATCH 165/302] [libcalamaresui] Don't include QJsonModel --- src/libcalamaresui/utils/DebugWindow.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libcalamaresui/utils/DebugWindow.cpp b/src/libcalamaresui/utils/DebugWindow.cpp index 094511be4..237b8a7ed 100644 --- a/src/libcalamaresui/utils/DebugWindow.cpp +++ b/src/libcalamaresui/utils/DebugWindow.cpp @@ -30,8 +30,6 @@ #include "utils/Logger.h" #include "utils/Retranslator.h" -#include "3rdparty/qjsonmodel.h" - #ifdef WITH_PYTHONQT #include "ViewManager.h" #include "viewpages/PythonQtViewStep.h" @@ -39,10 +37,10 @@ #include #endif -#include #include #include #include +#include /** * @brief crash makes Calamares crash immediately. From e31a498c9b70abebe50bdeaeec661545eab4bc40 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 06:35:40 -0400 Subject: [PATCH 166/302] [calamares] Move DebugWindow - This is a fairly specialized class, for use only in the whole-application where it ties in with the module system. Move it to the application directory and slim down the UI library. - Include it from the new location. - Add UIC to Calamares (the application) because there's now a designer-based widget in it. --- src/calamares/CMakeLists.txt | 3 +++ src/calamares/CalamaresWindow.cpp | 2 +- src/{libcalamaresui/utils => calamares}/DebugWindow.cpp | 0 src/{libcalamaresui/utils => calamares}/DebugWindow.h | 0 src/{libcalamaresui/utils => calamares}/DebugWindow.ui | 0 src/libcalamaresui/CMakeLists.txt | 6 ------ 6 files changed, 4 insertions(+), 7 deletions(-) rename src/{libcalamaresui/utils => calamares}/DebugWindow.cpp (100%) rename src/{libcalamaresui/utils => calamares}/DebugWindow.h (100%) rename src/{libcalamaresui/utils => calamares}/DebugWindow.ui (100%) diff --git a/src/calamares/CMakeLists.txt b/src/calamares/CMakeLists.txt index 5dbf137bb..92521f17a 100644 --- a/src/calamares/CMakeLists.txt +++ b/src/calamares/CMakeLists.txt @@ -5,6 +5,8 @@ set( calamaresSources CalamaresApplication.cpp CalamaresWindow.cpp + DebugWindow.cpp + progresstree/ProgressTreeDelegate.cpp progresstree/ProgressTreeItem.cpp progresstree/ProgressTreeModel.cpp @@ -35,6 +37,7 @@ set_target_properties(calamares_bin RUNTIME_OUTPUT_NAME calamares ) calamares_automoc( calamares_bin ) +calamares_autouic( calamares_bin ) target_link_libraries( calamares_bin PRIVATE diff --git a/src/calamares/CalamaresWindow.cpp b/src/calamares/CalamaresWindow.cpp index d80b6cb67..68f29ef18 100644 --- a/src/calamares/CalamaresWindow.cpp +++ b/src/calamares/CalamaresWindow.cpp @@ -26,7 +26,7 @@ #include "ViewManager.h" #include "progresstree/ProgressTreeView.h" #include "utils/CalamaresUtilsGui.h" -#include "utils/DebugWindow.h" +#include "DebugWindow.h" #include "utils/Logger.h" #include "utils/Retranslator.h" diff --git a/src/libcalamaresui/utils/DebugWindow.cpp b/src/calamares/DebugWindow.cpp similarity index 100% rename from src/libcalamaresui/utils/DebugWindow.cpp rename to src/calamares/DebugWindow.cpp diff --git a/src/libcalamaresui/utils/DebugWindow.h b/src/calamares/DebugWindow.h similarity index 100% rename from src/libcalamaresui/utils/DebugWindow.h rename to src/calamares/DebugWindow.h diff --git a/src/libcalamaresui/utils/DebugWindow.ui b/src/calamares/DebugWindow.ui similarity index 100% rename from src/libcalamaresui/utils/DebugWindow.ui rename to src/calamares/DebugWindow.ui diff --git a/src/libcalamaresui/CMakeLists.txt b/src/libcalamaresui/CMakeLists.txt index 89a50e2ec..111113a47 100644 --- a/src/libcalamaresui/CMakeLists.txt +++ b/src/libcalamaresui/CMakeLists.txt @@ -14,7 +14,6 @@ set( calamaresui_SOURCES modulesystem/ViewModule.cpp utils/CalamaresUtilsGui.cpp - utils/DebugWindow.cpp utils/ImageRegistry.cpp utils/Paste.cpp @@ -38,10 +37,6 @@ mark_thirdparty_code( ${CMAKE_SOURCE_DIR}/3rdparty/waitingspinnerwidget.cpp ) -set( calamaresui_UI - utils/DebugWindow.ui -) - if( WITH_PYTHON ) list( APPEND calamaresui_SOURCES modulesystem/PythonJobModule.cpp @@ -69,7 +64,6 @@ endif() calamares_add_library( calamaresui SOURCES ${calamaresui_SOURCES} - UI ${calamaresui_UI} EXPORT_MACRO UIDLLEXPORT_PRO LINK_PRIVATE_LIBRARIES ${OPTIONAL_PYTHON_LIBRARIES} From 2a3ab4dbe768792ac87ec637ffdcfad21cf5ff69 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 07:21:48 -0400 Subject: [PATCH 167/302] [calamares] Add a model for viewing QVariants directly --- src/calamares/CMakeLists.txt | 1 + src/calamares/VariantModel.cpp | 234 +++++++++++++++++++++++++++++++++ src/calamares/VariantModel.h | 74 +++++++++++ 3 files changed, 309 insertions(+) create mode 100644 src/calamares/VariantModel.cpp create mode 100644 src/calamares/VariantModel.h diff --git a/src/calamares/CMakeLists.txt b/src/calamares/CMakeLists.txt index 92521f17a..259e3bf56 100644 --- a/src/calamares/CMakeLists.txt +++ b/src/calamares/CMakeLists.txt @@ -6,6 +6,7 @@ set( calamaresSources CalamaresWindow.cpp DebugWindow.cpp + VariantModel.cpp progresstree/ProgressTreeDelegate.cpp progresstree/ProgressTreeItem.cpp diff --git a/src/calamares/VariantModel.cpp b/src/calamares/VariantModel.cpp new file mode 100644 index 000000000..bdcf8f75c --- /dev/null +++ b/src/calamares/VariantModel.cpp @@ -0,0 +1,234 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 "VariantModel.h" + +static void +overallLength( const QVariant& item, int& c, int parent, VariantModel::IndexVector* skiplist ) +{ + if ( skiplist ) + { + skiplist->append( parent ); + } + + parent = c++; + if ( item.canConvert< QVariantList >() ) + { + for ( const auto& subitem : item.toList() ) + { + overallLength( subitem, c, parent, skiplist ); + } + } + else if ( item.canConvert< QVariantMap >() ) + { + for ( const auto& subitem : item.toMap() ) + { + overallLength( subitem, c, parent, skiplist ); + } + } +} + +static quintptr +findNth( const VariantModel::IndexVector& skiplist, quintptr value, int n ) +{ + if ( n < 0 ) + { + return -1; + } + + int index = 0; + while ( ( n >= 0 ) && ( index < skiplist.count() ) ) + { + if ( skiplist[ index ] == value ) + { + if ( --n < 0 ) + { + return index; + } + } + index++; + } + return -1; +} + + +VariantModel::VariantModel( const QVariant* p ) + : m_p( p ) +{ + int x = 0; + overallLength( *p, x, -1, nullptr ); + m_rows.reserve( x ); + x = 0; + overallLength( *p, x, -1, &m_rows ); +} + +VariantModel::~VariantModel() {} + +int +VariantModel::columnCount( const QModelIndex& index ) const +{ + return 2; +} + +int +VariantModel::rowCount( const QModelIndex& index ) const +{ + quintptr p = index.isValid() ? index.internalId() : 0; + return m_rows.count( p ); +} + +QModelIndex +VariantModel::index( int row, int column, const QModelIndex& parent ) const +{ + quintptr p = 0; + + if ( parent.isValid() ) + { + if ( !( parent.internalId() >= m_rows.count() ) ) + { + p = parent.internalId(); + } + } + + return createIndex( row, column, findNth( m_rows, p, row ) ); +} + +QModelIndex +VariantModel::parent( const QModelIndex& index ) const +{ + if ( !index.isValid() || ( index.internalId() > m_rows.count() ) ) + { + return QModelIndex(); + } + + quintptr p = m_rows[ index.internalId() ]; + if ( p == 0 ) + { + return QModelIndex(); + } + + if ( p >= m_rows.count() ) + { + return QModelIndex(); + } + quintptr p_pid = m_rows[ p ]; + int row = 0; + for ( int i = 0; i < p; ++i ) + { + if ( m_rows[ i ] == p_pid ) + { + row++; + } + } + + return createIndex( row, index.column(), p ); +} + +QVariant +VariantModel::data( const QModelIndex& index, int role ) const +{ + if ( role != Qt::DisplayRole ) + { + return QVariant(); + } + + if ( !index.isValid() ) + { + return QVariant(); + } + + if ( ( index.column() < 0 ) || ( index.column() > 1 ) ) + { + return QVariant(); + } + + if ( index.internalId() >= m_rows.count() ) + { + return QVariant(); + } + + const QVariant thing = underlying( parent( index ) ); + + if ( !thing.isValid() ) + { + return QVariant(); + } + + if ( thing.canConvert< QVariantMap >() ) + { + QVariantMap the_map = thing.toMap(); + const auto key = the_map.keys().at( index.row() ); + if ( index.column() == 0 ) + { + return key; + } + else + { + return the_map[ key ]; + } + } + else if ( thing.canConvert< QVariantList >() ) + { + if ( index.column() == 0 ) + { + return index.row(); + } + else + { + QVariantList the_list = thing.toList(); + return the_list.at( index.row() ); + } + } + else + { + if ( index.column() == 0 ) + { + return QVariant(); + } + else + { + return thing; + } + } +} + +const QVariant +VariantModel::underlying( const QModelIndex& index ) const +{ + if ( !index.isValid() ) + { + return *m_p; + } + + const auto& thing = underlying( parent( index ) ); + if ( thing.canConvert< QVariantMap >() ) + { + const auto& the_map = thing.toMap(); + return the_map[ the_map.keys()[ index.row() ] ]; + } + else if ( thing.canConvert< QVariantList >() ) + { + return thing.toList()[ index.row() ]; + } + else + { + return thing; + } + + return QVariant(); +} diff --git a/src/calamares/VariantModel.h b/src/calamares/VariantModel.h new file mode 100644 index 000000000..9ea6f6737 --- /dev/null +++ b/src/calamares/VariantModel.h @@ -0,0 +1,74 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 VARIANTMODEL_H +#define VARIANTMODEL_H + +#include +#include +#include + +/** @brief A model that operates directly on a QVariant + * + * A VariantModel operates directly on an underlying + * QVariant, treating QVariantMap and QVariantList as + * nodes with multiple children. In general, putting + * a QVariantMap into a QVariant and passing that into + * the model will get you a tree-like model of the + * VariantMap's data structure. + * + * Take care of object lifetimes and that the underlying + * QVariant does not change during use. + */ +class VariantModel : public QAbstractItemModel +{ +public: + /** @brief Auxiliary data + * + * The nodes of the tree are enumerated into a vector + * (of length equal to the number of nodes in the tree + 1) + * which are used to do index and parent calculations. + */ + using IndexVector = QVector< quintptr >; + + /** @brief Constructor + * + * The QVariant's lifetime is **not** affected by the model, + * so take care that the QVariant lives at least as long as + * the model). Also, don't change the QVariant underneath the model. + */ + VariantModel( const QVariant* p ); + + ~VariantModel() override; + + int columnCount( const QModelIndex& index ) const override; + int rowCount( const QModelIndex& index ) const override; + + QModelIndex index( int row, int column, const QModelIndex& parent ) const override; + QModelIndex parent( const QModelIndex& index ) const override; + QVariant data( const QModelIndex& index, int role ) const override; + +private: + const QVariant* const m_p; + IndexVector m_rows; + + /// @brief Implementation of walking an index through the variant-tree + const QVariant underlying( const QModelIndex& index ) const; +}; + +#endif From 2bd03ad3c09129c7b078e73193c10d20cddfa891 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 07:40:23 -0400 Subject: [PATCH 168/302] [calamares] Add reload() to update model after underlying data --- src/calamares/VariantModel.cpp | 16 +++++++++++----- src/calamares/VariantModel.h | 11 ++++++++++- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/calamares/VariantModel.cpp b/src/calamares/VariantModel.cpp index bdcf8f75c..fc11794bc 100644 --- a/src/calamares/VariantModel.cpp +++ b/src/calamares/VariantModel.cpp @@ -70,15 +70,21 @@ findNth( const VariantModel::IndexVector& skiplist, quintptr value, int n ) VariantModel::VariantModel( const QVariant* p ) : m_p( p ) { - int x = 0; - overallLength( *p, x, -1, nullptr ); - m_rows.reserve( x ); - x = 0; - overallLength( *p, x, -1, &m_rows ); + reload(); } VariantModel::~VariantModel() {} +void VariantModel::reload() +{ + int x = 0; + overallLength( *m_p, x, -1, nullptr ); + m_rows.clear(); // Start over + m_rows.reserve( x ); // We'll need this much + x = 0; + overallLength( *m_p, x, -1, &m_rows ); +} + int VariantModel::columnCount( const QModelIndex& index ) const { diff --git a/src/calamares/VariantModel.h b/src/calamares/VariantModel.h index 9ea6f6737..b0c93e91c 100644 --- a/src/calamares/VariantModel.h +++ b/src/calamares/VariantModel.h @@ -33,7 +33,9 @@ * VariantMap's data structure. * * Take care of object lifetimes and that the underlying - * QVariant does not change during use. + * QVariant does not change during use. If the QVariant + * **does** change, call reload() to re-build the internal + * representation of the tree. */ class VariantModel : public QAbstractItemModel { @@ -56,6 +58,13 @@ public: ~VariantModel() override; + /** @brief Re-build the internal tree + * + * Call this when the underlying variant is changed, which + * might impact how the tree is laid out. + */ + void reload(); + int columnCount( const QModelIndex& index ) const override; int rowCount( const QModelIndex& index ) const override; From eba4dc8df131d247c05395d56ceb5081ddcf3f0e Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 07:48:52 -0400 Subject: [PATCH 169/302] [calamares] Use VariantModel instead of QJsonModel - Drop the round-trip of forming a JSON document from a QVariant, then parsing the document into JSON objects and building a model out of that. View the Variant directly. --- src/calamares/DebugWindow.cpp | 30 +++++++++++++++++------------- src/calamares/DebugWindow.h | 8 ++++++++ 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/calamares/DebugWindow.cpp b/src/calamares/DebugWindow.cpp index 237b8a7ed..1680fb7de 100644 --- a/src/calamares/DebugWindow.cpp +++ b/src/calamares/DebugWindow.cpp @@ -20,6 +20,8 @@ #include "DebugWindow.h" #include "ui_DebugWindow.h" +#include "VariantModel.h" + #include "Branding.h" #include "modulesystem/Module.h" #include "modulesystem/ModuleManager.h" @@ -72,23 +74,25 @@ namespace Calamares { DebugWindow::DebugWindow() : QWidget( nullptr ) , m_ui( new Ui::DebugWindow ) + , m_globals( JobQueue::instance()->globalStorage()->data() ) + , m_globals_model( std::make_unique< VariantModel >( &m_globals ) ) + , m_module_model( std::make_unique< VariantModel >( &m_module ) ) { - m_ui->setupUi( this ); - - // GlobalStorage page - QJsonModel* jsonModel = new QJsonModel( this ); - - m_ui->globalStorageView->setModel( jsonModel ); GlobalStorage* gs = JobQueue::instance()->globalStorage(); + m_ui->setupUi( this ); + + m_ui->globalStorageView->setModel( m_globals_model.get() ); + m_ui->globalStorageView->expandAll(); + + // Do above when the GS changes, too connect( gs, &GlobalStorage::changed, this, [ = ] { - jsonModel->loadJson( QJsonDocument::fromVariant( gs->m ).toJson() ); + m_globals = JobQueue::instance()->globalStorage()->data(); + m_globals_model->reload(); m_ui->globalStorageView->expandAll(); } ); - jsonModel->loadJson( QJsonDocument::fromVariant( gs->m ).toJson() ); - m_ui->globalStorageView->expandAll(); // JobQueue page m_ui->jobQueueText->setReadOnly( true ); @@ -109,8 +113,7 @@ DebugWindow::DebugWindow() m_ui->modulesListView->setModel( modulesModel ); m_ui->modulesListView->setSelectionMode( QAbstractItemView::SingleSelection ); - QJsonModel* moduleConfigModel = new QJsonModel( this ); - m_ui->moduleConfigView->setModel( moduleConfigModel ); + m_ui->moduleConfigView->setModel( m_module_model.get() ); #ifdef WITH_PYTHONQT QPushButton* pythonConsoleButton = new QPushButton; @@ -181,7 +184,7 @@ DebugWindow::DebugWindow() #endif connect( m_ui->modulesListView->selectionModel(), &QItemSelectionModel::selectionChanged, - this, [ this, moduleConfigModel + this, [ this #ifdef WITH_PYTHONQT , pythonConsoleButton #endif @@ -191,7 +194,8 @@ DebugWindow::DebugWindow() Module* module = ModuleManager::instance()->moduleInstance( moduleName ); if ( module ) { - moduleConfigModel->loadJson( QJsonDocument::fromVariant( module->configurationMap() ).toJson() ); + m_module = module->configurationMap(); + m_module_model->reload(); m_ui->moduleConfigView->expandAll(); m_ui->moduleTypeLabel->setText( module->typeString() ); m_ui->moduleInterfaceLabel->setText( module->interfaceString() ); diff --git a/src/calamares/DebugWindow.h b/src/calamares/DebugWindow.h index e97f5727b..1a121455e 100644 --- a/src/calamares/DebugWindow.h +++ b/src/calamares/DebugWindow.h @@ -20,8 +20,12 @@ #ifndef CALAMARES_DEBUGWINDOW_H #define CALAMARES_DEBUGWINDOW_H +#include "VariantModel.h" + +#include #include +#include namespace Calamares { @@ -46,6 +50,10 @@ protected: private: Ui::DebugWindow *m_ui; + QVariant m_globals; + QVariant m_module; + std::unique_ptr< VariantModel> m_globals_model; + std::unique_ptr< VariantModel> m_module_model; }; From ab7a559e03476ff98b4bbd61a8a96d1dbd3bdeeb Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 07:58:20 -0400 Subject: [PATCH 170/302] [calamares] Add headerData to model (Key, Value columns) --- src/calamares/VariantModel.cpp | 32 +++++++++++++++++++++++++++++++- src/calamares/VariantModel.h | 1 + 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/calamares/VariantModel.cpp b/src/calamares/VariantModel.cpp index fc11794bc..965f0f3e0 100644 --- a/src/calamares/VariantModel.cpp +++ b/src/calamares/VariantModel.cpp @@ -75,7 +75,8 @@ VariantModel::VariantModel( const QVariant* p ) VariantModel::~VariantModel() {} -void VariantModel::reload() +void +VariantModel::reload() { int x = 0; overallLength( *m_p, x, -1, nullptr ); @@ -213,6 +214,35 @@ VariantModel::data( const QModelIndex& index, int role ) const } } +QVariant +VariantModel::headerData( int section, Qt::Orientation orientation, int role ) const +{ + if ( role != Qt::DisplayRole ) + { + return QVariant(); + } + + if ( orientation == Qt::Horizontal ) + { + if ( section == 0 ) + { + return tr( "Key" ); + } + else if ( section == 1 ) + { + return tr( "Value" ); + } + else + { + return QVariant(); + } + } + else + { + return QVariant(); + } +} + const QVariant VariantModel::underlying( const QModelIndex& index ) const { diff --git a/src/calamares/VariantModel.h b/src/calamares/VariantModel.h index b0c93e91c..9c4256f6a 100644 --- a/src/calamares/VariantModel.h +++ b/src/calamares/VariantModel.h @@ -71,6 +71,7 @@ public: QModelIndex index( int row, int column, const QModelIndex& parent ) const override; QModelIndex parent( const QModelIndex& index ) const override; QVariant data( const QModelIndex& index, int role ) const override; + QVariant headerData( int section, Qt::Orientation orientation, int role ) const override; private: const QVariant* const m_p; From ea0acf1606d369a350c1ffc1a958c6260789c441 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 15:25:37 +0200 Subject: [PATCH 171/302] [calamares] Apply current coding style --- src/calamares/progresstree/ProgressTreeView.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/calamares/progresstree/ProgressTreeView.cpp b/src/calamares/progresstree/ProgressTreeView.cpp index 5c81e3851..d4f652363 100644 --- a/src/calamares/progresstree/ProgressTreeView.cpp +++ b/src/calamares/progresstree/ProgressTreeView.cpp @@ -76,9 +76,10 @@ ProgressTreeView::setModel( QAbstractItemModel* model ) QTreeView::setModel( model ); expandAll(); - connect( Calamares::ViewManager::instance(), - &Calamares::ViewManager::currentStepChanged, - this, - [this]() { viewport()->update(); }, - Qt::UniqueConnection ); + connect( + Calamares::ViewManager::instance(), + &Calamares::ViewManager::currentStepChanged, + this, + [this]() { viewport()->update(); }, + Qt::UniqueConnection ); } From f5af4818fbc15bb02fb709de20b0387731227b76 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 15:27:40 +0200 Subject: [PATCH 172/302] [calamares] Apply current coding style --- src/calamares/CalamaresWindow.cpp | 2 +- src/calamares/DebugWindow.cpp | 140 ++++++++++++++---------------- src/calamares/DebugWindow.h | 13 +-- 3 files changed, 72 insertions(+), 83 deletions(-) diff --git a/src/calamares/CalamaresWindow.cpp b/src/calamares/CalamaresWindow.cpp index 68f29ef18..1638d6392 100644 --- a/src/calamares/CalamaresWindow.cpp +++ b/src/calamares/CalamaresWindow.cpp @@ -22,11 +22,11 @@ #include "CalamaresWindow.h" #include "Branding.h" +#include "DebugWindow.h" #include "Settings.h" #include "ViewManager.h" #include "progresstree/ProgressTreeView.h" #include "utils/CalamaresUtilsGui.h" -#include "DebugWindow.h" #include "utils/Logger.h" #include "utils/Retranslator.h" diff --git a/src/calamares/DebugWindow.cpp b/src/calamares/DebugWindow.cpp index 1680fb7de..6891851a7 100644 --- a/src/calamares/DebugWindow.cpp +++ b/src/calamares/DebugWindow.cpp @@ -55,21 +55,29 @@ crash() } /// @brief Print out the widget tree (names) in indented form. -static void dumpWidgetTree( QDebug& deb, const QWidget* widget, int depth ) +static void +dumpWidgetTree( QDebug& deb, const QWidget* widget, int depth ) { if ( !widget ) + { return; + } deb << Logger::Continuation; - for (int i = 0; i < depth; ++i ) + for ( int i = 0; i < depth; ++i ) + { deb << ' '; + } deb << widget->objectName(); - for ( const auto* w : widget->findChildren( QString(), Qt::FindDirectChildrenOnly ) ) - dumpWidgetTree( deb, w, depth+1 ); + for ( const auto* w : widget->findChildren< QWidget* >( QString(), Qt::FindDirectChildrenOnly ) ) + { + dumpWidgetTree( deb, w, depth + 1 ); + } } -namespace Calamares { +namespace Calamares +{ DebugWindow::DebugWindow() : QWidget( nullptr ) @@ -86,9 +94,7 @@ DebugWindow::DebugWindow() m_ui->globalStorageView->expandAll(); // Do above when the GS changes, too - connect( gs, &GlobalStorage::changed, - this, [ = ] - { + connect( gs, &GlobalStorage::changed, this, [=] { m_globals = JobQueue::instance()->globalStorage()->data(); m_globals_model->reload(); m_ui->globalStorageView->expandAll(); @@ -96,11 +102,9 @@ DebugWindow::DebugWindow() // JobQueue page m_ui->jobQueueText->setReadOnly( true ); - connect( JobQueue::instance(), &JobQueue::queueChanged, - this, [ this ]( const JobList& jobs ) - { + connect( JobQueue::instance(), &JobQueue::queueChanged, this, [this]( const JobList& jobs ) { QStringList text; - for ( const auto &job : jobs ) + for ( const auto& job : jobs ) { text.append( job->prettyName() ); } @@ -121,21 +125,17 @@ DebugWindow::DebugWindow() m_ui->modulesVerticalLayout->insertWidget( 1, pythonConsoleButton ); pythonConsoleButton->hide(); - QObject::connect( pythonConsoleButton, &QPushButton::clicked, - this, [ this, moduleConfigModel ] - { + QObject::connect( pythonConsoleButton, &QPushButton::clicked, this, [this, moduleConfigModel] { QString moduleName = m_ui->modulesListView->currentIndex().data().toString(); Module* module = ModuleManager::instance()->moduleInstance( moduleName ); - if ( module->interface() != Module::Interface::PythonQt || - module->type() != Module::Type::View ) + if ( module->interface() != Module::Interface::PythonQt || module->type() != Module::Type::View ) return; for ( ViewStep* step : ViewManager::instance()->viewSteps() ) { if ( step->moduleInstanceKey() == module->instanceKey() ) { - PythonQtViewStep* pqvs = - qobject_cast< PythonQtViewStep* >( step ); + PythonQtViewStep* pqvs = qobject_cast< PythonQtViewStep* >( step ); if ( pqvs ) { QWidget* consoleWindow = new QWidget; @@ -152,23 +152,17 @@ DebugWindow::DebugWindow() QLabel* bottomLabel = new QLabel( consoleWindow ); bottomLayout->addWidget( bottomLabel ); - QString line = - QString( "Module: %1
" - "Python class: %2" ) - .arg( module->instanceKey() ) - .arg( console->property( "classname" ).toString() ); + QString line = QString( "Module: %1
" + "Python class: %2" ) + .arg( module->instanceKey() ) + .arg( console->property( "classname" ).toString() ); bottomLabel->setText( line ); QPushButton* closeButton = new QPushButton( consoleWindow ); closeButton->setText( "&Close" ); - QObject::connect( closeButton, &QPushButton::clicked, - [ consoleWindow ] - { - consoleWindow->close(); - } ); + QObject::connect( closeButton, &QPushButton::clicked, [consoleWindow] { consoleWindow->close(); } ); bottomLayout->addWidget( closeButton ); - bottomLabel->setSizePolicy( QSizePolicy::Expanding, - QSizePolicy::Preferred ); + bottomLabel->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred ); consoleWindow->setParent( this ); consoleWindow->setWindowFlags( Qt::Window ); @@ -183,58 +177,52 @@ DebugWindow::DebugWindow() #endif - connect( m_ui->modulesListView->selectionModel(), &QItemSelectionModel::selectionChanged, - this, [ this + connect( m_ui->modulesListView->selectionModel(), + &QItemSelectionModel::selectionChanged, + this, + [this #ifdef WITH_PYTHONQT - , pythonConsoleButton + , + pythonConsoleButton #endif - ] - { - QString moduleName = m_ui->modulesListView->currentIndex().data().toString(); - Module* module = ModuleManager::instance()->moduleInstance( moduleName ); - if ( module ) - { - m_module = module->configurationMap(); - m_module_model->reload(); - m_ui->moduleConfigView->expandAll(); - m_ui->moduleTypeLabel->setText( module->typeString() ); - m_ui->moduleInterfaceLabel->setText( module->interfaceString() ); + ] { + QString moduleName = m_ui->modulesListView->currentIndex().data().toString(); + Module* module = ModuleManager::instance()->moduleInstance( moduleName ); + if ( module ) + { + m_module = module->configurationMap(); + m_module_model->reload(); + m_ui->moduleConfigView->expandAll(); + m_ui->moduleTypeLabel->setText( module->typeString() ); + m_ui->moduleInterfaceLabel->setText( module->interfaceString() ); #ifdef WITH_PYTHONQT - pythonConsoleButton->setVisible( - module->interface() == Module::Interface::PythonQt && - module->type() == Module::Type::View ); + pythonConsoleButton->setVisible( module->interface() == Module::Interface::PythonQt + && module->type() == Module::Type::View ); #endif - } - } ); + } + } ); // Tools page connect( m_ui->crashButton, &QPushButton::clicked, this, [] { ::crash(); } ); - connect( m_ui->reloadStylesheetButton, &QPushButton::clicked, - []() - { - for ( auto* w : qApp->topLevelWidgets() ) - { - // Needs to match what's set in CalamaresWindow - if ( w->objectName() == QStringLiteral( "mainApp" ) ) - { - w->setStyleSheet( Calamares::Branding::instance()->stylesheet() ); - } - } - }); - connect( m_ui->widgetTreeButton, &QPushButton::clicked, - []() - { - for ( auto* w : qApp->topLevelWidgets() ) - { - Logger::CDebug deb; - dumpWidgetTree( deb, w, 0 ); - } - }); + connect( m_ui->reloadStylesheetButton, &QPushButton::clicked, []() { + for ( auto* w : qApp->topLevelWidgets() ) + { + // Needs to match what's set in CalamaresWindow + if ( w->objectName() == QStringLiteral( "mainApp" ) ) + { + w->setStyleSheet( Calamares::Branding::instance()->stylesheet() ); + } + } + } ); + connect( m_ui->widgetTreeButton, &QPushButton::clicked, []() { + for ( auto* w : qApp->topLevelWidgets() ) + { + Logger::CDebug deb; + dumpWidgetTree( deb, w, 0 ); + } + } ); - CALAMARES_RETRANSLATE( - m_ui->retranslateUi( this ); - setWindowTitle( tr( "Debug information" ) ); - ) + CALAMARES_RETRANSLATE( m_ui->retranslateUi( this ); setWindowTitle( tr( "Debug information" ) ); ) } @@ -245,4 +233,4 @@ DebugWindow::closeEvent( QCloseEvent* e ) emit closed(); } -} // namespace Calamares +} // namespace Calamares diff --git a/src/calamares/DebugWindow.h b/src/calamares/DebugWindow.h index 1a121455e..764a141c2 100644 --- a/src/calamares/DebugWindow.h +++ b/src/calamares/DebugWindow.h @@ -27,12 +27,13 @@ #include -namespace Calamares { +namespace Calamares +{ // From the .ui file namespace Ui { - class DebugWindow; +class DebugWindow; } class DebugWindow : public QWidget @@ -49,13 +50,13 @@ protected: void closeEvent( QCloseEvent* e ) override; private: - Ui::DebugWindow *m_ui; + Ui::DebugWindow* m_ui; QVariant m_globals; QVariant m_module; - std::unique_ptr< VariantModel> m_globals_model; - std::unique_ptr< VariantModel> m_module_model; + std::unique_ptr< VariantModel > m_globals_model; + std::unique_ptr< VariantModel > m_module_model; }; -} // namespace +} // namespace Calamares #endif From dc09c5700b53c3a01e0bfff1eab68cfbf3d7964f Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 16:15:18 +0200 Subject: [PATCH 173/302] [calamares] Remove unreachable return --- src/calamares/VariantModel.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/calamares/VariantModel.cpp b/src/calamares/VariantModel.cpp index 965f0f3e0..5eaf4bac7 100644 --- a/src/calamares/VariantModel.cpp +++ b/src/calamares/VariantModel.cpp @@ -265,6 +265,4 @@ VariantModel::underlying( const QModelIndex& index ) const { return thing; } - - return QVariant(); } From 6f73151786dbd1bc4d2d3a892c13252b416071e0 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 16:22:22 +0200 Subject: [PATCH 174/302] [libcalamares] Reduce warnings - Although milliseconds::count() is long long, we pass it to a Qt interface that only takes int; let's assume we have only a 32-bit count, since a timeout of 4 billion milliseconds is roughly 46 days, which we'll just call "no timeout". --- src/libcalamares/utils/CalamaresUtilsSystem.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.cpp b/src/libcalamares/utils/CalamaresUtilsSystem.cpp index 00b879224..ea8f507bd 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.cpp +++ b/src/libcalamares/utils/CalamaresUtilsSystem.cpp @@ -236,8 +236,9 @@ System::runCommand( System::RunLocation location, } process.closeWriteChannel(); - if ( !process.waitForFinished( - timeoutSec > std::chrono::seconds::zero() ? ( std::chrono::milliseconds( timeoutSec ).count() ) : -1 ) ) + if ( !process.waitForFinished( timeoutSec > std::chrono::seconds::zero() + ? ( static_cast< int >( std::chrono::milliseconds( timeoutSec ).count() ) ) + : -1 ) ) { cWarning().noquote().nospace() << "Timed out. Output so far:\n" << process.readAllStandardOutput(); return ProcessResult::Code::TimedOut; From 739363cecd0ef6bdcd6689e53275f8c16363ced2 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 16:28:29 +0200 Subject: [PATCH 175/302] [libcalamaresui] Fix initialization order (reduce warnings) --- src/libcalamaresui/Branding.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcalamaresui/Branding.cpp b/src/libcalamaresui/Branding.cpp index 876fdfa80..d3b0de97d 100644 --- a/src/libcalamaresui/Branding.cpp +++ b/src/libcalamaresui/Branding.cpp @@ -125,9 +125,9 @@ Branding::Branding( const QString& brandingFilePath, QObject* parent ) : QObject( parent ) , m_descriptorPath( brandingFilePath ) + , m_slideshowAPI( 1 ) , m_welcomeStyleCalamares( false ) , m_welcomeExpandingLogo( true ) - , m_slideshowAPI( 1 ) { cDebug() << "Using Calamares branding file at" << brandingFilePath; From e81bd52fb53a8640072eae3cdd1b680247c47d17 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 16:29:55 +0200 Subject: [PATCH 176/302] [initcpio] [initramfs] Set compilation options on tests - calamares_automoc() sets AUTOMOC, but also adds some flags to avoid compilation warnings from the generated MOC code. - drop weird hard-coded include paths --- src/modules/initcpio/CMakeLists.txt | 3 +-- src/modules/initramfs/CMakeLists.txt | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/modules/initcpio/CMakeLists.txt b/src/modules/initcpio/CMakeLists.txt index 990220b10..af217fb1a 100644 --- a/src/modules/initcpio/CMakeLists.txt +++ b/src/modules/initcpio/CMakeLists.txt @@ -21,6 +21,5 @@ if( ECM_FOUND AND BUILD_TESTING ) Qt5::Core Qt5::Test ) - set_target_properties( initcpiotest PROPERTIES AUTOMOC TRUE ) - target_include_directories( initcpiotest PRIVATE /usr/local/include ) + calamares_automoc( initcpiotest ) endif() diff --git a/src/modules/initramfs/CMakeLists.txt b/src/modules/initramfs/CMakeLists.txt index c2496b2a1..d7da12d55 100644 --- a/src/modules/initramfs/CMakeLists.txt +++ b/src/modules/initramfs/CMakeLists.txt @@ -21,6 +21,5 @@ if( ECM_FOUND AND BUILD_TESTING ) Qt5::Core Qt5::Test ) - set_target_properties( initramfstest PROPERTIES AUTOMOC TRUE ) - target_include_directories( initramfstest PRIVATE /usr/local/include ) + calamares_automoc( initramfstest ) endif() From 76041a21841d61c6c7fafd8d9206890915bbdacd Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 16:34:53 +0200 Subject: [PATCH 177/302] [dummycpp] Reduce warnings and apply coding style - tired of the (IMO, bogus) clang warnings from the switch() statement with a default:, so swap it out for some cascaded ifs. --- src/modules/dummycpp/DummyCppJob.cpp | 61 ++++++++++++++++------------ src/modules/dummycpp/DummyCppJob.h | 2 +- 2 files changed, 36 insertions(+), 27 deletions(-) diff --git a/src/modules/dummycpp/DummyCppJob.cpp b/src/modules/dummycpp/DummyCppJob.cpp index b404eaf63..a38cddc40 100644 --- a/src/modules/dummycpp/DummyCppJob.cpp +++ b/src/modules/dummycpp/DummyCppJob.cpp @@ -20,13 +20,13 @@ #include "DummyCppJob.h" -#include #include +#include #include #include "CalamaresVersion.h" -#include "JobQueue.h" #include "GlobalStorage.h" +#include "JobQueue.h" #include "utils/Logger.h" @@ -36,9 +36,7 @@ DummyCppJob::DummyCppJob( QObject* parent ) } -DummyCppJob::~DummyCppJob() -{ -} +DummyCppJob::~DummyCppJob() {} QString @@ -56,19 +54,20 @@ static QString variantHashToString( const QVariantHash& variantHash ); static QString variantToString( const QVariant& variant ) { - switch ( variant.type() ) + if ( variant.type() == QVariant::Map ) { - case QVariant::Map: return variantMapToString( variant.toMap() ); - - case QVariant::Hash: + } + else if ( variant.type() == QVariant::Hash ) + { return variantHashToString( variant.toHash() ); - - case QVariant::List: - case QVariant::StringList: + } + else if ( ( variant.type() == QVariant::List ) || ( variant.type() == QVariant::StringList ) ) + { return variantListToString( variant.toList() ); - - default: + } + else + { return variant.toString(); } } @@ -79,8 +78,10 @@ variantListToString( const QVariantList& variantList ) { QStringList result; for ( const QVariant& variant : variantList ) + { result.append( variantToString( variant ) ); - return '{' + result.join(',') + '}'; + } + return '{' + result.join( ',' ) + '}'; } @@ -89,8 +90,10 @@ variantMapToString( const QVariantMap& variantMap ) { QStringList result; for ( auto it = variantMap.constBegin(); it != variantMap.constEnd(); ++it ) + { result.append( it.key() + '=' + variantToString( it.value() ) ); - return '[' + result.join(',') + ']'; + } + return '[' + result.join( ',' ) + ']'; } @@ -99,8 +102,10 @@ variantHashToString( const QVariantHash& variantHash ) { QStringList result; for ( auto it = variantHash.constBegin(); it != variantHash.constEnd(); ++it ) + { result.append( it.key() + '=' + variantToString( it.value() ) ); - return '<' + result.join(',') + '>'; + } + return '<' + result.join( ',' ) + '>'; } @@ -108,24 +113,28 @@ Calamares::JobResult DummyCppJob::exec() { // Ported from dummypython - QProcess::execute( "/bin/sh", QStringList() << "-c" << "touch ~/calamares-dummycpp" ); + QProcess::execute( "/bin/sh", + QStringList() << "-c" + << "touch ~/calamares-dummycpp" ); QString accumulator = QDateTime::currentDateTimeUtc().toString( Qt::ISODate ) + '\n'; accumulator += QStringLiteral( "Calamares version: " ) + CALAMARES_VERSION_SHORT + '\n'; accumulator += QStringLiteral( "This job's name: " ) + prettyName() + '\n'; accumulator += QStringLiteral( "Configuration map: %1\n" ).arg( variantMapToString( m_configurationMap ) ); accumulator += QStringLiteral( " *** globalstorage test ***\n" ); - Calamares::GlobalStorage *globalStorage = Calamares::JobQueue::instance()->globalStorage(); - accumulator += QStringLiteral( "lala: " ) + (globalStorage->contains( "lala" ) ? QStringLiteral( "true" ) : QStringLiteral( "false" )) + '\n'; - accumulator += QStringLiteral( "foo: " ) + (globalStorage->contains( "foo" ) ? QStringLiteral( "true" ) : QStringLiteral( "false" )) + '\n'; + Calamares::GlobalStorage* globalStorage = Calamares::JobQueue::instance()->globalStorage(); + accumulator += QStringLiteral( "lala: " ) + + ( globalStorage->contains( "lala" ) ? QStringLiteral( "true" ) : QStringLiteral( "false" ) ) + '\n'; + accumulator += QStringLiteral( "foo: " ) + + ( globalStorage->contains( "foo" ) ? QStringLiteral( "true" ) : QStringLiteral( "false" ) ) + '\n'; accumulator += QStringLiteral( "count: " ) + QString::number( globalStorage->count() ) + '\n'; globalStorage->insert( "item2", "value2" ); globalStorage->insert( "item3", 3 ); accumulator += QStringLiteral( "keys: %1\n" ).arg( globalStorage->keys().join( ',' ) ); accumulator += QStringLiteral( "remove: %1\n" ).arg( QString::number( globalStorage->remove( "item2" ) ) ); - accumulator += QStringLiteral( "values: %1 %2 %3\n" ).arg( - globalStorage->value( "foo" ).toString(), - globalStorage->value( "item2" ).toString(), - globalStorage->value( "item3" ).toString() ); + accumulator += QStringLiteral( "values: %1 %2 %3\n" ) + .arg( globalStorage->value( "foo" ).toString(), + globalStorage->value( "item2" ).toString(), + globalStorage->value( "item3" ).toString() ); emit progress( 0.1 ); cDebug() << "[DUMMYCPP]: " << accumulator; @@ -145,4 +154,4 @@ DummyCppJob::setConfigurationMap( const QVariantMap& configurationMap ) m_configurationMap = configurationMap; } -CALAMARES_PLUGIN_FACTORY_DEFINITION( DummyCppJobFactory, registerPlugin(); ) +CALAMARES_PLUGIN_FACTORY_DEFINITION( DummyCppJobFactory, registerPlugin< DummyCppJob >(); ) diff --git a/src/modules/dummycpp/DummyCppJob.h b/src/modules/dummycpp/DummyCppJob.h index 98c4d19d6..4a79d0378 100644 --- a/src/modules/dummycpp/DummyCppJob.h +++ b/src/modules/dummycpp/DummyCppJob.h @@ -49,4 +49,4 @@ private: CALAMARES_PLUGIN_FACTORY_DECLARATION( DummyCppJobFactory ) -#endif // DUMMYCPPJOB_H +#endif // DUMMYCPPJOB_H From 41173360a71c6c13bb6e1fbcd1bf1c500b075b2c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 16:36:38 +0200 Subject: [PATCH 178/302] [libcalamares] We're just testing file modes, not whole int range --- src/libcalamares/utils/Tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcalamares/utils/Tests.cpp b/src/libcalamares/utils/Tests.cpp index 2f2b7ff4b..0f7d6cd81 100644 --- a/src/libcalamares/utils/Tests.cpp +++ b/src/libcalamares/utils/Tests.cpp @@ -158,7 +158,7 @@ LibCalamaresTests::testUmask() mode_t m = CalamaresUtils::setUMask( 022 ); QCOMPARE( CalamaresUtils::setUMask( m ), m ); - for ( int i = 0; i <= 0777 /* octal! */; ++i ) + for ( mode_t i = 0; i <= 0777 /* octal! */; ++i ) { QByteArray name = ( ft.fileName() + QChar( '.' ) + QString::number( i, 8 ) ).toLatin1(); CalamaresUtils::UMask um( i ); From 91d327b224b867960b991bb0afc79d124c373403 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 16:41:59 +0200 Subject: [PATCH 179/302] [libcalamaresui] Paste TCP port is quint16 - no sense in feeding in an int (and getting a compiler warning for narrowing) into something that by spec is a 16-bit value. --- src/libcalamaresui/utils/Paste.cpp | 2 +- src/libcalamaresui/utils/Paste.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libcalamaresui/utils/Paste.cpp b/src/libcalamaresui/utils/Paste.cpp index 6fead59e6..1b9ad4dfe 100644 --- a/src/libcalamaresui/utils/Paste.cpp +++ b/src/libcalamaresui/utils/Paste.cpp @@ -29,7 +29,7 @@ namespace CalamaresUtils { QString -sendLogToPastebin( QObject* parent, const QString& ficheHost, int fichePort ) +sendLogToPastebin( QObject* parent, const QString& ficheHost, quint16 fichePort ) { QString pasteUrlFmt = parent->tr( "Install log posted to:\n%1" ); QFile pasteSourceFile( Logger::logFile() ); diff --git a/src/libcalamaresui/utils/Paste.h b/src/libcalamaresui/utils/Paste.h index 2ac77f2f3..fd088882c 100644 --- a/src/libcalamaresui/utils/Paste.h +++ b/src/libcalamaresui/utils/Paste.h @@ -19,6 +19,8 @@ #ifndef UTILS_PASTE_H #define UTILS_PASTE_H +#include // for quint16 + class QObject; class QString; @@ -29,7 +31,7 @@ namespace CalamaresUtils * * Returns the (string) URL that the pastebin gives us. */ -QString sendLogToPastebin( QObject* parent, const QString& ficheHost, int fichePort ); +QString sendLogToPastebin( QObject* parent, const QString& ficheHost, quint16 fichePort ); } // namespace CalamaresUtils From ec08a293b28fc374b250b3549f1f742563fbc232 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 16:43:50 +0200 Subject: [PATCH 180/302] [libcalamaresui] Reduce compile warnings - "this" isn't used in the lambda; in future it might be if the lambda needs to get the configuration from settings. --- src/libcalamaresui/ViewManager.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libcalamaresui/ViewManager.cpp b/src/libcalamaresui/ViewManager.cpp index b27b36f80..7baefdbd0 100644 --- a/src/libcalamaresui/ViewManager.cpp +++ b/src/libcalamaresui/ViewManager.cpp @@ -241,7 +241,7 @@ ViewManager::onInstallationFailed( const QString& message, const QString& detail msgBox->show(); cDebug() << "Calamares will quit when the dialog closes."; - connect( msgBox, &QMessageBox::buttonClicked, [this,msgBox]( QAbstractButton* button ) { + connect( msgBox, &QMessageBox::buttonClicked, [msgBox]( QAbstractButton* button ) { if ( msgBox->buttonRole( button ) == QMessageBox::ButtonRole::YesRole ) { // TODO: host and port should be configurable @@ -254,9 +254,7 @@ ViewManager::onInstallationFailed( const QString& message, const QString& detail } // TODO: make the URL clickable, or copy it to the clipboard automatically - QMessageBox::critical(nullptr, - pasteUrlTitle, - pasteUrlMsg); + QMessageBox::critical( nullptr, pasteUrlTitle, pasteUrlMsg ); } QApplication::quit(); } ); From 8a7f32d3aa45fd1d34bbb7a704fc8aa39c334544 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 16:52:54 +0200 Subject: [PATCH 181/302] [libcalamaresui] Polish ImageRegistry - do static initialization more carefully - float -> qreal (double) because that's what the Qt API expects, to reduce type-conversion warnings - apply current coding style --- src/libcalamaresui/utils/ImageRegistry.cpp | 45 +++++++++++++--------- src/libcalamaresui/utils/ImageRegistry.h | 23 +++++++---- 2 files changed, 42 insertions(+), 26 deletions(-) diff --git a/src/libcalamaresui/utils/ImageRegistry.cpp b/src/libcalamaresui/utils/ImageRegistry.cpp index 96ea92bbb..5cffac11c 100644 --- a/src/libcalamaresui/utils/ImageRegistry.cpp +++ b/src/libcalamaresui/utils/ImageRegistry.cpp @@ -2,6 +2,8 @@ * * SPDX-License-Identifier: GPLv3+ * License-Filename: LICENSES/GPLv3+-ImageRegistry + * + * Copyright 2019, Adriaan de Groot */ /* @@ -23,25 +25,22 @@ #include "ImageRegistry.h" -#include #include +#include #include static QHash< QString, QHash< int, QHash< qint64, QPixmap > > > s_cache; -ImageRegistry* ImageRegistry::s_instance = 0; ImageRegistry* ImageRegistry::instance() { + static ImageRegistry* s_instance = new ImageRegistry(); return s_instance; } -ImageRegistry::ImageRegistry() -{ - s_instance = this; -} +ImageRegistry::ImageRegistry() {} QIcon @@ -52,16 +51,20 @@ ImageRegistry::icon( const QString& image, CalamaresUtils::ImageMode mode ) qint64 -ImageRegistry::cacheKey( const QSize& size, float opacity, QColor tint ) +ImageRegistry::cacheKey( const QSize& size, qreal opacity, QColor tint ) { - return size.width() * 100 + size.height() * 10 + ( opacity * 100.0 ) + tint.value(); + return size.width() * 100 + size.height() * 10 + static_cast< qint64 >( opacity * 100.0 ) + tint.value(); } QPixmap -ImageRegistry::pixmap( const QString& image, const QSize& size, CalamaresUtils::ImageMode mode, float opacity, QColor tint ) +ImageRegistry::pixmap( const QString& image, + const QSize& size, + CalamaresUtils::ImageMode mode, + qreal opacity, + QColor tint ) { - Q_ASSERT( !(size.width() < 0 || size.height() < 0) ); + Q_ASSERT( !( size.width() < 0 || size.height() < 0 ) ); if ( size.width() < 0 || size.height() < 0 ) { return QPixmap(); @@ -110,23 +113,20 @@ ImageRegistry::pixmap( const QString& image, const QSize& size, CalamaresUtils:: resultImage.setAlphaChannel( p.toImage().alphaChannel() ); p = QPixmap::fromImage( resultImage ); - } + } pixmap = p; } else + { pixmap = QPixmap( image ); + } if ( !pixmap.isNull() ) { - switch ( mode ) + if ( mode == CalamaresUtils::RoundedCorners ) { - case CalamaresUtils::RoundedCorners: - pixmap = CalamaresUtils::createRoundedImage( pixmap, size ); - break; - - default: - break; + pixmap = CalamaresUtils::createRoundedImage( pixmap, size ); } if ( !size.isNull() && pixmap.size() != size ) @@ -140,7 +140,9 @@ ImageRegistry::pixmap( const QString& image, const QSize& size, CalamaresUtils:: pixmap = pixmap.scaledToWidth( size.width(), Qt::SmoothTransformation ); } else + { pixmap = pixmap.scaled( size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); + } } putInCache( image, size, mode, opacity, pixmap, tint ); @@ -151,7 +153,12 @@ ImageRegistry::pixmap( const QString& image, const QSize& size, CalamaresUtils:: void -ImageRegistry::putInCache( const QString& image, const QSize& size, CalamaresUtils::ImageMode mode, float opacity, const QPixmap& pixmap, QColor tint ) +ImageRegistry::putInCache( const QString& image, + const QSize& size, + CalamaresUtils::ImageMode mode, + qreal opacity, + const QPixmap& pixmap, + QColor tint ) { QHash< qint64, QPixmap > subsubcache; QHash< int, QHash< qint64, QPixmap > > subcache; diff --git a/src/libcalamaresui/utils/ImageRegistry.h b/src/libcalamaresui/utils/ImageRegistry.h index e35eaf74a..06ab45831 100644 --- a/src/libcalamaresui/utils/ImageRegistry.h +++ b/src/libcalamaresui/utils/ImageRegistry.h @@ -2,6 +2,8 @@ * * SPDX-License-Identifier: GPLv3+ * License-Filename: LICENSES/GPLv3+-ImageRegistry + * + * Copyright 2019, Adriaan de Groot */ /* @@ -26,8 +28,8 @@ #include -#include "utils/CalamaresUtilsGui.h" #include "UiDllMacro.h" +#include "utils/CalamaresUtilsGui.h" class UIDLLEXPORT ImageRegistry { @@ -37,13 +39,20 @@ public: explicit ImageRegistry(); QIcon icon( const QString& image, CalamaresUtils::ImageMode mode = CalamaresUtils::Original ); - QPixmap pixmap( const QString& image, const QSize& size, CalamaresUtils::ImageMode mode = CalamaresUtils::Original, float opacity = 1.0, QColor tint = QColor( 0, 0, 0, 0 ) ); + QPixmap pixmap( const QString& image, + const QSize& size, + CalamaresUtils::ImageMode mode = CalamaresUtils::Original, + qreal opacity = 1.0, + QColor tint = QColor( 0, 0, 0, 0 ) ); private: - qint64 cacheKey( const QSize& size, float opacity, QColor tint ); - void putInCache( const QString& image, const QSize& size, CalamaresUtils::ImageMode mode, float opacity, const QPixmap& pixmap, QColor tint ); - - static ImageRegistry* s_instance; + qint64 cacheKey( const QSize& size, qreal opacity, QColor tint ); + void putInCache( const QString& image, + const QSize& size, + CalamaresUtils::ImageMode mode, + qreal opacity, + const QPixmap& pixmap, + QColor tint ); }; -#endif // IMAGE_REGISTRY_H +#endif // IMAGE_REGISTRY_H From 96ef488f1bbd0c298c7d20efc2722ab46fc21944 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 17:17:46 +0200 Subject: [PATCH 182/302] [calamares] Clean up VariantModel - stop compiler warnings with some judicious casting; that's what you get when a container indexed by int stored those indexes as quintptr. - apply coding style --- src/calamares/VariantModel.cpp | 46 +++++++++++++++++++++------------- src/calamares/VariantModel.h | 4 +++ 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/calamares/VariantModel.cpp b/src/calamares/VariantModel.cpp index 5eaf4bac7..a7e1243f3 100644 --- a/src/calamares/VariantModel.cpp +++ b/src/calamares/VariantModel.cpp @@ -19,7 +19,7 @@ #include "VariantModel.h" static void -overallLength( const QVariant& item, int& c, int parent, VariantModel::IndexVector* skiplist ) +overallLength( const QVariant& item, quintptr& c, quintptr parent, VariantModel::IndexVector* skiplist ) { if ( skiplist ) { @@ -46,9 +46,11 @@ overallLength( const QVariant& item, int& c, int parent, VariantModel::IndexVect static quintptr findNth( const VariantModel::IndexVector& skiplist, quintptr value, int n ) { + constexpr const quintptr invalid_index = static_cast< quintptr >( -1 ); + if ( n < 0 ) { - return -1; + return invalid_index; } int index = 0; @@ -58,12 +60,13 @@ findNth( const VariantModel::IndexVector& skiplist, quintptr value, int n ) { if ( --n < 0 ) { - return index; + // It's bigger than 0 + return static_cast< quintptr >( index ); } } index++; } - return -1; + return invalid_index; } @@ -78,16 +81,19 @@ VariantModel::~VariantModel() {} void VariantModel::reload() { - int x = 0; - overallLength( *m_p, x, -1, nullptr ); + constexpr const quintptr invalid_index = static_cast< quintptr >( -1 ); + + quintptr x = 0; m_rows.clear(); // Start over - m_rows.reserve( x ); // We'll need this much - x = 0; - overallLength( *m_p, x, -1, &m_rows ); + if ( m_rows.capacity() < 64 ) + { + m_rows.reserve( 64 ); // Start reasonably-sized + } + overallLength( *m_p, x, invalid_index, &m_rows ); } int -VariantModel::columnCount( const QModelIndex& index ) const +VariantModel::columnCount( const QModelIndex& ) const { return 2; } @@ -106,7 +112,7 @@ VariantModel::index( int row, int column, const QModelIndex& parent ) const if ( parent.isValid() ) { - if ( !( parent.internalId() >= m_rows.count() ) ) + if ( inRange( parent ) ) { p = parent.internalId(); } @@ -115,27 +121,33 @@ VariantModel::index( int row, int column, const QModelIndex& parent ) const return createIndex( row, column, findNth( m_rows, p, row ) ); } +static inline quintptr +deref( const VariantModel::IndexVector& v, quintptr i ) +{ + return v[ static_cast< int >( i ) ]; +} + QModelIndex VariantModel::parent( const QModelIndex& index ) const { - if ( !index.isValid() || ( index.internalId() > m_rows.count() ) ) + if ( !index.isValid() || !inRange( index ) ) { return QModelIndex(); } - quintptr p = m_rows[ index.internalId() ]; + quintptr p = deref( m_rows, index.internalId() ); if ( p == 0 ) { return QModelIndex(); } - if ( p >= m_rows.count() ) + if ( !inRange( p ) ) { return QModelIndex(); } - quintptr p_pid = m_rows[ p ]; + quintptr p_pid = deref( m_rows, p ); int row = 0; - for ( int i = 0; i < p; ++i ) + for ( int i = 0; i < static_cast< int >( p ); ++i ) { if ( m_rows[ i ] == p_pid ) { @@ -164,7 +176,7 @@ VariantModel::data( const QModelIndex& index, int role ) const return QVariant(); } - if ( index.internalId() >= m_rows.count() ) + if ( !inRange( index ) ) { return QVariant(); } diff --git a/src/calamares/VariantModel.h b/src/calamares/VariantModel.h index 9c4256f6a..372400940 100644 --- a/src/calamares/VariantModel.h +++ b/src/calamares/VariantModel.h @@ -79,6 +79,10 @@ private: /// @brief Implementation of walking an index through the variant-tree const QVariant underlying( const QModelIndex& index ) const; + + /// @brief Helpers for range-checking + inline bool inRange( quintptr p ) const { return p < static_cast< quintptr >( m_rows.count() ); } + inline bool inRange( const QModelIndex& index ) const { return inRange( index.internalId() ); } }; #endif From 08a08f9b54b0a2fc1f84d30c2ec0d8f6caceb7c7 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 9 Aug 2019 17:29:28 +0200 Subject: [PATCH 183/302] [calamares] Minor optimizations and documentation - document the data structure; for the vector V (called m_rows) the values are V_i < i, so that enables microscopic optimizations. --- src/calamares/VariantModel.cpp | 4 ++-- src/calamares/VariantModel.h | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/calamares/VariantModel.cpp b/src/calamares/VariantModel.cpp index a7e1243f3..2d8313665 100644 --- a/src/calamares/VariantModel.cpp +++ b/src/calamares/VariantModel.cpp @@ -53,7 +53,7 @@ findNth( const VariantModel::IndexVector& skiplist, quintptr value, int n ) return invalid_index; } - int index = 0; + int index = static_cast< int >( value ); while ( ( n >= 0 ) && ( index < skiplist.count() ) ) { if ( skiplist[ index ] == value ) @@ -147,7 +147,7 @@ VariantModel::parent( const QModelIndex& index ) const } quintptr p_pid = deref( m_rows, p ); int row = 0; - for ( int i = 0; i < static_cast< int >( p ); ++i ) + for ( int i = static_cast< int >( p_pid ); i < static_cast< int >( p ); ++i ) { if ( m_rows[ i ] == p_pid ) { diff --git a/src/calamares/VariantModel.h b/src/calamares/VariantModel.h index 372400940..bdf6da866 100644 --- a/src/calamares/VariantModel.h +++ b/src/calamares/VariantModel.h @@ -75,6 +75,30 @@ public: private: const QVariant* const m_p; + + /** @brief Tree representation of the variant. + * + * At index 0 in the vector , we store -1 to indicate the root. + * + * Then we enumerate all the elements in the tree (by traversing + * the variant and using QVariantMap and QVariantList as having + * children, and everything else being a leaf node) and at the index + * for a child, store the index of its parent. This means that direct + * children of the root store a 0 in their indexes, children of the first + * child of the root store a 1, and we can "pointer chase" from an index + * through parents back to index 0. + * + * Because of this structure, the value stored at index i must be + * less than i (except for index 0, which is special). This makes it + * slightly easier to search for a given value *p*, because we can start + * at index *p* (or even *p+1*). + * + * Given an index *i* into the vector corresponding to a child, we know the + * parent, but can also count which row this child should have, by counting + * *other* indexes before *i* with the same parent (and by the ordering + * of values, we can start counting at index *parent-index*). + * + */ IndexVector m_rows; /// @brief Implementation of walking an index through the variant-tree From 5c94a7b15d07ffc837456be331270b130510e065 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Sat, 10 Aug 2019 01:00:28 -0400 Subject: [PATCH 184/302] [settings.conf] fix yaml --- settings.conf | 60 +++++++++++++++++++++++++-------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/settings.conf b/settings.conf index 3d2ce4b93..d13963c24 100644 --- a/settings.conf +++ b/settings.conf @@ -86,38 +86,38 @@ modules-search: [ local ] # YAML: list of lists of strings. sequence: - show: - - welcome - - locale - - keyboard - - partition - - users - - summary + - welcome + - locale + - keyboard + - partition + - users + - summary - exec: - - partition - - mount - - unpackfs - - machineid - - fstab - - locale - - keyboard - - localecfg - - luksopenswaphookcfg - - luksbootkeyfile - - plymouthcfg - - initcpiocfg - - initcpio - - users - - displaymanager - - mhwdcfg - - networkcfg - - hwclock - - services-systemd - - grubcfg - - bootloader - - postcfg - - umount + - partition + - mount + - unpackfs + - machineid + - fstab + - locale + - keyboard + - localecfg + - luksopenswaphookcfg + - luksbootkeyfile + - plymouthcfg + - initcpiocfg + - initcpio + - users + - displaymanager + - mhwdcfg + - networkcfg + - hwclock + - services-systemd + - grubcfg + - bootloader + - postcfg + - umount - show: - - finished + - finished # A branding component is a directory, either in SHARE/calamares/branding or # in /etc/calamares/branding (the latter takes precedence). The directory must From a1014f765685813fa590ef737b715db74571184e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Sat, 10 Aug 2019 01:15:59 -0400 Subject: [PATCH 185/302] [libcalamaresui] try to fix pythonqt --- src/libcalamaresui/viewpages/PythonQtViewStep.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcalamaresui/viewpages/PythonQtViewStep.h b/src/libcalamaresui/viewpages/PythonQtViewStep.h index b6b7c193b..f3655e945 100644 --- a/src/libcalamaresui/viewpages/PythonQtViewStep.h +++ b/src/libcalamaresui/viewpages/PythonQtViewStep.h @@ -21,7 +21,7 @@ #include "ViewStep.h" -#include +#include namespace Calamares { From b700eea6f92e06656ad328d5f6a92071be28e533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Sat, 10 Aug 2019 01:19:53 -0400 Subject: [PATCH 186/302] Revert "[libcalamaresui] try to fix pythonqt" This reverts commit a1014f765685813fa590ef737b715db74571184e. --- src/libcalamaresui/viewpages/PythonQtViewStep.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcalamaresui/viewpages/PythonQtViewStep.h b/src/libcalamaresui/viewpages/PythonQtViewStep.h index f3655e945..b6b7c193b 100644 --- a/src/libcalamaresui/viewpages/PythonQtViewStep.h +++ b/src/libcalamaresui/viewpages/PythonQtViewStep.h @@ -21,7 +21,7 @@ #include "ViewStep.h" -#include +#include namespace Calamares { From 8c78a6cdfa6bc0943b7e2ac4776636f811e6d222 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 12 Aug 2019 12:05:50 +0200 Subject: [PATCH 187/302] Documentation: match stated requirements with CMakeLists.txt --- README.md | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index f35b012c8..df4c02b66 100644 --- a/README.md +++ b/README.md @@ -13,28 +13,22 @@ ### Dependencies Main: -* Compiler with C++11 support: GCC >= 4.9.0 or Clang >= 3.5.1 -* CMake >= 3.2 -* Qt >= 5.7 +* Compiler with C++14 support: GCC >= 5 or Clang >= 3.5.1 +* CMake >= 3.3 +* Qt >= 5.9 * yaml-cpp >= 0.5.1 * Python >= 3.3 (required for some modules) -* Boost.Python >= 1.55.0 (recommended, or PythonQt; one is required for some modules) -* PythonQt (recommended, or Boost.Python; one is required for some modules) -* extra-cmake-modules >= 5.18 (recommended; required for some modules) +* Boost.Python >= 1.55.0 (required for some modules) +* KDE extra-cmake-modules >= 5.18 (recommended; required for some modules; + required for some tests) +* PythonQt (optional, deprecated) Modules: -* welcome: - * NetworkManager - * UPower (optional, runtime) -* partition: - * extra-cmake-modules - * KF5: KCoreAddons, KConfig, KI18n, KService, KWidgetsAddons - * KPMcore >= 3.3 -* bootloader: - * systemd-boot or GRUB -* unpackfs: - * squashfs-tools - * rsync +* 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 +* *users* LibPWQuality (optional) ### Building From a6db224fcb98d90309aea2795ad444e4c16231f0 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 8 Aug 2019 13:32:20 +0200 Subject: [PATCH 188/302] [fsresizer] [partition] Gracefully fail on missing dependencies - If KPMcore is found -- it requires some other KDE Frameworks but at least in pre-4.0 versions doesn't check very well for them -- then missing its dependencies is no cause for CMake failure. Instead, log it nicely and suppress the module. --- src/modules/fsresizer/CMakeLists.txt | 14 +++++++++----- src/modules/partition/CMakeLists.txt | 14 +++++++++----- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/modules/fsresizer/CMakeLists.txt b/src/modules/fsresizer/CMakeLists.txt index ba9c81f4c..3d82489b7 100644 --- a/src/modules/fsresizer/CMakeLists.txt +++ b/src/modules/fsresizer/CMakeLists.txt @@ -1,11 +1,11 @@ find_package( KPMcore 3.3 ) +find_package( KF5Config CONFIG ) +find_package( KF5I18n CONFIG ) +find_package( KF5WidgetsAddons CONFIG ) set( _partition_defs "" ) -if ( KPMcore_FOUND ) - find_package( Qt5 REQUIRED DBus ) # Needed for KPMCore - find_package( KF5 REQUIRED I18n WidgetsAddons ) # Needed for KPMCore - +if ( KPMcore_FOUND AND Qt5DBus_FOUND AND KF5CoreAddons_FOUND AND KF5Config_FOUND ) include_directories( ${KPMCORE_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/src/modules/partition ) if ( KPMcore_VERSION VERSION_GREATER "3.3.0") @@ -48,5 +48,9 @@ if ( KPMcore_FOUND ) target_compile_definitions( fsresizertest PRIVATE ${_partition_defs} ) endif() else() - calamares_skip_module( "fsresizer (missing suitable KPMcore)" ) + if ( NOT KPMcore_FOUND ) + calamares_skip_module( "fsresizer (missing suitable KPMcore)" ) + else() + calamares_skip_module( "fsresizer (missing dependencies for KPMcore)" ) + endif() endif() diff --git a/src/modules/partition/CMakeLists.txt b/src/modules/partition/CMakeLists.txt index df1588cb2..f9c32b39e 100644 --- a/src/modules/partition/CMakeLists.txt +++ b/src/modules/partition/CMakeLists.txt @@ -22,11 +22,11 @@ set_package_properties( KPMcore PROPERTIES PURPOSE "For partitioning module" ) +find_package( KF5Config CONFIG ) +find_package( KF5I18n CONFIG ) +find_package( KF5WidgetsAddons CONFIG ) -if ( KPMcore_FOUND ) - find_package( Qt5 REQUIRED DBus ) - find_package( KF5 REQUIRED Config CoreAddons I18n WidgetsAddons ) - +if ( KPMcore_FOUND AND Qt5DBus_FOUND AND KF5CoreAddons_FOUND AND KF5Config_FOUND ) if ( KPMcore_VERSION VERSION_GREATER "3.3.0") list( APPEND _partition_defs WITH_KPMCORE331API) # kpmcore > 3.3.0 with deprecations endif() @@ -106,5 +106,9 @@ if ( KPMcore_FOUND ) SHARED_LIB ) else() - calamares_skip_module( "partition (missing suitable KPMcore)" ) + if ( NOT KPMcore_FOUND ) + calamares_skip_module( "partition (missing suitable KPMcore)" ) + else() + calamares_skip_module( "partition (missing dependencies for KPMcore)" ) + endif() endif() From bcb7f17584161fe0805605ca8eae2db8c2f3d1a2 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 8 Aug 2019 14:06:33 +0200 Subject: [PATCH 189/302] [calamares] Make KCoreAddons a requirement - Require KCoreAddons for KAboutData (also, optionally, for KOSRelease) --- CMakeLists.txt | 30 +++++++++++++++++++++++++++--- src/calamares/CMakeLists.txt | 2 +- src/calamares/main.cpp | 7 ++++--- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 36c09abf0..5461aa3c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -261,6 +261,8 @@ if( Qt5_VERSION VERSION_GREATER 5.12.1 ) list( APPEND _tx_ok "eo" ) endif() endif() +# Optional Qt parts +find_package( Qt5DBus CONFIG ) find_package( YAMLCPP ${YAMLCPP_VERSION} REQUIRED ) if( INSTALL_POLKIT ) @@ -291,7 +293,14 @@ if( ECM_FOUND ) include(KDEInstallDirs) endif() -find_package( KF5 COMPONENTS CoreAddons Crash ) +find_package( KF5 QUIET COMPONENTS CoreAddons Crash ) +set_package_properties( + KF5::CoreAddons PROPERTIES + TYPE REQUIRED + DESCRIPTION "Classes built on QtCore for About Data" + URL "https://api.kde.org/frameworks/kcoreaddons/" + PURPOSE "About Calamares" +) if( NOT KF5Crash_FOUND ) set( WITH_KF5Crash OFF ) endif() @@ -590,10 +599,25 @@ add_custom_target( uninstall ### CMAKE SUMMARY REPORT # -feature_summary(WHAT ALL) - get_directory_property( SKIPPED_MODULES DIRECTORY src/modules DEFINITION LIST_SKIPPED_MODULES ) calamares_explain_skipped_modules( ${SKIPPED_MODULES} ) + +feature_summary( + WHAT DISABLED_FEATURES + DESCRIPTION "The following features have been disabled:" + QUIET_ON_EMPTY +) +feature_summary( + WHAT OPTIONAL_PACKAGES_NOT_FOUND + DESCRIPTION "The following OPTIONAL packages were not found:" + QUIET_ON_EMPTY +) +feature_summary( + WHAT REQUIRED_PACKAGES_NOT_FOUND + FATAL_ON_MISSING_REQUIRED_PACKAGES + DESCRIPTION "The following REQUIRED packages were not found:" + QUIET_ON_EMPTY +) diff --git a/src/calamares/CMakeLists.txt b/src/calamares/CMakeLists.txt index 259e3bf56..a55e26b6d 100644 --- a/src/calamares/CMakeLists.txt +++ b/src/calamares/CMakeLists.txt @@ -46,11 +46,11 @@ target_link_libraries( calamares_bin calamaresui Qt5::Core Qt5::Widgets + KF5::CoreAddons ) if( WITH_KF5Crash ) target_link_libraries( calamares_bin PRIVATE - KF5::CoreAddons KF5::Crash ) target_compile_definitions( calamares_bin PRIVATE WITH_KF5Crash ) diff --git a/src/calamares/main.cpp b/src/calamares/main.cpp index 704c2bf59..caf1f6cfd 100644 --- a/src/calamares/main.cpp +++ b/src/calamares/main.cpp @@ -26,8 +26,8 @@ #include "3rdparty/kdsingleapplicationguard/kdsingleapplicationguard.h" -#ifdef WITH_KF5Crash #include +#ifdef WITH_KF5Crash #include #endif @@ -93,7 +93,6 @@ main( int argc, char* argv[] ) { CalamaresApplication a( argc, argv ); -#ifdef WITH_KF5Crash KAboutData aboutData( "calamares", "Calamares", a.applicationVersion(), @@ -104,12 +103,14 @@ main( int argc, char* argv[] ) "https://calamares.io", "https://github.com/calamares/calamares/issues" ); KAboutData::setApplicationData( aboutData ); + a.setApplicationDisplayName( QString() ); // To avoid putting an extra "Calamares/" into the log-file + +#ifdef WITH_KF5Crash KCrash::initialize(); // KCrash::setCrashHandler(); KCrash::setDrKonqiEnabled( true ); KCrash::setFlags( KCrash::SaferDialog | KCrash::AlwaysDirectly ); // TODO: umount anything in /tmp/calamares-... as an emergency save function - a.setApplicationDisplayName( QString() ); #endif handle_args( a ); From 44991e700b943003fe58030ce7dbdcaa43bbf0dd Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 8 Aug 2019 14:30:50 +0200 Subject: [PATCH 190/302] [libcalamaresui] Check KCoreAddons version directly --- src/libcalamaresui/CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libcalamaresui/CMakeLists.txt b/src/libcalamaresui/CMakeLists.txt index 111113a47..a9d31c2c3 100644 --- a/src/libcalamaresui/CMakeLists.txt +++ b/src/libcalamaresui/CMakeLists.txt @@ -75,8 +75,6 @@ calamares_add_library( calamaresui VERSION ${CALAMARES_VERSION_SHORT} ) -find_package( KF5CoreAddons 5.58 QUIET ) # If it's really new -if ( KF5CoreAddons_FOUND ) +if ( KF5CoreAddons_FOUND AND KF5CoreAddons_VERSION VERSION_GREATER_EQUAL 5.58 ) target_compile_definitions( calamaresui PRIVATE WITH_KOSRelease ) - target_link_libraries( calamaresui PRIVATE KF5::CoreAddons ) endif() From 1711071c588b6fdd779ca06dcbcea1f99dbb62f5 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 8 Aug 2019 14:31:25 +0200 Subject: [PATCH 191/302] [libcalamares] Swap out own PluginLoader for KCoreAddons --- src/libcalamares/CMakeLists.txt | 2 +- src/libcalamares/utils/PluginFactory.cpp | 127 ---------- src/libcalamares/utils/PluginFactory.h | 291 +---------------------- src/libcalamares/utils/PluginFactory_p.h | 55 ----- 4 files changed, 5 insertions(+), 470 deletions(-) delete mode 100644 src/libcalamares/utils/PluginFactory.cpp delete mode 100644 src/libcalamares/utils/PluginFactory_p.h diff --git a/src/libcalamares/CMakeLists.txt b/src/libcalamares/CMakeLists.txt index 790d4b6ac..c6f8cd0d2 100644 --- a/src/libcalamares/CMakeLists.txt +++ b/src/libcalamares/CMakeLists.txt @@ -44,7 +44,6 @@ set( libSources utils/CommandList.cpp utils/Dirs.cpp utils/Logger.cpp - utils/PluginFactory.cpp utils/Retranslator.cpp utils/String.cpp utils/UMask.cpp @@ -120,6 +119,7 @@ target_link_libraries( calamares LINK_PUBLIC ${YAMLCPP_LIBRARY} Qt5::Core + KF5::CoreAddons ${OPTIONAL_PUBLIC_LIBRARIES} ) diff --git a/src/libcalamares/utils/PluginFactory.cpp b/src/libcalamares/utils/PluginFactory.cpp deleted file mode 100644 index 878182ea4..000000000 --- a/src/libcalamares/utils/PluginFactory.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* === This file is part of Calamares - === - * - * Copyright 2015, Teo Mrnjavac - * Copyright 2017-2018, Adriaan de Groot - * - * Based on KPluginFactory from KCoreAddons, KDE project - * Copyright 2007, Matthias Kretz - * Copyright 2007, Bernhard Loos - * - * 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 "PluginFactory.h" -#include "PluginFactory_p.h" - -#include -#include - -// *INDENT-OFF* -// clang-format off - -Q_GLOBAL_STATIC( QObjectCleanupHandler, factorycleanup ) - -namespace Calamares -{ - -PluginFactory::PluginFactory() - : pd_ptr( new PluginFactoryPrivate ) -{ - pd_ptr->q_ptr = this; - - factorycleanup()->add( this ); -} - -PluginFactory::PluginFactory( PluginFactoryPrivate& d ) - : pd_ptr( &d ) -{ - factorycleanup()->add( this ); -} - -PluginFactory::~PluginFactory() -{ - delete pd_ptr; -} - -void PluginFactory::doRegisterPlugin( const QString& keyword, const QMetaObject* metaObject, CreateInstanceFunction instanceFunction ) -{ - Q_ASSERT( metaObject ); - - // we allow different interfaces to be registered without keyword - if ( !keyword.isEmpty() ) - { - if ( pd_ptr->createInstanceHash.contains( keyword ) ) - qWarning() << "A plugin with the keyword" << keyword << "was already registered. A keyword must be unique!"; - pd_ptr->createInstanceHash.insert( keyword, PluginFactoryPrivate::Plugin( metaObject, instanceFunction ) ); - } - else - { - const QList clashes( pd_ptr->createInstanceHash.values( keyword ) ); - const QMetaObject* superClass = metaObject->superClass(); - if ( superClass ) - { - for ( const PluginFactoryPrivate::Plugin& plugin : clashes ) - { - for ( const QMetaObject* otherSuper = plugin.first->superClass(); otherSuper; - otherSuper = otherSuper->superClass() ) - { - if ( superClass == otherSuper ) - qWarning() << "Two plugins with the same interface(" << superClass->className() << ") were registered. Use keywords to identify the plugins."; - } - } - } - for ( const PluginFactoryPrivate::Plugin& plugin : clashes ) - { - superClass = plugin.first->superClass(); - if ( superClass ) - { - for ( const QMetaObject* otherSuper = metaObject->superClass(); otherSuper; - otherSuper = otherSuper->superClass() ) - { - if ( superClass == otherSuper ) - qWarning() << "Two plugins with the same interface(" << superClass->className() << ") were registered. Use keywords to identify the plugins."; - } - } - } - pd_ptr->createInstanceHash.insertMulti( keyword, PluginFactoryPrivate::Plugin( metaObject, instanceFunction ) ); - } -} - -QObject* PluginFactory::create( const char* iface, QWidget* parentWidget, QObject* parent, const QString& keyword ) -{ - QObject* obj = nullptr; - - const QList candidates( pd_ptr->createInstanceHash.values( keyword ) ); - // for !keyword.isEmpty() candidates.count() is 0 or 1 - - for ( const PluginFactoryPrivate::Plugin& plugin : candidates ) - { - for ( const QMetaObject* current = plugin.first; current; current = current->superClass() ) - { - if ( 0 == qstrcmp( iface, current->className() ) ) - { - if ( obj ) - qWarning() << "ambiguous interface requested from a DSO containing more than one plugin"; - obj = plugin.second( parentWidget, parent ); - break; - } - } - } - - if ( obj ) - emit objectCreated( obj ); - return obj; -} - -} diff --git a/src/libcalamares/utils/PluginFactory.h b/src/libcalamares/utils/PluginFactory.h index f2481f10d..2ba9fd3cd 100644 --- a/src/libcalamares/utils/PluginFactory.h +++ b/src/libcalamares/utils/PluginFactory.h @@ -24,298 +24,15 @@ #ifndef UTILS_PLUGINFACTORY_H #define UTILS_PLUGINFACTORY_H -#include "DllMacro.h" - -#include -#include -#include - -// *INDENT-OFF* -// clang-format off - -namespace Calamares -{ -class PluginFactoryPrivate; -} +#include #define CalamaresPluginFactory_iid "io.calamares.PluginFactory" -/** - * \relates PluginFactory - * - * CALAMARES_PLUGIN_FACTORY_DECLARATION declares the PluginFactory subclass. This macro - * can be used in a header file. - * - * \param name The name of the PluginFactory derived class. - * - * \see CALAMARES_PLUGIN_FACTORY - * \see CALAMARES_PLUGIN_FACTORY_DEFINITION - */ #define CALAMARES_PLUGIN_FACTORY_DECLARATION(name) \ - class name : public Calamares::PluginFactory \ - { \ - Q_OBJECT \ - Q_INTERFACES(Calamares::PluginFactory) \ - Q_PLUGIN_METADATA(IID CalamaresPluginFactory_iid) \ - public: \ - explicit name(); \ - ~name(); \ - private: \ - void init(); \ - }; - -/** - * \relates PluginFactory - * CALAMARES_PLUGIN_FACTORY_DEFINITION defines the PluginFactory subclass. This macro - * can not be used in a header file. - * - * \param name The name of the PluginFactory derived class. - * - * \param pluginRegistrations Code to be inserted into the constructor of the - * class. Usually a series of registerPlugin() calls. - * - * \see CALAMARES_PLUGIN_FACTORY - * \see CALAMARES_PLUGIN_FACTORY_DECLARATION - */ + K_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY_SKEL(name,KPluginFactory,Q_PLUGIN_METADATA(IID CalamaresPluginFactory_iid)) #define CALAMARES_PLUGIN_FACTORY_DEFINITION(name, pluginRegistrations) \ - name::name() \ - { \ - pluginRegistrations \ - } \ - name::~name() {} + K_PLUGIN_FACTORY_DEFINITION(name, pluginRegistrations ) -namespace Calamares -{ - -/** - * \class PluginFactory PluginFactory.h - * - * PluginFactory provides a convenient way to provide factory-style plugins. - * Qt plugins provide a singleton object, but a common pattern is for plugins - * to generate as many objects of a particular type as the application requires. - * By using PluginFactory, you can avoid implementing the factory pattern - * yourself. - * - * PluginFactory also allows plugins to provide multiple different object - * types, indexed by keywords. - * - * The objects created by PluginFactory must inherit QObject, and must have a - * standard constructor pattern: - * \li if the object is a KPart::Part, it must be of the form - * \code - * T(QWidget *parentWidget, QObject *parent, const QVariantList &args) - * \endcode - * \li if it is a QWidget, it must be of the form - * \code - * T(QWidget *parent, const QVariantList &args) - * \endcode - * \li otherwise it must be of the form - * \code - * T(QObject *parent, const QVariantList &args) - * \endcode - * - * You should typically use CALAMARES_PLUGIN_FACTORY_DEFINITION() in your plugin code to - * create the factory. The pattern is - * - * \code - * #include "utils/PluginFactory.h" - * - * class MyPlugin : public PluginInterface - * { - * public: - * MyPlugin(QObject *parent, const QVariantList &args) - * : PluginInterface(parent) - * {} - * }; - * - * CALAMARES_PLUGIN_FACTORY_DEFINITION(MyPluginFactory, - * registerPlugin(); - * ) - * \endcode - * - * If you want to load a library use KPluginLoader. - * The application that wants to instantiate plugin classes can do the following: - * \code - * PluginFactory *factory = KPluginLoader("libraryname").factory(); - * if (factory) { - * PluginInterface *p1 = factory->create(parent); - * OtherInterface *p2 = factory->create(parent); - * NextInterface *p3 = factory->create("keyword1", parent); - * NextInterface *p3 = factory->create("keyword2", parent); - * } - * \endcode - * - * \author Matthias Kretz - * \author Bernhard Loos - */ -class DLLEXPORT PluginFactory : public QObject -{ - Q_OBJECT - friend class PluginFactoryPrivate; -public: - /** - * This constructor creates a factory for a plugin. - */ - explicit PluginFactory(); - - /** - * This destroys the PluginFactory. - */ - virtual ~PluginFactory(); - - /** - * Use this method to create an object. It will try to create an object which inherits - * \p T. If it has multiple choices, you will get a fatal error (kFatal()), so be careful - * to request a unique interface or use keywords. - * - * \tparam T The interface for which an object should be created. The object will inherit \p T. - * \param parent The parent of the object. If \p parent is a widget type, it will also passed - * to the parentWidget argument of the CreateInstanceFunction for the object. - * \returns A pointer to the created object is returned, or 0 if an error occurred. - */ - template - T* create( QObject* parent = nullptr ); - - /** - * Use this method to create an object. It will try to create an object which inherits - * \p T and was registered with \p keyword. - * - * \tparam T The interface for which an object should be created. The object will inherit \p T. - * \param keyword The keyword of the object. - * \param parent The parent of the object. If \p parent is a widget type, it will also passed - * to the parentWidget argument of the CreateInstanceFunction for the object. - * \returns A pointer to the created object is returned, or 0 if an error occurred. - */ - template - T* create( const QString& keyword, QObject* parent = nullptr ); - -Q_SIGNALS: - void objectCreated( QObject* object ); - -protected: - /** - * Function pointer type to a function that instantiates a plugin. - */ - typedef QObject* ( *CreateInstanceFunction )( QWidget*, QObject* ); - - /** - * This is used to detect the arguments need for the constructor of plugin classes. - * You can inherit it, if you want to add new classes and still keep support for the old ones. - */ - template - struct InheritanceChecker - { - CreateInstanceFunction createInstanceFunction( QWidget* ) - { - return &createInstance; - } - CreateInstanceFunction createInstanceFunction( ... ) - { - return &createInstance; - } - }; - - explicit PluginFactory( PluginFactoryPrivate& dd ); - - /** - * Registers a plugin with the factory. Call this function from the constructor of the - * PluginFactory subclass to make the create function able to instantiate the plugin when asked - * for an interface the plugin implements. - * - * \tparam T the name of the plugin class - * - * \param keyword An optional keyword as unique identifier for the plugin. This allows you to - * put more than one plugin with the same interface into the same library using the same - * factory. X-KDE-PluginKeyword is a convenient way to specify the keyword in a desktop file. - * - * \param instanceFunction A function pointer to a function that creates an instance of the - * plugin. The default function that will be used depends on the type of interface. If the - * interface inherits from - * \li \c KParts::Part the function will call - * \code - * new T(QWidget *parentWidget, QObject *parent) - * \endcode - * \li \c QWidget the function will call - * \code - * new T(QWidget *parent) - * \endcode - * \li else the function will call - * \code - * new T(QObject *parent) - * \endcode - */ - template - void registerPlugin( const QString& keyword = QString(), - CreateInstanceFunction instanceFunction - = InheritanceChecker().createInstanceFunction( reinterpret_cast( 0 ) ) ) - { - doRegisterPlugin( keyword, &T::staticMetaObject, instanceFunction ); - } - - PluginFactoryPrivate* const pd_ptr; - - /** - * This function is called when the factory asked to create an Object. - * - * You may reimplement it to provide a very flexible factory. This is especially useful to - * provide generic factories for plugins implemeted using a scripting language. - * - * \param iface The staticMetaObject::className() string identifying the plugin interface that - * was requested. E.g. for KCModule plugins this string will be "KCModule". - * \param parentWidget Only used if the requested plugin is a KPart. - * \param parent The parent object for the plugin object. - * \param keyword A string that uniquely identifies the plugin. If a KService is used this - * keyword is read from the X-KDE-PluginKeyword entry in the .desktop file. - */ - virtual QObject* create( const char* iface, QWidget* parentWidget, QObject* parent, const QString& keyword ); - - template - static QObject* createInstance( QWidget* parentWidget, QObject* parent ) - { - Q_UNUSED( parentWidget ) - ParentType* p = nullptr; - if ( parent ) - { - p = qobject_cast( parent ); - Q_ASSERT( p ); - } - return new impl( p ); - } - -private: - void doRegisterPlugin( const QString& keyword, const QMetaObject* metaObject, CreateInstanceFunction instanceFunction ); -}; - -template -inline T* PluginFactory::create( QObject* parent ) -{ - QObject* o = create( T::staticMetaObject.className(), - parent && parent->isWidgetType() ? reinterpret_cast( parent ) : nullptr, - parent, - QString() ); - - T* t = qobject_cast( o ); - if ( !t ) - delete o; - return t; -} - -template -inline T* PluginFactory::create( const QString& keyword, QObject* parent ) -{ - QObject* o = create( T::staticMetaObject.className(), - parent && parent->isWidgetType() ? reinterpret_cast( parent ) : nullptr, - parent, - keyword ); - - T* t = qobject_cast( o ); - if ( !t ) - delete o; - return t; -} - -} // namespace - -Q_DECLARE_INTERFACE( Calamares::PluginFactory, CalamaresPluginFactory_iid ) +// Q_DECLARE_INTERFACE( Calamares::PluginFactory, CalamaresPluginFactory_iid ) #endif diff --git a/src/libcalamares/utils/PluginFactory_p.h b/src/libcalamares/utils/PluginFactory_p.h deleted file mode 100644 index dc272f077..000000000 --- a/src/libcalamares/utils/PluginFactory_p.h +++ /dev/null @@ -1,55 +0,0 @@ -/* === This file is part of Calamares - === - * - * Copyright 2015, Teo Mrnjavac - * - * Based on KPluginFactory from KCoreAddons, KDE project - * Copyright 2007, Matthias Kretz - * Copyright 2007, Bernhard Loos - * - * 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 UTILS_PLUGINFACTORY_P_H -#define UTILS_PLUGINFACTORY_P_H - -#include "PluginFactory.h" - -#include - -namespace Calamares -{ - -class PluginFactoryPrivate -{ - Q_DECLARE_PUBLIC( PluginFactory ) -protected: - typedef QPair< const QMetaObject*, PluginFactory::CreateInstanceFunction > Plugin; - - PluginFactoryPrivate() - : catalogInitialized( false ) - , q_ptr( nullptr ) - { - } - ~PluginFactoryPrivate() {} - - QHash< QString, Plugin > createInstanceHash; - QString catalogName; - bool catalogInitialized; - - PluginFactory* q_ptr; -}; - -} // namespace Calamares - -#endif From 9098f8d7410661e286787200c19c079a2522ec28 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 12 Aug 2019 13:29:53 +0200 Subject: [PATCH 192/302] Changes: document KCoreAddons dependency --- CHANGES | 5 +++++ README.md | 1 + 2 files changed, 6 insertions(+) diff --git a/CHANGES b/CHANGES index dbdcb3523..00ea25223 100644 --- a/CHANGES +++ b/CHANGES @@ -13,6 +13,11 @@ This release contains contributions from (alphabetically by first name): has had a few updates and has now been consistently applied across the core codebase (e.g. libcalamares, libcalamaresui, calamares, but not the modules). +- *KCoreAddons* is now a required dependency. This lets us drop a chunk + of code that was copied from KCoreAddons years ago, and use the + (maintained!) upstream version instead. It also gives us KMacroExpander + everywhere, which will simplify code for handling substitutions + in configuration files. ## Modules ## diff --git a/README.md b/README.md index df4c02b66..e2e87fddf 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ Main: * Boost.Python >= 1.55.0 (required for some modules) * KDE extra-cmake-modules >= 5.18 (recommended; required for some modules; required for some tests) +* KDE Frameworks KCoreAddons (>= 5.58 recommended) * PythonQt (optional, deprecated) Modules: From 2ab45cf4f0d7181ca3b393feb213288e16a8f77b Mon Sep 17 00:00:00 2001 From: Arnaud Rebillout Date: Tue, 16 Jul 2019 20:20:19 +0700 Subject: [PATCH 193/302] Make sure that variable num_files_total_local is declared This variable is declared in `if m:`. Of course if this codepath doesn't run, the variable is not declared an Python doesn't like this kind of surprise... Signed-off-by: Arnaud Rebillout --- src/modules/unpackfs/main.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/unpackfs/main.py b/src/modules/unpackfs/main.py index ac90a994e..e956dc070 100644 --- a/src/modules/unpackfs/main.py +++ b/src/modules/unpackfs/main.py @@ -103,6 +103,7 @@ def file_copy(source, dest, progress_cb): if not source.endswith("/"): source += "/" + num_files_total_local = 0 num_files_copied = 0 # Gets updated through rsync output args = ['rsync', '-aHAXr'] From bf47e761b041c55aa880650759a311e225e24bbe Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Wed, 17 Jul 2019 12:15:22 +0200 Subject: [PATCH 194/302] mount: Make sure extra mounts are mounted right after / When the rootfs partition is read-only, mount points for the other partitions cannot be created, therefore they need to be created in a tmpfs, already mounted somewhere in `/`. However, the extra mounts are only mounted at the end, which causes an error as no tmpfs is currently mounted. This patch makes sure all extra mounts are mounted right after the `/` partition, allowing the use of a read-only rootfs. Signed-off-by: Arnaud Ferraris --- src/modules/mount/main.py | 184 +++++++++++++++++++------------------- 1 file changed, 94 insertions(+), 90 deletions(-) diff --git a/src/modules/mount/main.py b/src/modules/mount/main.py index ed649aead..b093d0dfb 100644 --- a/src/modules/mount/main.py +++ b/src/modules/mount/main.py @@ -37,104 +37,109 @@ _ = gettext.translation("calamares-python", def pretty_name(): return _("Mounting partitions.") +def mount_part(root_mount_point, partition, partitions): + # Create mount point with `+` rather than `os.path.join()` because + # `partition["mountPoint"]` starts with a '/'. + raw_mount_point = partition["mountPoint"] + mount_point = root_mount_point + raw_mount_point -def mount_partitions(root_mount_point, 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]) + + fstype = partition.get("fs", "").lower() + + if fstype == "fat16" or fstype == "fat32": + fstype = "vfat" + + if "luksMapperName" in partition: + libcalamares.utils.debug( + "about to mount {!s}".format(partition["luksMapperName"])) + libcalamares.utils.mount( + "/dev/mapper/{!s}".format(partition["luksMapperName"]), + mount_point, + fstype, + partition.get("options", ""), + ) + + else: + libcalamares.utils.mount(partition["device"], + mount_point, + fstype, + partition.get("options", ""), + ) + + # If the root partition is btrfs, we create a subvolume "@" + # for the root mount point. + # If a separate /home partition isn't defined, we also create + # a subvolume "@home". + # Finally we remount all of the above on the correct paths. + if fstype == "btrfs" and partition["mountPoint"] == '/': + has_home_mount_point = False + for p in partitions: + if "mountPoint" not in p or not p["mountPoint"]: + continue + if p["mountPoint"] == "/home": + has_home_mount_point = True + break + + subprocess.check_call(['btrfs', 'subvolume', 'create', + root_mount_point + '/@']) + + if not has_home_mount_point: + subprocess.check_call(['btrfs', 'subvolume', 'create', + root_mount_point + '/@home']) + + subprocess.check_call(["umount", "-v", root_mount_point]) + + if "luksMapperName" in partition: + libcalamares.utils.mount( + "/dev/mapper/{!s}".format(partition["luksMapperName"]), + mount_point, + fstype, + ",".join( + ["subvol=@", partition.get("options", "")]), + ) + if not has_home_mount_point: + libcalamares.utils.mount( + "/dev/mapper/{!s}".format(partition["luksMapperName"]), + root_mount_point + "/home", + fstype, + ",".join( + ["subvol=@home", partition.get("options", "")]), + ) + else: + libcalamares.utils.mount( + partition["device"], + mount_point, + fstype, + ",".join(["subvol=@", partition.get("options", "")]), + ) + if not has_home_mount_point: + libcalamares.utils.mount( + partition["device"], + root_mount_point + "/home", + fstype, + ",".join( + ["subvol=@home", partition.get("options", "")]), + ) + +def mount_partitions(root_mount_point, partitions, extra_mounts=None): """ Pass back mount point and filesystem for each partition. :param root_mount_point: :param partitions: + :param extra_mounts: """ for partition in partitions: if "mountPoint" not in partition or not partition["mountPoint"]: continue - # Create mount point with `+` rather than `os.path.join()` because - # `partition["mountPoint"]` starts with a '/'. - raw_mount_point = partition["mountPoint"] - mount_point = root_mount_point + raw_mount_point - - # 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]) - - fstype = partition.get("fs", "").lower() - - if fstype == "fat16" or fstype == "fat32": - fstype = "vfat" - - if "luksMapperName" in partition: - libcalamares.utils.debug( - "about to mount {!s}".format(partition["luksMapperName"])) - libcalamares.utils.mount( - "/dev/mapper/{!s}".format(partition["luksMapperName"]), - mount_point, - fstype, - partition.get("options", ""), - ) - - else: - libcalamares.utils.mount(partition["device"], - mount_point, - fstype, - partition.get("options", ""), - ) - - # If the root partition is btrfs, we create a subvolume "@" - # for the root mount point. - # If a separate /home partition isn't defined, we also create - # a subvolume "@home". - # Finally we remount all of the above on the correct paths. - if fstype == "btrfs" and partition["mountPoint"] == '/': - has_home_mount_point = False - for p in partitions: - if "mountPoint" not in p or not p["mountPoint"]: - continue - if p["mountPoint"] == "/home": - has_home_mount_point = True - break - - subprocess.check_call(['btrfs', 'subvolume', 'create', - root_mount_point + '/@']) - - if not has_home_mount_point: - subprocess.check_call(['btrfs', 'subvolume', 'create', - root_mount_point + '/@home']) - - subprocess.check_call(["umount", "-v", root_mount_point]) - - if "luksMapperName" in partition: - libcalamares.utils.mount( - "/dev/mapper/{!s}".format(partition["luksMapperName"]), - mount_point, - fstype, - ",".join( - ["subvol=@", partition.get("options", "")]), - ) - if not has_home_mount_point: - libcalamares.utils.mount( - "/dev/mapper/{!s}".format(partition["luksMapperName"]), - root_mount_point + "/home", - fstype, - ",".join( - ["subvol=@home", partition.get("options", "")]), - ) - else: - libcalamares.utils.mount( - partition["device"], - mount_point, - fstype, - ",".join(["subvol=@", partition.get("options", "")]), - ) - if not has_home_mount_point: - libcalamares.utils.mount( - partition["device"], - root_mount_point + "/home", - fstype, - ",".join( - ["subvol=@home", partition.get("options", "")]), - ) + mount_part(root_mount_point, partition, partitions) + if partition["mountPoint"] is "/" and extra_mounts is not None: + mount_partitions(root_mount_point, extra_mounts) def run(): @@ -160,8 +165,7 @@ def run(): # Sort by mount points to ensure / is mounted before the rest partitions.sort(key=lambda x: x["mountPoint"]) - mount_partitions(root_mount_point, partitions) - mount_partitions(root_mount_point, extra_mounts) + mount_partitions(root_mount_point, partitions, extra_mounts) all_extra_mounts = extra_mounts if libcalamares.globalstorage.value("firmwareType") == "efi": From 0d06e047ae32f5a0c9afddb8a0df1986f3b006d4 Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Mon, 22 Jul 2019 15:56:20 +0200 Subject: [PATCH 195/302] libcalamares: Prevent integer overflows when parsing configuration Currently, a number of configuration parsing-related functions and classes use only `int` type for dealing with integers. Should the user need a bigger integer value, this would result in an erroneous value being used (`0`), as the correct value would overflow the 32-bits type. In order to prevent these overflow, this patch replaces `int` with `qint64` in the following functions & classes : * CalamaresUtils::yamlScalarToVariant() * CalamaresUtils::getInteger * NamedSuffix * PartitionSize This way, sizes or other integer values greater than 2^31 (for signed types) can be used. Signed-off-by: Arnaud Ferraris --- src/libcalamares/partition/PartitionSize.cpp | 2 +- src/libcalamares/utils/NamedSuffix.h | 8 ++++---- src/libcalamares/utils/Variant.cpp | 10 +++++++--- src/libcalamares/utils/Variant.h | 2 +- src/libcalamares/utils/Yaml.cpp | 2 +- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/libcalamares/partition/PartitionSize.cpp b/src/libcalamares/partition/PartitionSize.cpp index 3f4463f3c..3397dcbec 100644 --- a/src/libcalamares/partition/PartitionSize.cpp +++ b/src/libcalamares/partition/PartitionSize.cpp @@ -50,7 +50,7 @@ PartitionSize::PartitionSize( const QString& s ) if ( m_unit == SizeUnit::None ) { - m_value = s.toInt(); + m_value = s.toLongLong(); if ( m_value > 0 ) { m_unit = SizeUnit::Byte; diff --git a/src/libcalamares/utils/NamedSuffix.h b/src/libcalamares/utils/NamedSuffix.h index e697c0640..8ad52edea 100644 --- a/src/libcalamares/utils/NamedSuffix.h +++ b/src/libcalamares/utils/NamedSuffix.h @@ -58,7 +58,7 @@ public: } /** @brief Specific value and unit. */ - NamedSuffix( int value, unit_t unit ) + NamedSuffix( qint64 value, unit_t unit ) : m_value( value ) , m_unit( unit ) { @@ -75,7 +75,7 @@ public: for ( const auto& suffix : table.table ) if ( s.endsWith( suffix.first ) ) { - m_value = s.left( s.length() - suffix.first.length() ).toInt(); + m_value = s.left( s.length() - suffix.first.length() ).toLongLong(); m_unit = suffix.second; break; } @@ -89,7 +89,7 @@ public: */ NamedSuffix( const QString& s ); - int value() const { return m_value; } + qint64 value() const { return m_value; } unit_t unit() const { return m_unit; } /** @brief Check that a value-unit combination is valid. @@ -100,7 +100,7 @@ public: bool isValid() const; protected: - int m_value; + qint64 m_value; unit_t m_unit; }; diff --git a/src/libcalamares/utils/Variant.cpp b/src/libcalamares/utils/Variant.cpp index 2e7a13eed..c56f9301a 100644 --- a/src/libcalamares/utils/Variant.cpp +++ b/src/libcalamares/utils/Variant.cpp @@ -61,10 +61,10 @@ getString( const QVariantMap& map, const QString& key ) return QString(); } -int -getInteger( const QVariantMap& map, const QString& key, int d ) +qint64 +getInteger( const QVariantMap& map, const QString& key, qint64 d ) { - int result = d; + qint64 result = d; if ( map.contains( key ) ) { auto v = map.value( key ); @@ -72,6 +72,10 @@ getInteger( const QVariantMap& map, const QString& key, int d ) { result = v.toInt(); } + else if ( v.type() == QVariant::LongLong ) + { + result = v.toLongLong(); + } } return result; diff --git a/src/libcalamares/utils/Variant.h b/src/libcalamares/utils/Variant.h index c68c2a801..15f791b74 100644 --- a/src/libcalamares/utils/Variant.h +++ b/src/libcalamares/utils/Variant.h @@ -41,7 +41,7 @@ DLLEXPORT QString getString( const QVariantMap& map, const QString& key ); /** * Get an integer value from a mapping; returns @p d if no value. */ -DLLEXPORT int getInteger( const QVariantMap& map, const QString& key, int d ); +DLLEXPORT qint64 getInteger( const QVariantMap& map, const QString& key, qint64 d ); /** * Get a double value from a mapping (integers are converted); returns @p d if no value. diff --git a/src/libcalamares/utils/Yaml.cpp b/src/libcalamares/utils/Yaml.cpp index cad6ac1fe..164c17a21 100644 --- a/src/libcalamares/utils/Yaml.cpp +++ b/src/libcalamares/utils/Yaml.cpp @@ -79,7 +79,7 @@ yamlScalarToVariant( const YAML::Node& scalarNode ) } if ( QRegExp( "[-+]?\\d+" ).exactMatch( scalarString ) ) { - return QVariant( scalarString.toInt() ); + return QVariant( scalarString.toLongLong() ); } if ( QRegExp( "[-+]?\\d*\\.?\\d+" ).exactMatch( scalarString ) ) { From 3929557a5ac5ad69af6f6ada1a9a3c04941d9c9d Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Thu, 25 Jul 2019 09:53:02 +0200 Subject: [PATCH 196/302] welcome: Fix requirements parsing As the config files integer are now of type `QVariant::LongLong` instead of `QVariant::Int`, requirements relying on this type were not parsed correctly. This patch fixes this, and adds an option to the python conversion to take into account `QVariant::LongLong` types. Signed-off-by: Arnaud Ferraris --- src/libcalamares/PythonHelper.cpp | 3 +++ src/modules/welcome/checker/GeneralRequirements.cpp | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/libcalamares/PythonHelper.cpp b/src/libcalamares/PythonHelper.cpp index 40210856b..670390d6c 100644 --- a/src/libcalamares/PythonHelper.cpp +++ b/src/libcalamares/PythonHelper.cpp @@ -52,6 +52,9 @@ variantToPyObject( const QVariant& variant ) case QVariant::Int: return bp::object( variant.toInt() ); + case QVariant::LongLong: + return bp::object( variant.toLongLong() ); + case QVariant::Double: return bp::object( variant.toDouble() ); diff --git a/src/modules/welcome/checker/GeneralRequirements.cpp b/src/modules/welcome/checker/GeneralRequirements.cpp index 812605091..0e6133d3f 100644 --- a/src/modules/welcome/checker/GeneralRequirements.cpp +++ b/src/modules/welcome/checker/GeneralRequirements.cpp @@ -206,7 +206,7 @@ GeneralRequirements::setConfigurationMap( const QVariantMap& configurationMap ) if ( configurationMap.contains( "requiredStorage" ) && ( configurationMap.value( "requiredStorage" ).type() == QVariant::Double || - configurationMap.value( "requiredStorage" ).type() == QVariant::Int ) ) + configurationMap.value( "requiredStorage" ).type() == QVariant::LongLong ) ) { bool ok = false; m_requiredStorageGiB = configurationMap.value( "requiredStorage" ).toDouble( &ok ); @@ -227,7 +227,7 @@ GeneralRequirements::setConfigurationMap( const QVariantMap& configurationMap ) if ( configurationMap.contains( "requiredRam" ) && ( configurationMap.value( "requiredRam" ).type() == QVariant::Double || - configurationMap.value( "requiredRam" ).type() == QVariant::Int ) ) + configurationMap.value( "requiredRam" ).type() == QVariant::LongLong ) ) { bool ok = false; m_requiredRamGiB = configurationMap.value( "requiredRam" ).toDouble( &ok ); From 0716a46eb2a79668c727bfc5b24f539306cd65e2 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 12 Aug 2019 15:52:59 +0200 Subject: [PATCH 197/302] [libcalamares] Switch to using KPluginFactory - this is not entirely straightfoward, since we need different constructor arguments for the objects Calamares creates (no QVariantList& args, in particular). Implement our own registerPlugin() and createInstance() for that. - work around a bug in K_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY --- src/libcalamares/CMakeLists.txt | 1 + src/libcalamares/utils/PluginFactory.cpp | 11 +++ src/libcalamares/utils/PluginFactory.h | 69 ++++++++++++++++++- .../modulesystem/CppJobModule.cpp | 2 +- .../modulesystem/ViewModule.cpp | 2 +- 5 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 src/libcalamares/utils/PluginFactory.cpp diff --git a/src/libcalamares/CMakeLists.txt b/src/libcalamares/CMakeLists.txt index c6f8cd0d2..f2063813c 100644 --- a/src/libcalamares/CMakeLists.txt +++ b/src/libcalamares/CMakeLists.txt @@ -44,6 +44,7 @@ set( libSources utils/CommandList.cpp utils/Dirs.cpp utils/Logger.cpp + utils/PluginFactory.cpp utils/Retranslator.cpp utils/String.cpp utils/UMask.cpp diff --git a/src/libcalamares/utils/PluginFactory.cpp b/src/libcalamares/utils/PluginFactory.cpp new file mode 100644 index 000000000..7e1b29921 --- /dev/null +++ b/src/libcalamares/utils/PluginFactory.cpp @@ -0,0 +1,11 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, Adriaan de Groot + * + */ + +#include "PluginFactory.h" + +CalamaresPluginFactory::~CalamaresPluginFactory() +{ +} diff --git a/src/libcalamares/utils/PluginFactory.h b/src/libcalamares/utils/PluginFactory.h index 2ba9fd3cd..20c82c464 100644 --- a/src/libcalamares/utils/PluginFactory.h +++ b/src/libcalamares/utils/PluginFactory.h @@ -28,10 +28,75 @@ #define CalamaresPluginFactory_iid "io.calamares.PluginFactory" +/** @brief Plugin factory for Calamares + * + * Try to re-use KPluginFactory as much as possible (since the + * old code for PluginFactory was a fork of an old version of + * exactly that). + * + * The current createInstance() method passes more arguments + * to the job and viewstep constructors than we want; chasing + * that change means modifying each Calamares module. This class + * implements a version of createInstance() with fewer arguments + * and overloads registerPlugin() to use that. + */ +class CalamaresPluginFactory : public KPluginFactory +{ + Q_OBJECT +public: + explicit CalamaresPluginFactory() : KPluginFactory() {} + ~CalamaresPluginFactory() override; + + /** @brief Create an object from the factory. + * + * Ignores all the @p args since they are not used. Calls + * Calamares constructors for the Jobs and ViewSteps. + */ + template + static QObject *createInstance(QWidget *parentWidget, QObject *parent, const QVariantList &args) + { + Q_UNUSED(parentWidget); + Q_UNUSED(args); + ParentType *p = nullptr; + if (parent) { + p = qobject_cast(parent); + Q_ASSERT(p); + } + return new impl(p); + } + + /** @brief register a plugin + * + * The Calamares version doesn't accept keywords, and uses + * the Calamares createInstance() version which ignores + * the QVariantList of arguments. + */ + template + void registerPlugin() + { + KPluginFactory::registerPlugin(QString(), &createInstance); + } +}; + +/** @brief declare a Calamares Plugin Factory + * + * This would be defined as K_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY, + * except that does not actually use the base factory class that is + * passed in. + */ #define CALAMARES_PLUGIN_FACTORY_DECLARATION(name) \ - K_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY_SKEL(name,KPluginFactory,Q_PLUGIN_METADATA(IID CalamaresPluginFactory_iid)) + class name : public CalamaresPluginFactory \ + { \ + Q_OBJECT \ + Q_INTERFACES(KPluginFactory) \ + Q_PLUGIN_METADATA(IID CalamaresPluginFactory_iid) \ + public: \ + explicit name(); \ + ~name(); \ + }; #define CALAMARES_PLUGIN_FACTORY_DEFINITION(name, pluginRegistrations) \ - K_PLUGIN_FACTORY_DEFINITION(name, pluginRegistrations ) + K_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY(name,CalamaresPluginFactory,pluginRegistrations) + // Q_DECLARE_INTERFACE( Calamares::PluginFactory, CalamaresPluginFactory_iid ) diff --git a/src/libcalamaresui/modulesystem/CppJobModule.cpp b/src/libcalamaresui/modulesystem/CppJobModule.cpp index 17c191024..c6571dbf6 100644 --- a/src/libcalamaresui/modulesystem/CppJobModule.cpp +++ b/src/libcalamaresui/modulesystem/CppJobModule.cpp @@ -49,7 +49,7 @@ CppJobModule::loadSelf() { if ( m_loader ) { - PluginFactory* pf = qobject_cast< PluginFactory* >( m_loader->instance() ); + CalamaresPluginFactory* pf = qobject_cast< CalamaresPluginFactory* >( m_loader->instance() ); if ( !pf ) { cDebug() << Q_FUNC_INFO << m_loader->errorString(); diff --git a/src/libcalamaresui/modulesystem/ViewModule.cpp b/src/libcalamaresui/modulesystem/ViewModule.cpp index 5cd2fe7d9..7506e5348 100644 --- a/src/libcalamaresui/modulesystem/ViewModule.cpp +++ b/src/libcalamaresui/modulesystem/ViewModule.cpp @@ -50,7 +50,7 @@ ViewModule::loadSelf() { if ( m_loader ) { - PluginFactory* pf = qobject_cast< PluginFactory* >( m_loader->instance() ); + CalamaresPluginFactory* pf = qobject_cast< CalamaresPluginFactory* >( m_loader->instance() ); if ( !pf ) { cWarning() << Q_FUNC_INFO << "No factory:" << m_loader->errorString(); From 209e8331b7843e1dbc2ead5931a8354074865b43 Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Mon, 22 Jul 2019 16:29:39 +0200 Subject: [PATCH 198/302] libcalamares: Add support for KB/MB/GB size units Currently, all size units are expressed as KiB, MiB or GiB (resp. 2^10, 2^20 or 2^30). In order to maximize compatibility and consistent results with other partitioning tools, this commit adds support for sizes expressed as KB, MB or GB (resp. 10^3, 10^6 or 10^9). This change won't affect existing users, it simply adds a new option that wasn't previously handled. Signed-off-by: Arnaud Ferraris --- src/libcalamares/partition/PartitionSize.cpp | 27 +++++++++- src/libcalamares/partition/PartitionSize.h | 3 ++ src/libcalamares/utils/Units.h | 54 ++++++++++++++++++++ 3 files changed, 83 insertions(+), 1 deletion(-) diff --git a/src/libcalamares/partition/PartitionSize.cpp b/src/libcalamares/partition/PartitionSize.cpp index 3f4463f3c..bdb9eaad8 100644 --- a/src/libcalamares/partition/PartitionSize.cpp +++ b/src/libcalamares/partition/PartitionSize.cpp @@ -33,7 +33,8 @@ unitSuffixes() { QStringLiteral( "%" ), SizeUnit::Percent }, { QStringLiteral( "K" ), SizeUnit::KiB }, { QStringLiteral( "KiB" ), SizeUnit::KiB }, { QStringLiteral( "M" ), SizeUnit::MiB }, { QStringLiteral( "MiB" ), SizeUnit::MiB }, { QStringLiteral( "G" ), SizeUnit::GiB }, - { QStringLiteral( "GiB" ), SizeUnit::GiB } + { QStringLiteral( "GiB" ), SizeUnit::GiB }, { QStringLiteral( "KB" ), SizeUnit::KB }, + { QStringLiteral( "MB" ), SizeUnit::MB }, { QStringLiteral( "GB" ), SizeUnit::GB } }; return names; @@ -90,8 +91,11 @@ PartitionSize::toSectors( qint64 totalSectors, qint64 sectorSize ) const return totalSectors * value() / 100; } case SizeUnit::Byte: + case SizeUnit::KB: case SizeUnit::KiB: + case SizeUnit::MB: case SizeUnit::MiB: + case SizeUnit::GB: case SizeUnit::GiB: return CalamaresUtils::bytesToSectors( toBytes(), sectorSize ); } @@ -125,8 +129,11 @@ PartitionSize::toBytes( qint64 totalSectors, qint64 sectorSize ) const return totalSectors * value() / 100; } case SizeUnit::Byte: + case SizeUnit::KB: case SizeUnit::KiB: + case SizeUnit::MB: case SizeUnit::MiB: + case SizeUnit::GB: case SizeUnit::GiB: return toBytes(); } @@ -161,8 +168,11 @@ PartitionSize::toBytes( qint64 totalBytes ) const return totalBytes * value() / 100; } case SizeUnit::Byte: + case SizeUnit::KB: case SizeUnit::KiB: + case SizeUnit::MB: case SizeUnit::MiB: + case SizeUnit::GB: case SizeUnit::GiB: return toBytes(); } @@ -186,10 +196,16 @@ PartitionSize::toBytes() const return -1; case SizeUnit::Byte: return value(); + case SizeUnit::KB: + return CalamaresUtils::KBtoBytes( static_cast< unsigned long long >( value() ) ); case SizeUnit::KiB: return CalamaresUtils::KiBtoBytes( static_cast< unsigned long long >( value() ) ); + case SizeUnit::MB: + return CalamaresUtils::MBtoBytes( static_cast< unsigned long long >( value() ) ); case SizeUnit::MiB: return CalamaresUtils::MiBtoBytes( static_cast< unsigned long long >( value() ) ); + case SizeUnit::GB: + return CalamaresUtils::GBtoBytes( static_cast< unsigned long long >( value() ) ); case SizeUnit::GiB: return CalamaresUtils::GiBtoBytes( static_cast< unsigned long long >( value() ) ); } @@ -211,8 +227,11 @@ PartitionSize::operator<( const PartitionSize& other ) const case SizeUnit::Percent: return ( m_value < other.m_value ); case SizeUnit::Byte: + case SizeUnit::KB: case SizeUnit::KiB: + case SizeUnit::MB: case SizeUnit::MiB: + case SizeUnit::GB: case SizeUnit::GiB: return ( toBytes() < other.toBytes() ); } @@ -234,8 +253,11 @@ PartitionSize::operator>( const PartitionSize& other ) const case SizeUnit::Percent: return ( m_value > other.m_value ); case SizeUnit::Byte: + case SizeUnit::KB: case SizeUnit::KiB: + case SizeUnit::MB: case SizeUnit::MiB: + case SizeUnit::GB: case SizeUnit::GiB: return ( toBytes() > other.toBytes() ); } @@ -257,8 +279,11 @@ PartitionSize::operator==( const PartitionSize& other ) const case SizeUnit::Percent: return ( m_value == other.m_value ); case SizeUnit::Byte: + case SizeUnit::KB: case SizeUnit::KiB: + case SizeUnit::MB: case SizeUnit::MiB: + case SizeUnit::GB: case SizeUnit::GiB: return ( toBytes() == other.toBytes() ); } diff --git a/src/libcalamares/partition/PartitionSize.h b/src/libcalamares/partition/PartitionSize.h index 44cedbffe..b22698e55 100644 --- a/src/libcalamares/partition/PartitionSize.h +++ b/src/libcalamares/partition/PartitionSize.h @@ -36,8 +36,11 @@ enum class SizeUnit None, Percent, Byte, + KB, KiB, + MB, MiB, + GB, GiB }; diff --git a/src/libcalamares/utils/Units.h b/src/libcalamares/utils/Units.h index e1f30460a..b869d7dde 100644 --- a/src/libcalamares/utils/Units.h +++ b/src/libcalamares/utils/Units.h @@ -25,54 +25,108 @@ namespace CalamaresUtils { +/** User defined literals, 1_KB is 1 KiloByte (= 10^3 bytes) */ +constexpr qint64 operator""_KB( unsigned long long m ) +{ + return qint64( m ) * 1000; +} + /** User defined literals, 1_KiB is 1 KibiByte (= 2^10 bytes) */ constexpr qint64 operator""_KiB( unsigned long long m ) { return qint64( m ) * 1024; } +/** User defined literals, 1_MB is 1 MegaByte (= 10^6 bytes) */ +constexpr qint64 operator""_MB( unsigned long long m ) +{ + return operator""_KB(m)*1000; +} + /** User defined literals, 1_MiB is 1 MibiByte (= 2^20 bytes) */ constexpr qint64 operator""_MiB( unsigned long long m ) { return operator""_KiB(m)*1024; } +/** User defined literals, 1_GB is 1 GigaByte (= 10^9 bytes) */ +constexpr qint64 operator""_GB( unsigned long long m ) +{ + return operator""_MB(m)*1000; +} + /** User defined literals, 1_GiB is 1 GibiByte (= 2^30 bytes) */ constexpr qint64 operator""_GiB( unsigned long long m ) { return operator""_MiB(m)*1024; } +constexpr qint64 +KBtoBytes( unsigned long long m ) +{ + return operator""_KB( m ); +} + constexpr qint64 KiBtoBytes( unsigned long long m ) { return operator""_KiB( m ); } +constexpr qint64 +MBtoBytes( unsigned long long m ) +{ + return operator""_MB( m ); +} + constexpr qint64 MiBtoBytes( unsigned long long m ) { return operator""_MiB( m ); } +constexpr qint64 +GBtoBytes( unsigned long long m ) +{ + return operator""_GB( m ); +} + constexpr qint64 GiBtoBytes( unsigned long long m ) { return operator""_GiB( m ); } +constexpr qint64 +KBtoBytes( double m ) +{ + return qint64( m * 1000 ); +} + constexpr qint64 KiBtoBytes( double m ) { return qint64( m * 1024 ); } +constexpr qint64 +MBtoBytes( double m ) +{ + return qint64( m * 1000 * 1000 ); +} + constexpr qint64 MiBtoBytes( double m ) { return qint64( m * 1024 * 1024 ); } +constexpr qint64 +GBtoBytes( double m ) +{ + return qint64( m * 1000 * 1000 * 1000 ); +} + constexpr qint64 GiBtoBytes( double m ) { From 40202705ffd397757d74f9c0ab1ac82ce990a2c9 Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Mon, 22 Jul 2019 16:33:00 +0200 Subject: [PATCH 199/302] libcalamares: Align partition sizes on actual sectors Currently, the `bytesToSectors()` function rounds a partition size to the nearest MiB unit, which may lead to inconsistencies when a partition is expected to only be a few KiB's. This patch changes the behaviour of `bytesToSectors()` so that it aligns on sector size, without rounding the partition size to a multiple of 1MiB. Signed-off-by: Arnaud Ferraris --- src/libcalamares/utils/Units.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcalamares/utils/Units.h b/src/libcalamares/utils/Units.h index b869d7dde..7b8b8c172 100644 --- a/src/libcalamares/utils/Units.h +++ b/src/libcalamares/utils/Units.h @@ -160,7 +160,7 @@ alignBytesToBlockSize( qint64 bytes, qint64 blocksize ) constexpr qint64 bytesToSectors( qint64 bytes, qint64 blocksize ) { - return alignBytesToBlockSize( alignBytesToBlockSize( bytes, blocksize ), MiBtoBytes( 1ULL ) ) / blocksize; + return alignBytesToBlockSize( bytes, blocksize ) / blocksize; } } // namespace CalamaresUtils From a51d612afa456191b5c88be2ac32f89c06f09fba Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Tue, 13 Aug 2019 16:57:47 +0200 Subject: [PATCH 200/302] Revert "libcalamares: Align partition sizes on actual sectors" This reverts commit 40202705ffd397757d74f9c0ab1ac82ce990a2c9. --- src/libcalamares/utils/Units.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcalamares/utils/Units.h b/src/libcalamares/utils/Units.h index 7b8b8c172..b869d7dde 100644 --- a/src/libcalamares/utils/Units.h +++ b/src/libcalamares/utils/Units.h @@ -160,7 +160,7 @@ alignBytesToBlockSize( qint64 bytes, qint64 blocksize ) constexpr qint64 bytesToSectors( qint64 bytes, qint64 blocksize ) { - return alignBytesToBlockSize( bytes, blocksize ) / blocksize; + return alignBytesToBlockSize( alignBytesToBlockSize( bytes, blocksize ), MiBtoBytes( 1ULL ) ) / blocksize; } } // namespace CalamaresUtils From c57a30c73fb28718bfa0ad1bb7ababa49d26cf76 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 13 Aug 2019 17:06:27 +0200 Subject: [PATCH 201/302] Changes: credit where due for recent PRs --- CHANGES | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index 00ea25223..3f4aad749 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,8 @@ website will have to do for older versions. # 3.2.13 (unreleased) # This release contains contributions from (alphabetically by first name): + - Arnaud Ferraris + - Arnaud Rebillout ## Core ## From ccd707b23a82d1f426ec93af315f893c72cbde06 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 13 Aug 2019 20:49:58 +0200 Subject: [PATCH 202/302] [libcalamares] Apply coding style - .. or, rather, avoid re-formatting tables in future. --- src/libcalamares/partition/PartitionSize.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/libcalamares/partition/PartitionSize.cpp b/src/libcalamares/partition/PartitionSize.cpp index 90431fb70..fc8d72582 100644 --- a/src/libcalamares/partition/PartitionSize.cpp +++ b/src/libcalamares/partition/PartitionSize.cpp @@ -29,13 +29,22 @@ namespace Partition static const NamedEnumTable< SizeUnit >& unitSuffixes() { + // *INDENT-OFF* + // clang-format off static const NamedEnumTable< SizeUnit > names { - { QStringLiteral( "%" ), SizeUnit::Percent }, { QStringLiteral( "K" ), SizeUnit::KiB }, - { QStringLiteral( "KiB" ), SizeUnit::KiB }, { QStringLiteral( "M" ), SizeUnit::MiB }, - { QStringLiteral( "MiB" ), SizeUnit::MiB }, { QStringLiteral( "G" ), SizeUnit::GiB }, - { QStringLiteral( "GiB" ), SizeUnit::GiB }, { QStringLiteral( "KB" ), SizeUnit::KB }, - { QStringLiteral( "MB" ), SizeUnit::MB }, { QStringLiteral( "GB" ), SizeUnit::GB } + { QStringLiteral( "%" ), SizeUnit::Percent }, + { QStringLiteral( "K" ), SizeUnit::KiB }, + { QStringLiteral( "KiB" ), SizeUnit::KiB }, + { QStringLiteral( "M" ), SizeUnit::MiB }, + { QStringLiteral( "MiB" ), SizeUnit::MiB }, + { QStringLiteral( "G" ), SizeUnit::GiB }, + { QStringLiteral( "GiB" ), SizeUnit::GiB }, + { QStringLiteral( "KB" ), SizeUnit::KB }, + { QStringLiteral( "MB" ), SizeUnit::MB }, + { QStringLiteral( "GB" ), SizeUnit::GB } }; + // clang-format on + // *INDENT-ON* return names; } From f31ff8b9ea4ae05aaaf349b3bf66999212a3c500 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 13 Aug 2019 20:50:52 +0200 Subject: [PATCH 203/302] [libcalamares] Apply coding style to PluginFactory --- src/libcalamares/utils/PluginFactory.cpp | 4 +-- src/libcalamares/utils/PluginFactory.h | 38 +++++++++++++----------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/libcalamares/utils/PluginFactory.cpp b/src/libcalamares/utils/PluginFactory.cpp index 7e1b29921..50b88ebfd 100644 --- a/src/libcalamares/utils/PluginFactory.cpp +++ b/src/libcalamares/utils/PluginFactory.cpp @@ -6,6 +6,4 @@ #include "PluginFactory.h" -CalamaresPluginFactory::~CalamaresPluginFactory() -{ -} +CalamaresPluginFactory::~CalamaresPluginFactory() {} diff --git a/src/libcalamares/utils/PluginFactory.h b/src/libcalamares/utils/PluginFactory.h index 20c82c464..84694a83a 100644 --- a/src/libcalamares/utils/PluginFactory.h +++ b/src/libcalamares/utils/PluginFactory.h @@ -44,7 +44,10 @@ class CalamaresPluginFactory : public KPluginFactory { Q_OBJECT public: - explicit CalamaresPluginFactory() : KPluginFactory() {} + explicit CalamaresPluginFactory() + : KPluginFactory() + { + } ~CalamaresPluginFactory() override; /** @brief Create an object from the factory. @@ -52,17 +55,18 @@ public: * Ignores all the @p args since they are not used. Calls * Calamares constructors for the Jobs and ViewSteps. */ - template - static QObject *createInstance(QWidget *parentWidget, QObject *parent, const QVariantList &args) + template < class impl, class ParentType > + static QObject* createInstance( QWidget* parentWidget, QObject* parent, const QVariantList& args ) { - Q_UNUSED(parentWidget); - Q_UNUSED(args); - ParentType *p = nullptr; - if (parent) { - p = qobject_cast(parent); - Q_ASSERT(p); + Q_UNUSED( parentWidget ); + Q_UNUSED( args ); + ParentType* p = nullptr; + if ( parent ) + { + p = qobject_cast< ParentType* >( parent ); + Q_ASSERT( p ); } - return new impl(p); + return new impl( p ); } /** @brief register a plugin @@ -71,10 +75,10 @@ public: * the Calamares createInstance() version which ignores * the QVariantList of arguments. */ - template + template < class T > void registerPlugin() { - KPluginFactory::registerPlugin(QString(), &createInstance); + KPluginFactory::registerPlugin< T >( QString(), &createInstance< T, QObject > ); } }; @@ -84,18 +88,18 @@ public: * except that does not actually use the base factory class that is * passed in. */ -#define CALAMARES_PLUGIN_FACTORY_DECLARATION(name) \ +#define CALAMARES_PLUGIN_FACTORY_DECLARATION( name ) \ class name : public CalamaresPluginFactory \ { \ Q_OBJECT \ - Q_INTERFACES(KPluginFactory) \ - Q_PLUGIN_METADATA(IID CalamaresPluginFactory_iid) \ + Q_INTERFACES( KPluginFactory ) \ + Q_PLUGIN_METADATA( IID CalamaresPluginFactory_iid ) \ public: \ explicit name(); \ ~name(); \ }; -#define CALAMARES_PLUGIN_FACTORY_DEFINITION(name, pluginRegistrations) \ - K_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY(name,CalamaresPluginFactory,pluginRegistrations) +#define CALAMARES_PLUGIN_FACTORY_DEFINITION( name, pluginRegistrations ) \ + K_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY( name, CalamaresPluginFactory, pluginRegistrations ) // Q_DECLARE_INTERFACE( Calamares::PluginFactory, CalamaresPluginFactory_iid ) From 27c3a5a11d4739e5fe7081e72b48ed5318443f42 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 13 Aug 2019 20:51:46 +0200 Subject: [PATCH 204/302] [calamares] Apply coding style --- src/calamares/CalamaresVersion.h.in | 2 +- src/calamares/progresstree/ProgressTreeView.cpp | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/calamares/CalamaresVersion.h.in b/src/calamares/CalamaresVersion.h.in index 13a8c9e2e..4ac7ee1d1 100644 --- a/src/calamares/CalamaresVersion.h.in +++ b/src/calamares/CalamaresVersion.h.in @@ -14,4 +14,4 @@ #cmakedefine CALAMARES_TRANSLATION_LANGUAGES "${CALAMARES_TRANSLATION_LANGUAGES}" -#endif // CALAMARES_VERSION_H +#endif // CALAMARES_VERSION_H diff --git a/src/calamares/progresstree/ProgressTreeView.cpp b/src/calamares/progresstree/ProgressTreeView.cpp index d4f652363..5c81e3851 100644 --- a/src/calamares/progresstree/ProgressTreeView.cpp +++ b/src/calamares/progresstree/ProgressTreeView.cpp @@ -76,10 +76,9 @@ ProgressTreeView::setModel( QAbstractItemModel* model ) QTreeView::setModel( model ); expandAll(); - connect( - Calamares::ViewManager::instance(), - &Calamares::ViewManager::currentStepChanged, - this, - [this]() { viewport()->update(); }, - Qt::UniqueConnection ); + connect( Calamares::ViewManager::instance(), + &Calamares::ViewManager::currentStepChanged, + this, + [this]() { viewport()->update(); }, + Qt::UniqueConnection ); } From 6224d6605b20be6580b49b6ff1dbf2badc515834 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 13 Aug 2019 20:57:52 +0200 Subject: [PATCH 205/302] [libcalamaresui] Apply coding style to widgets/ --- src/libcalamaresui/widgets/ClickableLabel.cpp | 11 +++++++---- src/libcalamaresui/widgets/ClickableLabel.h | 2 +- .../widgets/FixedAspectRatioLabel.cpp | 17 +++++------------ .../widgets/FixedAspectRatioLabel.h | 4 ++-- src/libcalamaresui/widgets/WaitingWidget.h | 2 +- 5 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/libcalamaresui/widgets/ClickableLabel.cpp b/src/libcalamaresui/widgets/ClickableLabel.cpp index b6786cab8..62985acf8 100644 --- a/src/libcalamaresui/widgets/ClickableLabel.cpp +++ b/src/libcalamaresui/widgets/ClickableLabel.cpp @@ -23,16 +23,17 @@ ClickableLabel::ClickableLabel( QWidget* parent ) : QLabel( parent ) -{} +{ +} ClickableLabel::ClickableLabel( const QString& text, QWidget* parent ) : QLabel( text, parent ) -{} +{ +} -ClickableLabel::~ClickableLabel() -{} +ClickableLabel::~ClickableLabel() {} void @@ -48,5 +49,7 @@ ClickableLabel::mouseReleaseEvent( QMouseEvent* event ) { QLabel::mouseReleaseEvent( event ); if ( m_time.elapsed() < qApp->doubleClickInterval() ) + { emit clicked(); + } } diff --git a/src/libcalamaresui/widgets/ClickableLabel.h b/src/libcalamaresui/widgets/ClickableLabel.h index ab993c721..fd66082c5 100644 --- a/src/libcalamaresui/widgets/ClickableLabel.h +++ b/src/libcalamaresui/widgets/ClickableLabel.h @@ -42,4 +42,4 @@ private: QTime m_time; }; -#endif // CLICKABLELABEL_H +#endif // CLICKABLELABEL_H diff --git a/src/libcalamaresui/widgets/FixedAspectRatioLabel.cpp b/src/libcalamaresui/widgets/FixedAspectRatioLabel.cpp index d1094bb7c..c495ca5bb 100644 --- a/src/libcalamaresui/widgets/FixedAspectRatioLabel.cpp +++ b/src/libcalamaresui/widgets/FixedAspectRatioLabel.cpp @@ -22,21 +22,18 @@ FixedAspectRatioLabel::FixedAspectRatioLabel( QWidget* parent ) : QLabel( parent ) -{} +{ +} -FixedAspectRatioLabel::~FixedAspectRatioLabel() -{} +FixedAspectRatioLabel::~FixedAspectRatioLabel() {} void FixedAspectRatioLabel::setPixmap( const QPixmap& pixmap ) { m_pixmap = pixmap; - QLabel::setPixmap( pixmap.scaled( - contentsRect().size(), - Qt::KeepAspectRatio, - Qt::SmoothTransformation ) ); + QLabel::setPixmap( pixmap.scaled( contentsRect().size(), Qt::KeepAspectRatio, Qt::SmoothTransformation ) ); } @@ -44,9 +41,5 @@ void FixedAspectRatioLabel::resizeEvent( QResizeEvent* event ) { Q_UNUSED( event ) - QLabel::setPixmap( m_pixmap.scaled( - contentsRect().size(), - Qt::KeepAspectRatio, - Qt::SmoothTransformation ) ); + QLabel::setPixmap( m_pixmap.scaled( contentsRect().size(), Qt::KeepAspectRatio, Qt::SmoothTransformation ) ); } - diff --git a/src/libcalamaresui/widgets/FixedAspectRatioLabel.h b/src/libcalamaresui/widgets/FixedAspectRatioLabel.h index 8f881753c..9466fcd15 100644 --- a/src/libcalamaresui/widgets/FixedAspectRatioLabel.h +++ b/src/libcalamaresui/widgets/FixedAspectRatioLabel.h @@ -31,11 +31,11 @@ public: virtual ~FixedAspectRatioLabel() override; public slots: - void setPixmap( const QPixmap &pixmap ); + void setPixmap( const QPixmap& pixmap ); void resizeEvent( QResizeEvent* event ) override; private: QPixmap m_pixmap; }; -#endif // FIXEDASPECTRATIOLABEL_H +#endif // FIXEDASPECTRATIOLABEL_H diff --git a/src/libcalamaresui/widgets/WaitingWidget.h b/src/libcalamaresui/widgets/WaitingWidget.h index 5c19cce26..0d8b6fd5b 100644 --- a/src/libcalamaresui/widgets/WaitingWidget.h +++ b/src/libcalamaresui/widgets/WaitingWidget.h @@ -35,4 +35,4 @@ private: QLabel* m_waitingLabel; }; -#endif // WAITINGWIDGET_H +#endif // WAITINGWIDGET_H From 1b6aed8c402f1898727833b450c269e39e0856dd Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 13 Aug 2019 20:58:39 +0200 Subject: [PATCH 206/302] [libcalamaresui] Apply coding style to modulesystem/ --- src/libcalamaresui/modulesystem/ProcessJobModule.cpp | 2 ++ src/libcalamaresui/modulesystem/RequirementsChecker.cpp | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libcalamaresui/modulesystem/ProcessJobModule.cpp b/src/libcalamaresui/modulesystem/ProcessJobModule.cpp index 74c195b6b..fc4b5f254 100644 --- a/src/libcalamaresui/modulesystem/ProcessJobModule.cpp +++ b/src/libcalamaresui/modulesystem/ProcessJobModule.cpp @@ -77,7 +77,9 @@ ProcessJobModule::initFrom( const QVariantMap& moduleDescriptor ) { int sec = moduleDescriptor.value( "timeout" ).toInt(); if ( sec < 0 ) + { sec = 0; + } m_secondsTimeout = std::chrono::seconds( sec ); } diff --git a/src/libcalamaresui/modulesystem/RequirementsChecker.cpp b/src/libcalamaresui/modulesystem/RequirementsChecker.cpp index 916463ae4..41281c9b9 100644 --- a/src/libcalamaresui/modulesystem/RequirementsChecker.cpp +++ b/src/libcalamaresui/modulesystem/RequirementsChecker.cpp @@ -151,8 +151,7 @@ RequirementsChecker::reportProgress() m_progressTimeouts++; QStringList remainingNames; - auto remaining = std::count_if( m_watchers.cbegin(), m_watchers.cend(), - [&]( const Watcher* w ) { + auto remaining = std::count_if( m_watchers.cbegin(), m_watchers.cend(), [&]( const Watcher* w ) { if ( w && !w->isFinished() ) { remainingNames << w->objectName(); From 6f74463a80d608808c2136c617bd2672da9dacd9 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 13 Aug 2019 21:00:36 +0200 Subject: [PATCH 207/302] [libcalamaresui] Apply coding style to utils/ --- src/libcalamaresui/utils/CalamaresUtilsGui.cpp | 18 ++++++++++++++---- src/libcalamaresui/utils/CalamaresUtilsGui.h | 12 +++++------- src/libcalamaresui/utils/ImageRegistry.cpp | 2 +- src/libcalamaresui/utils/ImageRegistry.h | 2 +- src/libcalamaresui/utils/PythonQtUtils.cpp | 4 +++- src/libcalamaresui/utils/PythonQtUtils.h | 4 ++-- 6 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/libcalamaresui/utils/CalamaresUtilsGui.cpp b/src/libcalamaresui/utils/CalamaresUtilsGui.cpp index 808c805cb..b6c927763 100644 --- a/src/libcalamaresui/utils/CalamaresUtilsGui.cpp +++ b/src/libcalamaresui/utils/CalamaresUtilsGui.cpp @@ -34,11 +34,10 @@ namespace CalamaresUtils { -static int s_defaultFontSize = 0; +static int s_defaultFontSize = 0; static int s_defaultFontHeight = 0; - QPixmap defaultPixmap( ImageType type, ImageMode mode, const QSize& size ) { @@ -152,11 +151,15 @@ createRoundedImage( const QPixmap& pixmap, const QSize& size, float frameWidthPc } if ( !height || !width ) + { return QPixmap(); + } QPixmap scaledAvatar = pixmap.scaled( width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); if ( frameWidthPct == 0.00f ) + { return scaledAvatar; + } QPixmap frame( width, height ); frame.fill( Qt::transparent ); @@ -172,7 +175,8 @@ createRoundedImage( const QPixmap& pixmap, const QSize& size, float frameWidthPc painter.setBrush( brush ); painter.setPen( pen ); - painter.drawRoundedRect( outerRect, qreal( frameWidthPct ) * 100.0, qreal( frameWidthPct ) * 100.0, Qt::RelativeSize ); + painter.drawRoundedRect( + outerRect, qreal( frameWidthPct ) * 100.0, qreal( frameWidthPct ) * 100.0, Qt::RelativeSize ); return frame; } @@ -189,7 +193,9 @@ unmarginLayout( QLayout* layout ) { QLayout* childLayout = layout->itemAt( i )->layout(); if ( childLayout ) + { unmarginLayout( childLayout ); + } } } @@ -255,13 +261,17 @@ clearLayout( QLayout* layout ) while ( QLayoutItem* item = layout->takeAt( 0 ) ) { if ( QWidget* widget = item->widget() ) + { widget->deleteLater(); + } if ( QLayout* childLayout = item->layout() ) + { clearLayout( childLayout ); + } delete item; } } -} // namespace +} // namespace CalamaresUtils diff --git a/src/libcalamaresui/utils/CalamaresUtilsGui.h b/src/libcalamaresui/utils/CalamaresUtilsGui.h index 72430a083..012795e34 100644 --- a/src/libcalamaresui/utils/CalamaresUtilsGui.h +++ b/src/libcalamaresui/utils/CalamaresUtilsGui.h @@ -56,7 +56,7 @@ enum ImageType : int PartitionTable, BootEnvironment, Squid, - StatusOk, // Icons for the requirements checker + StatusOk, // Icons for the requirements checker StatusWarning, StatusError }; @@ -94,9 +94,7 @@ UIDLLEXPORT QPixmap defaultPixmap( ImageType type, * @return the transformed pixmap. * This one is currently unused. */ -UIDLLEXPORT QPixmap createRoundedImage( const QPixmap& avatar, - const QSize& size, - float frameWidthPct = 0.20f ); +UIDLLEXPORT QPixmap createRoundedImage( const QPixmap& avatar, const QSize& size, float frameWidthPct = 0.20f ); /** * @brief unmarginLayout recursively walks the QLayout tree and removes all margins. @@ -112,8 +110,8 @@ UIDLLEXPORT void unmarginLayout( QLayout* layout ); UIDLLEXPORT void clearLayout( QLayout* layout ); UIDLLEXPORT void setDefaultFontSize( int points ); -UIDLLEXPORT int defaultFontSize(); // in points -UIDLLEXPORT int defaultFontHeight(); // in pixels, DPI-specific +UIDLLEXPORT int defaultFontSize(); // in points +UIDLLEXPORT int defaultFontHeight(); // in pixels, DPI-specific UIDLLEXPORT QFont defaultFont(); UIDLLEXPORT QFont largeFont(); UIDLLEXPORT QSize defaultIconSize(); @@ -128,4 +126,4 @@ constexpr int windowPreferredHeight = 520; } // namespace CalamaresUtils -#endif // CALAMARESUTILSGUI_H +#endif // CALAMARESUTILSGUI_H diff --git a/src/libcalamaresui/utils/ImageRegistry.cpp b/src/libcalamaresui/utils/ImageRegistry.cpp index 5cffac11c..1c3b9433e 100644 --- a/src/libcalamaresui/utils/ImageRegistry.cpp +++ b/src/libcalamaresui/utils/ImageRegistry.cpp @@ -2,7 +2,7 @@ * * SPDX-License-Identifier: GPLv3+ * License-Filename: LICENSES/GPLv3+-ImageRegistry - * + * * Copyright 2019, Adriaan de Groot */ diff --git a/src/libcalamaresui/utils/ImageRegistry.h b/src/libcalamaresui/utils/ImageRegistry.h index 06ab45831..454cb500d 100644 --- a/src/libcalamaresui/utils/ImageRegistry.h +++ b/src/libcalamaresui/utils/ImageRegistry.h @@ -2,7 +2,7 @@ * * SPDX-License-Identifier: GPLv3+ * License-Filename: LICENSES/GPLv3+-ImageRegistry - * + * * Copyright 2019, Adriaan de Groot */ diff --git a/src/libcalamaresui/utils/PythonQtUtils.cpp b/src/libcalamaresui/utils/PythonQtUtils.cpp index 201fe6635..3a60839a4 100644 --- a/src/libcalamaresui/utils/PythonQtUtils.cpp +++ b/src/libcalamaresui/utils/PythonQtUtils.cpp @@ -34,11 +34,13 @@ lookupAndCall( PyObject* object, { PythonQtObjectPtr callable = PythonQt::self()->lookupCallable( object, name ); if ( callable ) + { return callable.call( args, kwargs ); + } } // If we haven't found a callable with the given names, we force an error: return PythonQt::self()->call( object, candidateNames.first(), args, kwargs ); } -} +} // namespace CalamaresUtils diff --git a/src/libcalamaresui/utils/PythonQtUtils.h b/src/libcalamaresui/utils/PythonQtUtils.h index 22a248cea..dc889b2d0 100644 --- a/src/libcalamaresui/utils/PythonQtUtils.h +++ b/src/libcalamaresui/utils/PythonQtUtils.h @@ -33,6 +33,6 @@ QVariant lookupAndCall( PyObject* object, const QVariantList& args = QVariantList(), const QVariantMap& kwargs = QVariantMap() ); -} //ns +} // namespace CalamaresUtils -#endif // PYTHONQTUTILS_H +#endif // PYTHONQTUTILS_H From d44e8f61153096595cf6272e17688696e3ddc433 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 13 Aug 2019 21:02:30 +0200 Subject: [PATCH 208/302] [libcalamaresui] Apply coding style to viewpages/ --- .../viewpages/BlankViewStep.cpp | 13 +-- src/libcalamaresui/viewpages/BlankViewStep.h | 7 +- .../PythonQtGlobalStorageWrapper.cpp | 3 +- .../viewpages/PythonQtGlobalStorageWrapper.h | 2 +- src/libcalamaresui/viewpages/PythonQtJob.cpp | 28 +++---- src/libcalamaresui/viewpages/PythonQtJob.h | 15 ++-- .../viewpages/PythonQtUtilsWrapper.cpp | 61 +++++--------- .../viewpages/PythonQtUtilsWrapper.h | 26 ++---- .../viewpages/PythonQtViewStep.cpp | 81 ++++++++----------- .../viewpages/PythonQtViewStep.h | 7 +- src/libcalamaresui/viewpages/ViewStep.cpp | 25 +++--- src/libcalamaresui/viewpages/ViewStep.h | 9 +-- 12 files changed, 110 insertions(+), 167 deletions(-) diff --git a/src/libcalamaresui/viewpages/BlankViewStep.cpp b/src/libcalamaresui/viewpages/BlankViewStep.cpp index 243305c1f..af10c7a99 100644 --- a/src/libcalamaresui/viewpages/BlankViewStep.cpp +++ b/src/libcalamaresui/viewpages/BlankViewStep.cpp @@ -26,7 +26,10 @@ namespace Calamares { -BlankViewStep::BlankViewStep( const QString& title, const QString& description, const QString& details, QObject* parent) +BlankViewStep::BlankViewStep( const QString& title, + const QString& description, + const QString& details, + QObject* parent ) : Calamares::ViewStep( parent ) , m_widget( new QWidget() ) { @@ -54,14 +57,12 @@ BlankViewStep::BlankViewStep( const QString& title, const QString& description, layout->addWidget( label ); } - layout->addStretch( 1 ); // Push the rest to the top + layout->addStretch( 1 ); // Push the rest to the top m_widget->setLayout( layout ); } -BlankViewStep::~BlankViewStep() -{ -} +BlankViewStep::~BlankViewStep() {} QString BlankViewStep::prettyName() const @@ -115,4 +116,4 @@ BlankViewStep::jobs() const return JobList(); } -} // namespace +} // namespace Calamares diff --git a/src/libcalamaresui/viewpages/BlankViewStep.h b/src/libcalamaresui/viewpages/BlankViewStep.h index a3f46d1d5..17d323c85 100644 --- a/src/libcalamaresui/viewpages/BlankViewStep.h +++ b/src/libcalamaresui/viewpages/BlankViewStep.h @@ -39,7 +39,10 @@ class BlankViewStep : public Calamares::ViewStep Q_OBJECT public: - explicit BlankViewStep( const QString& title, const QString& description, const QString& details = QString(), QObject* parent = nullptr ); + explicit BlankViewStep( const QString& title, + const QString& description, + const QString& details = QString(), + QObject* parent = nullptr ); virtual ~BlankViewStep() override; QString prettyName() const override; @@ -61,5 +64,5 @@ private: QWidget* m_widget; }; -} // namespace +} // namespace Calamares #endif // BLANKVIEWSTEP_H diff --git a/src/libcalamaresui/viewpages/PythonQtGlobalStorageWrapper.cpp b/src/libcalamaresui/viewpages/PythonQtGlobalStorageWrapper.cpp index 4eae8cf98..ba7657b09 100644 --- a/src/libcalamaresui/viewpages/PythonQtGlobalStorageWrapper.cpp +++ b/src/libcalamaresui/viewpages/PythonQtGlobalStorageWrapper.cpp @@ -24,7 +24,8 @@ GlobalStorage::GlobalStorage( Calamares::GlobalStorage* gs ) : QObject( gs ) , m_gs( gs ) -{} +{ +} bool diff --git a/src/libcalamaresui/viewpages/PythonQtGlobalStorageWrapper.h b/src/libcalamaresui/viewpages/PythonQtGlobalStorageWrapper.h index 8a8b775fc..946f93e97 100644 --- a/src/libcalamaresui/viewpages/PythonQtGlobalStorageWrapper.h +++ b/src/libcalamaresui/viewpages/PythonQtGlobalStorageWrapper.h @@ -54,4 +54,4 @@ private: Calamares::GlobalStorage* m_gs; }; -#endif // PYTHONQTGLOBALSTORAGEWRAPPER_H +#endif // PYTHONQTGLOBALSTORAGEWRAPPER_H diff --git a/src/libcalamaresui/viewpages/PythonQtJob.cpp b/src/libcalamaresui/viewpages/PythonQtJob.cpp index 291cbd014..0718df95d 100644 --- a/src/libcalamaresui/viewpages/PythonQtJob.cpp +++ b/src/libcalamaresui/viewpages/PythonQtJob.cpp @@ -20,34 +20,26 @@ #include "utils/PythonQtUtils.h" -PythonQtJob::PythonQtJob( PythonQtObjectPtr cxt, - PythonQtObjectPtr pyJob, - QObject* parent ) +PythonQtJob::PythonQtJob( PythonQtObjectPtr cxt, PythonQtObjectPtr pyJob, QObject* parent ) : Calamares::Job( parent ) , m_cxt( cxt ) , m_pyJob( pyJob ) { - } QString PythonQtJob::prettyName() const { - return CalamaresUtils::lookupAndCall( m_pyJob, - { "prettyName", - "prettyname", - "pretty_name" } ).toString(); + return CalamaresUtils::lookupAndCall( m_pyJob, { "prettyName", "prettyname", "pretty_name" } ).toString(); } QString PythonQtJob::prettyDescription() const { - return CalamaresUtils::lookupAndCall( m_pyJob, - { "prettyDescription", - "prettydescription", - "pretty_description" } ).toString(); + return CalamaresUtils::lookupAndCall( m_pyJob, { "prettyDescription", "prettydescription", "pretty_description" } ) + .toString(); } @@ -55,9 +47,8 @@ QString PythonQtJob::prettyStatusMessage() const { return CalamaresUtils::lookupAndCall( m_pyJob, - { "prettyStatusMessage", - "prettystatusmessage", - "pretty_status_message" } ).toString(); + { "prettyStatusMessage", "prettystatusmessage", "pretty_status_message" } ) + .toString(); } @@ -66,12 +57,15 @@ PythonQtJob::exec() { QVariant response = m_pyJob.call( "exec" ); if ( response.isNull() ) + { return Calamares::JobResult::ok(); + } QVariantMap map = response.toMap(); if ( map.isEmpty() || map.value( "ok" ).toBool() ) + { return Calamares::JobResult::ok(); + } - return Calamares::JobResult::error( map.value( "message" ).toString(), - map.value( "details" ).toString() ); + return Calamares::JobResult::error( map.value( "message" ).toString(), map.value( "details" ).toString() ); } diff --git a/src/libcalamaresui/viewpages/PythonQtJob.h b/src/libcalamaresui/viewpages/PythonQtJob.h index 2b50c0ded..a73e7eb82 100644 --- a/src/libcalamaresui/viewpages/PythonQtJob.h +++ b/src/libcalamaresui/viewpages/PythonQtJob.h @@ -32,12 +32,11 @@ class PythonQtJobResult : public QObject, public Calamares::JobResult { Q_OBJECT public: - explicit PythonQtJobResult( bool ok, - const QString& message, - const QString& details ) + explicit PythonQtJobResult( bool ok, const QString& message, const QString& details ) : QObject( nullptr ) , Calamares::JobResult( message, details, ok ? 0 : Calamares::JobResult::GenericError ) - {} + { + } }; @@ -53,13 +52,11 @@ public: Calamares::JobResult exec() override; private: - explicit PythonQtJob( PythonQtObjectPtr cxt, - PythonQtObjectPtr pyJob, - QObject* parent = nullptr ); - friend class Calamares::PythonQtViewStep; // only this one can call the ctor + explicit PythonQtJob( PythonQtObjectPtr cxt, PythonQtObjectPtr pyJob, QObject* parent = nullptr ); + friend class Calamares::PythonQtViewStep; // only this one can call the ctor PythonQtObjectPtr m_cxt; PythonQtObjectPtr m_pyJob; }; -#endif // PYTHONQTJOB_H +#endif // PYTHONQTJOB_H diff --git a/src/libcalamaresui/viewpages/PythonQtUtilsWrapper.cpp b/src/libcalamaresui/viewpages/PythonQtUtilsWrapper.cpp index 69027d018..c13e063bd 100644 --- a/src/libcalamaresui/viewpages/PythonQtUtilsWrapper.cpp +++ b/src/libcalamaresui/viewpages/PythonQtUtilsWrapper.cpp @@ -25,7 +25,7 @@ #include -Utils::Utils(QObject* parent) +Utils::Utils( QObject* parent ) : QObject( parent ) , m_exceptionCxt( PythonQt::self()->createUniqueModule() ) { @@ -34,7 +34,7 @@ Utils::Utils(QObject* parent) void -Utils::debug(const QString& s) const +Utils::debug( const QString& s ) const { cDebug() << "PythonQt DBG>" << s; } @@ -46,35 +46,28 @@ Utils::mount( const QString& device_path, const QString& filesystem_name, const QString& options ) const { - return CalamaresUtils::System::instance()-> - mount( device_path, mount_point, filesystem_name, options ); + return CalamaresUtils::System::instance()->mount( device_path, mount_point, filesystem_name, options ); } int -Utils::target_env_call( const QString& command, - const QString& stdin, - int timeout ) const +Utils::target_env_call( const QString& command, const QString& stdin, int timeout ) const { - return CalamaresUtils::System::instance()-> - targetEnvCall( command, QString(), stdin, std::chrono::seconds( timeout > 0 ? timeout : 0 ) ); + return CalamaresUtils::System::instance()->targetEnvCall( + command, QString(), stdin, std::chrono::seconds( timeout > 0 ? timeout : 0 ) ); } int -Utils::target_env_call( const QStringList& args, - const QString& stdin, - int timeout ) const +Utils::target_env_call( const QStringList& args, const QString& stdin, int timeout ) const { - return CalamaresUtils::System::instance()-> - targetEnvCall( args, QString(), stdin, std::chrono::seconds( timeout > 0 ? timeout : 0 ) ); + return CalamaresUtils::System::instance()->targetEnvCall( + args, QString(), stdin, std::chrono::seconds( timeout > 0 ? timeout : 0 ) ); } int -Utils::check_target_env_call( const QString& command, - const QString& stdin, - int timeout ) const +Utils::check_target_env_call( const QString& command, const QString& stdin, int timeout ) const { int ec = target_env_call( command, stdin, timeout ); return _handle_check_target_env_call_error( ec, command ); @@ -82,9 +75,7 @@ Utils::check_target_env_call( const QString& command, int -Utils::check_target_env_call( const QStringList& args, - const QString& stdin, - int timeout) const +Utils::check_target_env_call( const QStringList& args, const QString& stdin, int timeout ) const { int ec = target_env_call( args, stdin, timeout ); return _handle_check_target_env_call_error( ec, args.join( ' ' ) ); @@ -92,34 +83,22 @@ Utils::check_target_env_call( const QStringList& args, QString -Utils::check_target_env_output( const QString& command, - const QString& stdin, - int timeout ) const +Utils::check_target_env_output( const QString& command, const QString& stdin, int timeout ) const { QString output; - int ec = CalamaresUtils::System::instance()-> - targetEnvOutput( command, - output, - QString(), - stdin, - std::chrono::seconds( timeout > 0 ? timeout : 0 ) ); + int ec = CalamaresUtils::System::instance()->targetEnvOutput( + command, output, QString(), stdin, std::chrono::seconds( timeout > 0 ? timeout : 0 ) ); _handle_check_target_env_call_error( ec, command ); return output; } QString -Utils::check_target_env_output( const QStringList& args, - const QString& stdin, - int timeout ) const +Utils::check_target_env_output( const QStringList& args, const QString& stdin, int timeout ) const { QString output; - int ec = CalamaresUtils::System::instance()-> - targetEnvOutput( args, - output, - QString(), - stdin, - std::chrono::seconds( timeout > 0 ? timeout : 0 ) ); + int ec = CalamaresUtils::System::instance()->targetEnvOutput( + args, output, QString(), stdin, std::chrono::seconds( timeout > 0 ? timeout : 0 ) ); _handle_check_target_env_call_error( ec, args.join( ' ' ) ); return output; } @@ -133,13 +112,11 @@ Utils::obscure( const QString& string ) const int -Utils::_handle_check_target_env_call_error( int ec, const QString& cmd) const +Utils::_handle_check_target_env_call_error( int ec, const QString& cmd ) const { if ( ec ) { - QString raise = QString( "raise subprocess.CalledProcessError(%1,\"%2\")" ) - .arg( ec ) - .arg( cmd ); + QString raise = QString( "raise subprocess.CalledProcessError(%1,\"%2\")" ).arg( ec ).arg( cmd ); PythonQt::self()->evalScript( m_exceptionCxt, raise ); } return ec; diff --git a/src/libcalamaresui/viewpages/PythonQtUtilsWrapper.h b/src/libcalamaresui/viewpages/PythonQtUtilsWrapper.h index ea6955337..19b8b623d 100644 --- a/src/libcalamaresui/viewpages/PythonQtUtilsWrapper.h +++ b/src/libcalamaresui/viewpages/PythonQtUtilsWrapper.h @@ -43,29 +43,17 @@ public slots: const QString& filesystem_name, const QString& options ) const; - int target_env_call( const QString& command, - const QString& stdin = QString(), - int timeout = 0 ) const; + int target_env_call( const QString& command, const QString& stdin = QString(), int timeout = 0 ) const; - int target_env_call( const QStringList& args, - const QString& stdin = QString(), - int timeout = 0 ) const; + int target_env_call( const QStringList& args, const QString& stdin = QString(), int timeout = 0 ) const; - int check_target_env_call( const QString& command, - const QString& stdin = QString(), - int timeout = 0 ) const; + int check_target_env_call( const QString& command, const QString& stdin = QString(), int timeout = 0 ) const; - int check_target_env_call( const QStringList& args, - const QString& stdin = QString(), - int timeout = 0 ) const; + int check_target_env_call( const QStringList& args, const QString& stdin = QString(), int timeout = 0 ) const; - QString check_target_env_output( const QString& command, - const QString& stdin = QString(), - int timeout = 0 ) const; + QString check_target_env_output( const QString& command, const QString& stdin = QString(), int timeout = 0 ) const; - QString check_target_env_output( const QStringList& args, - const QString& stdin = QString(), - int timeout = 0 ) const; + QString check_target_env_output( const QStringList& args, const QString& stdin = QString(), int timeout = 0 ) const; QString obscure( const QString& string ) const; @@ -75,4 +63,4 @@ private: PythonQtObjectPtr m_exceptionCxt; }; -#endif // PYTHONQTUTILSWRAPPER_H +#endif // PYTHONQTUTILSWRAPPER_H diff --git a/src/libcalamaresui/viewpages/PythonQtViewStep.cpp b/src/libcalamaresui/viewpages/PythonQtViewStep.cpp index 2d128d1af..5e313ff98 100644 --- a/src/libcalamaresui/viewpages/PythonQtViewStep.cpp +++ b/src/libcalamaresui/viewpages/PythonQtViewStep.cpp @@ -18,8 +18,8 @@ */ #include "PythonQtViewStep.h" -#include "utils/Logger.h" #include "utils/CalamaresUtilsGui.h" +#include "utils/Logger.h" #include "utils/PythonQtUtils.h" #include "utils/Retranslator.h" #include "viewpages/PythonQtJob.h" @@ -33,8 +33,7 @@ namespace Calamares { -PythonQtViewStep::PythonQtViewStep( PythonQtObjectPtr cxt, - QObject* parent ) +PythonQtViewStep::PythonQtViewStep( PythonQtObjectPtr cxt, QObject* parent ) : ViewStep( parent ) , m_widget( new QWidget() ) , m_cxt( cxt ) @@ -48,32 +47,26 @@ PythonQtViewStep::PythonQtViewStep( PythonQtObjectPtr cxt, // Instantiate an object of the class marked with @calamares_module and // store it as _calamares_module. - pq->evalScript( m_cxt, QString( "_calamares_module = %1()" ) - .arg( className ) ); + pq->evalScript( m_cxt, QString( "_calamares_module = %1()" ).arg( className ) ); m_obj = pq->lookupObject( m_cxt, "_calamares_module" ); - Q_ASSERT( !m_obj.isNull() ); // no entry point, no party + Q_ASSERT( !m_obj.isNull() ); // no entry point, no party // Prepare the base widget for the module's pages m_widget->setLayout( new QVBoxLayout ); CalamaresUtils::unmarginLayout( m_widget->layout() ); m_cxt.addObject( "_calamares_module_basewidget", m_widget ); - CALAMARES_RETRANSLATE_WIDGET( m_widget, - CalamaresUtils::lookupAndCall( m_obj, - { "retranslate" }, - { CalamaresUtils::translatorLocaleName() } ); - ) + CALAMARES_RETRANSLATE_WIDGET( + m_widget, + CalamaresUtils::lookupAndCall( m_obj, { "retranslate" }, { CalamaresUtils::translatorLocaleName() } ); ) } QString PythonQtViewStep::prettyName() const { - return CalamaresUtils::lookupAndCall( m_obj, - { "prettyName", - "prettyname", - "pretty_name" } ).toString(); + return CalamaresUtils::lookupAndCall( m_obj, { "prettyName", "prettyname", "pretty_name" } ).toString(); } @@ -82,12 +75,14 @@ PythonQtViewStep::widget() { if ( m_widget->layout()->count() > 1 ) cWarning() << "PythonQtViewStep wrapper widget has more than 1 child. " - "This should never happen."; + "This should never happen."; - bool nothingChanged = m_cxt.evalScript( - "_calamares_module.widget() in _calamares_module_basewidget.children()" ).toBool(); + bool nothingChanged + = m_cxt.evalScript( "_calamares_module.widget() in _calamares_module_basewidget.children()" ).toBool(); if ( nothingChanged ) + { return m_widget; + } // Else, we either don't have a child widget, or we have a child widget that // was previously set and doesn't apply any more since the Python module @@ -97,10 +92,11 @@ PythonQtViewStep::widget() // We only remove from the layout and not delete because Python is in charge // of memory management for these widgets. while ( m_widget->layout()->itemAt( 0 ) ) + { m_widget->layout()->takeAt( 0 ); + } - m_cxt.evalScript( - "_calamares_module_basewidget.layout().addWidget(_calamares_module.widget())" ); + m_cxt.evalScript( "_calamares_module_basewidget.layout().addWidget(_calamares_module.widget())" ); return m_widget; } @@ -123,58 +119,40 @@ PythonQtViewStep::back() bool PythonQtViewStep::isNextEnabled() const { - return CalamaresUtils::lookupAndCall( m_obj, - { "isNextEnabled", - "isnextenabled", - "is_next_enabled" } ).toBool(); + return CalamaresUtils::lookupAndCall( m_obj, { "isNextEnabled", "isnextenabled", "is_next_enabled" } ).toBool(); } bool PythonQtViewStep::isBackEnabled() const { - return CalamaresUtils::lookupAndCall( m_obj, - { "isBackEnabled", - "isbackenabled", - "is_back_enabled" } ).toBool(); + return CalamaresUtils::lookupAndCall( m_obj, { "isBackEnabled", "isbackenabled", "is_back_enabled" } ).toBool(); } bool PythonQtViewStep::isAtBeginning() const { - return CalamaresUtils::lookupAndCall( m_obj, - { "isAtBeginning", - "isatbeginning", - "is_at_beginning" } ).toBool(); + return CalamaresUtils::lookupAndCall( m_obj, { "isAtBeginning", "isatbeginning", "is_at_beginning" } ).toBool(); } bool PythonQtViewStep::isAtEnd() const { - return CalamaresUtils::lookupAndCall( m_obj, - { "isAtEnd", - "isatend", - "is_at_end" } ).toBool(); + return CalamaresUtils::lookupAndCall( m_obj, { "isAtEnd", "isatend", "is_at_end" } ).toBool(); } void -PythonQtViewStep::onActivate() +PythonQtViewStep::onActivate() { - CalamaresUtils::lookupAndCall( m_obj, - { "onActivate", - "onactivate", - "on_activate" }); + CalamaresUtils::lookupAndCall( m_obj, { "onActivate", "onactivate", "on_activate" } ); } void PythonQtViewStep::onLeave() { - CalamaresUtils::lookupAndCall( m_obj, - { "onLeave", - "onleave", - "on_leave" }); + CalamaresUtils::lookupAndCall( m_obj, { "onLeave", "onleave", "on_leave" } ); } @@ -185,21 +163,29 @@ PythonQtViewStep::jobs() const PythonQtObjectPtr jobsCallable = PythonQt::self()->lookupCallable( m_obj, "jobs" ); if ( jobsCallable.isNull() ) + { return jobs; + } PythonQtObjectPtr response = PythonQt::self()->callAndReturnPyObject( jobsCallable ); if ( response.isNull() ) + { return jobs; + } PythonQtObjectPtr listPopCallable = PythonQt::self()->lookupCallable( response, "pop" ); if ( listPopCallable.isNull() ) + { return jobs; + } forever { PythonQtObjectPtr aJob = PythonQt::self()->callAndReturnPyObject( listPopCallable, { 0 } ); if ( aJob.isNull() ) + { break; + } jobs.append( Calamares::job_ptr( new PythonQtJob( m_cxt, aJob ) ) ); } @@ -219,9 +205,8 @@ QWidget* PythonQtViewStep::createScriptingConsole() { PythonQtScriptingConsole* console = new PythonQtScriptingConsole( nullptr, m_cxt ); - console->setProperty( "classname", - m_cxt.getVariable( "_calamares_module_typename" ).toString() ); + console->setProperty( "classname", m_cxt.getVariable( "_calamares_module_typename" ).toString() ); return console; } -} +} // namespace Calamares diff --git a/src/libcalamaresui/viewpages/PythonQtViewStep.h b/src/libcalamaresui/viewpages/PythonQtViewStep.h index b6b7c193b..5358bc824 100644 --- a/src/libcalamaresui/viewpages/PythonQtViewStep.h +++ b/src/libcalamaresui/viewpages/PythonQtViewStep.h @@ -30,8 +30,7 @@ class PythonQtViewStep : public Calamares::ViewStep { Q_OBJECT public: - PythonQtViewStep( PythonQtObjectPtr cxt, - QObject* parent = nullptr ); + PythonQtViewStep( PythonQtObjectPtr cxt, QObject* parent = nullptr ); QString prettyName() const override; @@ -62,6 +61,6 @@ private: PythonQtObjectPtr m_obj; }; -} +} // namespace Calamares -#endif // PYTHONQTVIEWSTEP_H +#endif // PYTHONQTVIEWSTEP_H diff --git a/src/libcalamaresui/viewpages/ViewStep.cpp b/src/libcalamaresui/viewpages/ViewStep.cpp index cdfc7bbc9..af1e347eb 100644 --- a/src/libcalamaresui/viewpages/ViewStep.cpp +++ b/src/libcalamaresui/viewpages/ViewStep.cpp @@ -24,11 +24,11 @@ namespace Calamares ViewStep::ViewStep( QObject* parent ) : QObject( parent ) -{} +{ +} -ViewStep::~ViewStep() -{} +ViewStep::~ViewStep() {} QString @@ -45,20 +45,24 @@ ViewStep::createSummaryWidget() const void ViewStep::onActivate() -{} +{ +} void ViewStep::onLeave() -{} +{ +} void ViewStep::next() -{} +{ +} void ViewStep::back() -{} +{ +} void @@ -69,10 +73,7 @@ ViewStep::setModuleInstanceKey( const QString& instanceKey ) void -ViewStep::setConfigurationMap( const QVariantMap& configurationMap ) -{ - Q_UNUSED( configurationMap ) -} +ViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { Q_UNUSED( configurationMap ) } RequirementsList ViewStep::checkRequirements() @@ -80,4 +81,4 @@ RequirementsList ViewStep::checkRequirements() return RequirementsList(); } -} +} // namespace Calamares diff --git a/src/libcalamaresui/viewpages/ViewStep.h b/src/libcalamaresui/viewpages/ViewStep.h index e3d5a021e..8c5020f83 100644 --- a/src/libcalamaresui/viewpages/ViewStep.h +++ b/src/libcalamaresui/viewpages/ViewStep.h @@ -130,10 +130,7 @@ public: virtual JobList jobs() const = 0; void setModuleInstanceKey( const QString& instanceKey ); - QString moduleInstanceKey() const - { - return m_instanceKey; - } + QString moduleInstanceKey() const { return m_instanceKey; } virtual void setConfigurationMap( const QVariantMap& configurationMap ); @@ -161,6 +158,6 @@ protected: }; using ViewStepList = QList< ViewStep* >; -} +} // namespace Calamares -#endif // VIEWSTEP_H +#endif // VIEWSTEP_H From e7dedbbfe0363aa0ff0256d48d30c66bc960cf10 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 13 Aug 2019 21:07:46 +0200 Subject: [PATCH 209/302] [libcalamaresui] Apply coding style to remainder --- src/libcalamaresui/Branding.cpp | 8 +++++ src/libcalamaresui/Branding.h | 43 ++++++++++++++++-------- src/libcalamaresui/ExecutionViewStep.cpp | 24 +++++++------ src/libcalamaresui/ExecutionViewStep.h | 2 +- src/libcalamaresui/UiDllMacro.h | 10 +++--- 5 files changed, 56 insertions(+), 31 deletions(-) diff --git a/src/libcalamaresui/Branding.cpp b/src/libcalamaresui/Branding.cpp index d3b0de97d..98dbab06c 100644 --- a/src/libcalamaresui/Branding.cpp +++ b/src/libcalamaresui/Branding.cpp @@ -52,6 +52,8 @@ Branding::instance() } +// *INDENT-OFF* +// clang-format off const QStringList Branding::s_stringEntryStrings = { "productName", @@ -82,15 +84,21 @@ const QStringList Branding::s_styleEntryStrings = "sidebarTextSelect", "sidebarTextHighlight" }; +// clang-format on +// *INDENT-ON* const NamedEnumTable& Branding::WindowDimension::suffixes() { using Unit = Branding::WindowDimensionUnit; + // *INDENT-OFF* + // clang-format off static const NamedEnumTable names{ {"px", Unit::Pixies}, {"em", Unit::Fonties} }; + // clang-format on + // *INDENT-ON* return names; } diff --git a/src/libcalamaresui/Branding.h b/src/libcalamaresui/Branding.h index a3909bc00..3723fd07f 100644 --- a/src/libcalamaresui/Branding.h +++ b/src/libcalamaresui/Branding.h @@ -25,13 +25,13 @@ #include "utils/NamedSuffix.h" +#include #include #include -#include namespace YAML { - class Node; +class Node; } namespace Calamares @@ -79,27 +79,39 @@ public: }; /** @brief Setting for how much the main window may expand. */ - enum class WindowExpansion { Normal, Fullscreen, Fixed } ; + enum class WindowExpansion + { + Normal, + Fullscreen, + Fixed + }; /** @brief Setting for the main window size. * * The units are pixels (Pixies) or something-based-on-fontsize (Fonties), which * we suffix as "em", e.g. "600px" or "32em". */ - enum class WindowDimensionUnit { None, Pixies, Fonties }; - class WindowDimension : public NamedSuffix + enum class WindowDimensionUnit + { + None, + Pixies, + Fonties + }; + class WindowDimension : public NamedSuffix< WindowDimensionUnit, WindowDimensionUnit::None > { public: - static const NamedEnumTable< WindowDimensionUnit >& suffixes(); + static const NamedEnumTable< WindowDimensionUnit >& suffixes(); bool isValid() const; using NamedSuffix::NamedSuffix; - WindowDimension( const QString& s ) : NamedSuffix( suffixes(), s ) {} - } ; + WindowDimension( const QString& s ) + : NamedSuffix( suffixes(), s ) + { + } + }; static Branding* instance(); - explicit Branding( const QString& brandingFilePath, - QObject* parent = nullptr ); + explicit Branding( const QString& brandingFilePath, QObject* parent = nullptr ); /** @brief Complete path of the branding descriptor file. */ QString descriptorPath() const { return m_descriptorPath; } @@ -184,11 +196,14 @@ private: WindowExpansion m_windowExpansion; WindowDimension m_windowHeight, m_windowWidth; - }; -template inline QString operator*(U e) { return Branding::instance()->string( e ); } - +template < typename U > +inline QString operator*( U e ) +{ + return Branding::instance()->string( e ); } -#endif // BRANDING_H +} // namespace Calamares + +#endif // BRANDING_H diff --git a/src/libcalamaresui/ExecutionViewStep.cpp b/src/libcalamaresui/ExecutionViewStep.cpp index e242622a0..4dd10bd93 100644 --- a/src/libcalamaresui/ExecutionViewStep.cpp +++ b/src/libcalamaresui/ExecutionViewStep.cpp @@ -23,10 +23,10 @@ #include "Branding.h" #include "Job.h" #include "JobQueue.h" -#include "modulesystem/Module.h" -#include "modulesystem/ModuleManager.h" #include "Settings.h" #include "ViewManager.h" +#include "modulesystem/Module.h" +#include "modulesystem/ModuleManager.h" #include "utils/CalamaresUtilsGui.h" #include "utils/Dirs.h" @@ -56,7 +56,7 @@ callQMLFunction( QQuickItem* qmlObject, const char* method ) QByteArray methodSignature( method ); methodSignature.append( "()" ); - if ( qmlObject && qmlObject->metaObject()->indexOfMethod( methodSignature ) >= 0 ) + if ( qmlObject && qmlObject->metaObject()->indexOfMethod( methodSignature ) >= 0 ) { QVariant returnValue; QMetaObject::invokeMethod( qmlObject, method, Q_RETURN_ARG( QVariant, returnValue ) ); @@ -117,9 +117,7 @@ ExecutionViewStep::ExecutionViewStep( QObject* parent ) QString ExecutionViewStep::prettyName() const { - return Calamares::Settings::instance()->isSetupMode() - ? tr( "Set up" ) - : tr( "Install" ); + return Calamares::Settings::instance()->isSetupMode() ? tr( "Set up" ) : tr( "Install" ); } @@ -176,8 +174,7 @@ ExecutionViewStep::loadQmlV2() { m_qmlComponent = new QQmlComponent( m_qmlShow->engine(), QUrl::fromLocalFile( Calamares::Branding::instance()->slideshowPath() ), - QQmlComponent::CompilationMode::Asynchronous - ); + QQmlComponent::CompilationMode::Asynchronous ); connect( m_qmlComponent, &QQmlComponent::statusChanged, this, &ExecutionViewStep::loadQmlV2Complete ); } } @@ -194,14 +191,17 @@ ExecutionViewStep::loadQmlV2Complete() QObject* o = m_qmlComponent->create(); m_qmlObject = qobject_cast< QQuickItem* >( o ); if ( !m_qmlObject ) + { delete o; + } else { // setContent() is public API, but not documented publicly. // It is marked \internal in the Qt sources, but does exactly // what is needed: sets up visual parent by replacing the root // item, and handling resizes. - m_qmlShow->setContent( QUrl::fromLocalFile( Calamares::Branding::instance()->slideshowPath() ), m_qmlComponent, m_qmlObject ); + m_qmlShow->setContent( + QUrl::fromLocalFile( Calamares::Branding::instance()->slideshowPath() ), m_qmlComponent, m_qmlObject ); if ( ViewManager::instance()->currentStep() == this ) { // We're alreay visible! Must have been slow QML loading, and we @@ -235,8 +235,10 @@ ExecutionViewStep::onActivate() auto jl = module->jobs(); if ( module->isEmergency() ) { - for( auto& j : jl ) + for ( auto& j : jl ) + { j->setEmergency( true ); + } } queue->enqueue( jl ); } @@ -279,4 +281,4 @@ ExecutionViewStep::onLeave() } } -} // namespace +} // namespace Calamares diff --git a/src/libcalamaresui/ExecutionViewStep.h b/src/libcalamaresui/ExecutionViewStep.h index 63594b151..8c4174cdb 100644 --- a/src/libcalamaresui/ExecutionViewStep.h +++ b/src/libcalamaresui/ExecutionViewStep.h @@ -77,6 +77,6 @@ private: void updateFromJobQueue( qreal percent, const QString& message ); }; -} +} // namespace Calamares #endif /* EXECUTIONVIEWSTEP_H */ diff --git a/src/libcalamaresui/UiDllMacro.h b/src/libcalamaresui/UiDllMacro.h index 35ad67453..3064ca68c 100644 --- a/src/libcalamaresui/UiDllMacro.h +++ b/src/libcalamaresui/UiDllMacro.h @@ -22,11 +22,11 @@ #include #ifndef UIDLLEXPORT -# if defined (UIDLLEXPORT_PRO) -# define UIDLLEXPORT Q_DECL_EXPORT -# else -# define UIDLLEXPORT Q_DECL_IMPORT -# endif +#if defined( UIDLLEXPORT_PRO ) +#define UIDLLEXPORT Q_DECL_EXPORT +#else +#define UIDLLEXPORT Q_DECL_IMPORT +#endif #endif #endif From 6b8c0129fdb2a6f3f9a82ea6b45d57b78292a5d3 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 13 Aug 2019 22:24:30 +0200 Subject: [PATCH 210/302] [libcalamaresui] Add one more icon (donate) from Breeze - LGPLv3 like the others --- data/images/help-donate.svg | 18 ++++++++++++++++++ src/libcalamaresui/libcalamaresui.qrc | 1 + src/libcalamaresui/utils/CalamaresUtilsGui.cpp | 4 ++++ src/libcalamaresui/utils/CalamaresUtilsGui.h | 1 + 4 files changed, 24 insertions(+) create mode 100644 data/images/help-donate.svg diff --git a/data/images/help-donate.svg b/data/images/help-donate.svg new file mode 100644 index 000000000..2370c127e --- /dev/null +++ b/data/images/help-donate.svg @@ -0,0 +1,18 @@ + + + + + + diff --git a/src/libcalamaresui/libcalamaresui.qrc b/src/libcalamaresui/libcalamaresui.qrc index 79ae4e45f..eeb3fc490 100644 --- a/src/libcalamaresui/libcalamaresui.qrc +++ b/src/libcalamaresui/libcalamaresui.qrc @@ -7,6 +7,7 @@ ../../data/images/bugs.svg ../../data/images/help.svg ../../data/images/release.svg + ../../data/images/help-donate.svg ../../data/images/partition-disk.svg ../../data/images/partition-partition.svg ../../data/images/partition-alongside.svg diff --git a/src/libcalamaresui/utils/CalamaresUtilsGui.cpp b/src/libcalamaresui/utils/CalamaresUtilsGui.cpp index b6c927763..bd15d7a68 100644 --- a/src/libcalamaresui/utils/CalamaresUtilsGui.cpp +++ b/src/libcalamaresui/utils/CalamaresUtilsGui.cpp @@ -74,6 +74,10 @@ defaultPixmap( ImageType type, ImageMode mode, const QSize& size ) pixmap = ImageRegistry::instance()->pixmap( RESPATH "images/release.svg", size ); break; + case Donate: + pixmap = ImageRegistry::instance()->pixmap( RESPATH "images/donate.svg", size ); + break; + case PartitionDisk: pixmap = ImageRegistry::instance()->pixmap( RESPATH "images/partition-disk.svg", size ); break; diff --git a/src/libcalamaresui/utils/CalamaresUtilsGui.h b/src/libcalamaresui/utils/CalamaresUtilsGui.h index 012795e34..0c10dcc30 100644 --- a/src/libcalamaresui/utils/CalamaresUtilsGui.h +++ b/src/libcalamaresui/utils/CalamaresUtilsGui.h @@ -47,6 +47,7 @@ enum ImageType : int Bugs, Help, Release, + Donate, PartitionDisk, PartitionPartition, PartitionAlongside, From b60ec123a0937e2a65d855ec1447534a5ab42890 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 13 Aug 2019 21:21:19 +0200 Subject: [PATCH 211/302] [branding] [welcome] Document interrelationship of settings --- src/branding/default/branding.desc | 5 ++++- src/modules/welcome/welcome.conf | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/branding/default/branding.desc b/src/branding/default/branding.desc index 1bd76cd29..3d1079a8c 100644 --- a/src/branding/default/branding.desc +++ b/src/branding/default/branding.desc @@ -56,6 +56,9 @@ windowSize: 800px,520px # Note that ANSI_COLOR and CPE_NAME don't make sense here, and # are not supported (the rest are). Remember to quote the string # if it contains substitutions, or you'll get YAML exceptions. +# +# The *Url* entries are used on the welcome page, and they +# are visible as buttons there if the corresponding *show* keys are set. strings: productName: "@{NAME}" shortProductName: Generic @@ -84,7 +87,7 @@ strings: # the window. Use `welcomeExpandingLogo` to make it non-scaled. # Recommended size is 320x150. # -# These strings can also use substitutions from os-release (see above). +# These filenames can also use substitutions from os-release (see above). images: productLogo: "squid.png" productIcon: "squid.png" diff --git a/src/modules/welcome/welcome.conf b/src/modules/welcome/welcome.conf index a89b63854..a430345a2 100644 --- a/src/modules/welcome/welcome.conf +++ b/src/modules/welcome/welcome.conf @@ -7,6 +7,7 @@ # can check requirements for installation. --- # Display settings for various buttons on the welcome page. +# The URLs themselves come from branding.desc showSupportUrl: true showKnownIssuesUrl: true showReleaseNotesUrl: true From 03e506a826dd2c72386babdae3e22171952f25d3 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 13 Aug 2019 22:29:01 +0200 Subject: [PATCH 212/302] [welcome] Add a donate button FIXES #1197 --- src/modules/welcome/WelcomePage.cpp | 187 ++++++++++++++---------- src/modules/welcome/WelcomePage.h | 16 +- src/modules/welcome/WelcomePage.ui | 10 ++ src/modules/welcome/WelcomeViewStep.cpp | 41 ++++-- src/modules/welcome/welcome.conf | 7 + 5 files changed, 160 insertions(+), 101 deletions(-) diff --git a/src/modules/welcome/WelcomePage.cpp b/src/modules/welcome/WelcomePage.cpp index b29b2e23e..6d0fc0d98 100644 --- a/src/modules/welcome/WelcomePage.cpp +++ b/src/modules/welcome/WelcomePage.cpp @@ -20,8 +20,8 @@ #include "WelcomePage.h" -#include "ui_WelcomePage.h" #include "checker/CheckerContainer.h" +#include "ui_WelcomePage.h" #include "Branding.h" #include "CalamaresVersion.h" @@ -48,9 +48,18 @@ WelcomePage::WelcomePage( QWidget* parent ) , m_checkingWidget( new CheckerContainer( this ) ) , m_languages( nullptr ) { - connect( Calamares::ModuleManager::instance(), &Calamares::ModuleManager::requirementsResult, m_checkingWidget, &CheckerContainer::requirementsChecked ); - connect( Calamares::ModuleManager::instance(), &Calamares::ModuleManager::requirementsComplete, m_checkingWidget, &CheckerContainer::requirementsComplete ); - connect( Calamares::ModuleManager::instance(), &Calamares::ModuleManager::requirementsProgress, m_checkingWidget, &CheckerContainer::requirementsProgress ); + connect( Calamares::ModuleManager::instance(), + &Calamares::ModuleManager::requirementsResult, + m_checkingWidget, + &CheckerContainer::requirementsChecked ); + connect( Calamares::ModuleManager::instance(), + &Calamares::ModuleManager::requirementsComplete, + m_checkingWidget, + &CheckerContainer::requirementsComplete ); + connect( Calamares::ModuleManager::instance(), + &Calamares::ModuleManager::requirementsProgress, + m_checkingWidget, + &CheckerContainer::requirementsProgress ); ui->setupUi( this ); ui->verticalLayout->insertSpacing( 1, CalamaresUtils::defaultFontHeight() * 2 ); @@ -61,38 +70,31 @@ WelcomePage::WelcomePage( QWidget* parent ) ui->mainText->setOpenExternalLinks( true ); cDebug() << "Welcome string" << Calamares::Branding::instance()->welcomeStyleCalamares() - << *Calamares::Branding::VersionedName; + << *Calamares::Branding::VersionedName; - CALAMARES_RETRANSLATE( - QString message; + CALAMARES_RETRANSLATE( QString message; - if ( Calamares::Settings::instance()->isSetupMode() ) - message = Calamares::Branding::instance()->welcomeStyleCalamares() - ? 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.

" ); + if ( Calamares::Settings::instance()->isSetupMode() ) message + = Calamares::Branding::instance()->welcomeStyleCalamares() + ? 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.

" ); - ui->mainText->setText( message.arg( *Calamares::Branding::VersionedName ) ); - ui->retranslateUi( this ); - ) + ui->mainText->setText( message.arg( *Calamares::Branding::VersionedName ) ); + ui->retranslateUi( this ); ) - ui->aboutButton->setIcon( CalamaresUtils::defaultPixmap( CalamaresUtils::Information, - CalamaresUtils::Original, - 2*QSize( CalamaresUtils::defaultFontHeight(), - CalamaresUtils::defaultFontHeight() ) ) ); - connect( ui->aboutButton, &QPushButton::clicked, - this, [ this ] - { - QString title = Calamares::Settings::instance()->isSetupMode() - ? tr( "About %1 setup" ) - : tr( "About %1 installer" ); + ui->aboutButton->setIcon( CalamaresUtils::defaultPixmap( + CalamaresUtils::Information, + CalamaresUtils::Original, + 2 * QSize( CalamaresUtils::defaultFontHeight(), CalamaresUtils::defaultFontHeight() ) ) ); + connect( ui->aboutButton, &QPushButton::clicked, this, [this] { + QString title + = Calamares::Settings::instance()->isSetupMode() ? tr( "About %1 setup" ) : tr( "About %1 installer" ); QMessageBox mb( QMessageBox::Information, title.arg( CALAMARES_APPLICATION_NAME ), - tr( - "

%1


" + tr( "

%1


" "%2
" "for %3


" "Copyright 2014-2017 Teo Mrnjavac <teo@kde.org>
" @@ -103,24 +105,23 @@ WelcomePage::WelcomePage( QWidget* parent ) "Calamares " "development is sponsored by
" "Blue Systems - " - "Liberating Software." - ) - .arg( CALAMARES_APPLICATION_NAME ) - .arg( CALAMARES_VERSION ) - .arg( *Calamares::Branding::VersionedName ), + "Liberating Software." ) + .arg( CALAMARES_APPLICATION_NAME ) + .arg( CALAMARES_VERSION ) + .arg( *Calamares::Branding::VersionedName ), QMessageBox::Ok, this ); - mb.setIconPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::Squid, - CalamaresUtils::Original, - QSize( CalamaresUtils::defaultFontHeight() * 6, - CalamaresUtils::defaultFontHeight() * 6 ) ) ); - QGridLayout* layout = reinterpret_cast( mb.layout() ); + mb.setIconPixmap( CalamaresUtils::defaultPixmap( + CalamaresUtils::Squid, + CalamaresUtils::Original, + QSize( CalamaresUtils::defaultFontHeight() * 6, CalamaresUtils::defaultFontHeight() * 6 ) ) ); + QGridLayout* layout = reinterpret_cast< QGridLayout* >( mb.layout() ); if ( layout ) layout->setColumnMinimumWidth( 2, CalamaresUtils::defaultFontHeight() * 24 ); mb.exec(); } ); - ui->verticalLayout->insertWidget( 3, m_checkingWidget); + ui->verticalLayout->insertWidget( 3, m_checkingWidget ); } @@ -139,15 +140,16 @@ WelcomePage::initLanguages() QLocale defaultLocale = QLocale( QLocale::system().name() ); cDebug() << "Matching locale" << defaultLocale; - int matchedLocaleIndex = m_languages->find( - [&](const QLocale& x){ return x.language() == defaultLocale.language() && x.country() == defaultLocale.country(); } ); + int matchedLocaleIndex = m_languages->find( [&]( const QLocale& x ) { + return x.language() == defaultLocale.language() && x.country() == defaultLocale.country(); + } ); if ( matchedLocaleIndex < 0 ) { cDebug() << Logger::SubEntry << "Matching approximate locale" << defaultLocale.language(); - matchedLocaleIndex = m_languages->find( - [&](const QLocale& x){ return x.language() == defaultLocale.language(); } ); + matchedLocaleIndex + = m_languages->find( [&]( const QLocale& x ) { return x.language() == defaultLocale.language(); } ); } if ( matchedLocaleIndex < 0 ) @@ -159,7 +161,9 @@ WelcomePage::initLanguages() // Now, if it matched, because we didn't match the system locale, switch to the one found if ( matchedLocaleIndex >= 0 ) + { QLocale::setDefault( m_languages->locale( matchedLocaleIndex ).locale() ); + } } if ( matchedLocaleIndex >= 0 ) @@ -171,44 +175,36 @@ WelcomePage::initLanguages() ui->languageWidget->setCurrentIndex( matchedLocaleIndex ); } else + { cWarning() << "No available translation matched" << defaultLocale; + } connect( ui->languageWidget, static_cast< void ( QComboBox::* )( int ) >( &QComboBox::currentIndexChanged ), this, - [&]( int newIndex ) - { + [&]( int newIndex ) { const auto& selectedLocale = m_languages->locale( newIndex ).locale(); cDebug() << "Selected locale" << selectedLocale; QLocale::setDefault( selectedLocale ); - CalamaresUtils::installTranslator( selectedLocale, - Calamares::Branding::instance()->translationsDirectory(), - qApp ); + CalamaresUtils::installTranslator( + selectedLocale, Calamares::Branding::instance()->translationsDirectory(), qApp ); } ); } void -WelcomePage::setUpLinks( bool showSupportUrl, - bool showKnownIssuesUrl, - bool showReleaseNotesUrl ) +WelcomePage::setUpLinks( bool showSupportUrl, bool showKnownIssuesUrl, bool showReleaseNotesUrl ) { using namespace Calamares; if ( showSupportUrl && !( *Branding::SupportUrl ).isEmpty() ) { - CALAMARES_RETRANSLATE( - ui->supportButton->setText( tr( "%1 support" ) - .arg( *Branding::ShortProductName ) ); - ) - ui->supportButton->setIcon( CalamaresUtils::defaultPixmap( CalamaresUtils::Help, - CalamaresUtils::Original, - 2*QSize( CalamaresUtils::defaultFontHeight(), - CalamaresUtils::defaultFontHeight() ) ) ); - connect( ui->supportButton, &QPushButton::clicked, [] - { - QDesktopServices::openUrl( *Branding::SupportUrl ); - } ); + CALAMARES_RETRANSLATE( ui->supportButton->setText( tr( "%1 support" ).arg( *Branding::ShortProductName ) ); ) + ui->supportButton->setIcon( CalamaresUtils::defaultPixmap( + CalamaresUtils::Help, + CalamaresUtils::Original, + 2 * QSize( CalamaresUtils::defaultFontHeight(), CalamaresUtils::defaultFontHeight() ) ) ); + connect( ui->supportButton, &QPushButton::clicked, [] { QDesktopServices::openUrl( *Branding::SupportUrl ); } ); } else { @@ -217,12 +213,11 @@ WelcomePage::setUpLinks( bool showSupportUrl, if ( showKnownIssuesUrl && !( *Branding::KnownIssuesUrl ).isEmpty() ) { - ui->knownIssuesButton->setIcon( CalamaresUtils::defaultPixmap( CalamaresUtils::Bugs, - CalamaresUtils::Original, - 2*QSize( CalamaresUtils::defaultFontHeight(), - CalamaresUtils::defaultFontHeight() ) ) ); - connect( ui->knownIssuesButton, &QPushButton::clicked, [] - { + ui->knownIssuesButton->setIcon( CalamaresUtils::defaultPixmap( + CalamaresUtils::Bugs, + CalamaresUtils::Original, + 2 * QSize( CalamaresUtils::defaultFontHeight(), CalamaresUtils::defaultFontHeight() ) ) ); + connect( ui->knownIssuesButton, &QPushButton::clicked, [] { QDesktopServices::openUrl( *Branding::KnownIssuesUrl ); } ); } @@ -233,12 +228,11 @@ WelcomePage::setUpLinks( bool showSupportUrl, if ( showReleaseNotesUrl && !( *Branding::ReleaseNotesUrl ).isEmpty() ) { - ui->releaseNotesButton->setIcon( CalamaresUtils::defaultPixmap( CalamaresUtils::Release, - CalamaresUtils::Original, - 2*QSize( CalamaresUtils::defaultFontHeight(), - CalamaresUtils::defaultFontHeight() ) ) ); - connect( ui->releaseNotesButton, &QPushButton::clicked, [] - { + ui->releaseNotesButton->setIcon( CalamaresUtils::defaultPixmap( + CalamaresUtils::Release, + CalamaresUtils::Original, + 2 * QSize( CalamaresUtils::defaultFontHeight(), CalamaresUtils::defaultFontHeight() ) ) ); + connect( ui->releaseNotesButton, &QPushButton::clicked, [] { QDesktopServices::openUrl( *Branding::ReleaseNotesUrl ); } ); } @@ -249,11 +243,38 @@ WelcomePage::setUpLinks( bool showSupportUrl, } +void +WelcomePage::setupDonateButton( const QString& url ) +{ + if ( url.isEmpty() ) + { + ui->donateButton->hide(); + return; + } + + QUrl u( url ); + if ( u.isValid() ) + { + ui->donateButton->setIcon( CalamaresUtils::defaultPixmap( + CalamaresUtils::Donate, + CalamaresUtils::Original, + 2 * QSize( CalamaresUtils::defaultFontHeight(), CalamaresUtils::defaultFontHeight() ) ) ); + connect( ui->donateButton, &QPushButton::clicked, [u]() { QDesktopServices::openUrl( u ); } ); + } + else + { + qWarning() << "Donate URL" << url << "is invalid."; + ui->donateButton->hide(); + } +} + void WelcomePage::focusInEvent( QFocusEvent* e ) { if ( ui->languageWidget ) + { ui->languageWidget->setFocus(); + } e->accept(); } @@ -267,7 +288,9 @@ void WelcomePage::externallySelectedLanguage( int row ) { if ( ( row >= 0 ) && ( row < ui->languageWidget->count() ) ) + { ui->languageWidget->setCurrentIndex( row ); + } } void @@ -278,8 +301,14 @@ WelcomePage::setLanguageIcon( QPixmap i ) void -LocaleTwoColumnDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const +LocaleTwoColumnDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const { QStyledItemDelegate::paint( painter, option, index ); - option.widget->style()->drawItemText( painter, option.rect, Qt::AlignRight | Qt::AlignVCenter, option.palette, false, index.data( CalamaresUtils::Locale::LabelModel::EnglishLabelRole ).toString() ); + option.widget->style()->drawItemText( + painter, + option.rect, + Qt::AlignRight | Qt::AlignVCenter, + option.palette, + false, + index.data( CalamaresUtils::Locale::LabelModel::EnglishLabelRole ).toString() ); } diff --git a/src/modules/welcome/WelcomePage.h b/src/modules/welcome/WelcomePage.h index 6c244bf0c..d8a1bd4f2 100644 --- a/src/modules/welcome/WelcomePage.h +++ b/src/modules/welcome/WelcomePage.h @@ -39,9 +39,10 @@ public: explicit WelcomePage( QWidget* parent = nullptr ); /// @brief Configure the buttons for URLs from the branding configuration - void setUpLinks( bool showSupportUrl, - bool showKnownIssuesUrl, - bool showReleaseNotesUrl ); + void setUpLinks( bool showSupportUrl, bool showKnownIssuesUrl, bool showReleaseNotesUrl ); + /// @brief Configure the "Donate" button + void setupDonateButton( const QString& ); + /// @brief Set international language-selector icon void setLanguageIcon( QPixmap ); @@ -50,8 +51,9 @@ public: /// @brief Change the language from an external source. void externallySelectedLanguage( int row ); + protected: - void focusInEvent( QFocusEvent* e ) override; //choose the child widget to focus + void focusInEvent( QFocusEvent* e ) override; //choose the child widget to focus private: /// @brief Fill the list of languages with the available translations @@ -59,7 +61,7 @@ private: Ui::WelcomePage* ui; CheckerContainer* m_checkingWidget; - CalamaresUtils::Locale::LabelModel *m_languages; + CalamaresUtils::Locale::LabelModel* m_languages; }; /** @brief Delegate to display language information in two columns. @@ -72,6 +74,6 @@ public: using QStyledItemDelegate::QStyledItemDelegate; void paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const override; -} ; +}; -#endif // WELCOMEPAGE_H +#endif // WELCOMEPAGE_H diff --git a/src/modules/welcome/WelcomePage.ui b/src/modules/welcome/WelcomePage.ui index 548bd5d27..0787ac6e7 100644 --- a/src/modules/welcome/WelcomePage.ui +++ b/src/modules/welcome/WelcomePage.ui @@ -134,6 +134,16 @@
+ + + + &Donate + + + true + + + diff --git a/src/modules/welcome/WelcomeViewStep.cpp b/src/modules/welcome/WelcomeViewStep.cpp index 938fe1f45..60dd6f500 100644 --- a/src/modules/welcome/WelcomeViewStep.cpp +++ b/src/modules/welcome/WelcomeViewStep.cpp @@ -33,13 +33,16 @@ #include #include -CALAMARES_PLUGIN_FACTORY_DEFINITION( WelcomeViewStepFactory, registerPlugin(); ) +CALAMARES_PLUGIN_FACTORY_DEFINITION( WelcomeViewStepFactory, registerPlugin< WelcomeViewStep >(); ) WelcomeViewStep::WelcomeViewStep( QObject* parent ) : Calamares::ViewStep( parent ) , m_requirementsChecker( new GeneralRequirements( this ) ) { - connect( Calamares::ModuleManager::instance(), &Calamares::ModuleManager::requirementsComplete, this, &WelcomeViewStep::nextStatusChanged ); + connect( Calamares::ModuleManager::instance(), + &Calamares::ModuleManager::requirementsComplete, + this, + &WelcomeViewStep::nextStatusChanged ); m_widget = new WelcomePage(); } @@ -47,7 +50,9 @@ WelcomeViewStep::WelcomeViewStep( QObject* parent ) WelcomeViewStep::~WelcomeViewStep() { if ( m_widget && m_widget->parent() == nullptr ) + { m_widget->deleteLater(); + } } @@ -107,16 +112,17 @@ WelcomeViewStep::setConfigurationMap( const QVariantMap& configurationMap ) bool showKnownIssuesUrl = CalamaresUtils::getBool( configurationMap, "showKnownIssuesUrl", false ); bool showReleaseNotesUrl = CalamaresUtils::getBool( configurationMap, "showReleaseNotesUrl", false ); - m_widget->setUpLinks( showSupportUrl, - showKnownIssuesUrl, - showReleaseNotesUrl ); + m_widget->setUpLinks( showSupportUrl, showKnownIssuesUrl, showReleaseNotesUrl ); + m_widget->setupDonateButton( CalamaresUtils::getString( configurationMap, "donateUrl" ) ); - if ( configurationMap.contains( "requirements" ) && - configurationMap.value( "requirements" ).type() == QVariant::Map ) + if ( configurationMap.contains( "requirements" ) + && configurationMap.value( "requirements" ).type() == QVariant::Map ) + { m_requirementsChecker->setConfigurationMap( configurationMap.value( "requirements" ).toMap() ); + } else cWarning() << "no valid requirements map found in welcome " - "module configuration."; + "module configuration."; bool ok = false; QVariantMap geoip = CalamaresUtils::getSubMap( configurationMap, "geoip", ok ); @@ -124,15 +130,13 @@ WelcomeViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { using FWString = QFutureWatcher< QString >; - auto* handler = new CalamaresUtils::GeoIP::Handler( - CalamaresUtils::getString( geoip, "style" ), - CalamaresUtils::getString( geoip, "url" ), - CalamaresUtils::getString( geoip, "selector" ) ); + auto* handler = new CalamaresUtils::GeoIP::Handler( CalamaresUtils::getString( geoip, "style" ), + CalamaresUtils::getString( geoip, "url" ), + CalamaresUtils::getString( geoip, "selector" ) ); if ( handler->type() != CalamaresUtils::GeoIP::Handler::Type::None ) { auto* future = new FWString(); - connect( future, &FWString::finished, [view=this, f=future, h=handler]() - { + connect( future, &FWString::finished, [view = this, f = future, h = handler]() { QString countryResult = f->future().result(); cDebug() << "GeoIP result for welcome=" << countryResult; view->setCountry( countryResult, h ); @@ -154,7 +158,9 @@ WelcomeViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { auto icon = Calamares::Branding::instance()->image( language, QSize( 48, 48 ) ); if ( !icon.isNull() ) + { m_widget->setLanguageIcon( icon ); + } } } @@ -169,7 +175,8 @@ logGeoIPHandler( CalamaresUtils::GeoIP::Handler* handler ) { if ( handler ) { - cDebug() << Logger::SubEntry << "Obtained from" << handler->url() << " (" << static_cast( handler->type() ) << handler->selector() << ')'; + cDebug() << Logger::SubEntry << "Obtained from" << handler->url() << " (" + << static_cast< int >( handler->type() ) << handler->selector() << ')'; } } @@ -194,8 +201,12 @@ WelcomeViewStep::setCountry( const QString& countryCode, CalamaresUtils::GeoIP:: { int r = CalamaresUtils::Locale::availableTranslations()->find( countryCode ); if ( r < 0 ) + { cDebug() << "Unusable country code" << countryCode << "(no suitable translation)"; + } if ( ( r >= 0 ) && m_widget ) + { m_widget->externallySelectedLanguage( r ); + } } } diff --git a/src/modules/welcome/welcome.conf b/src/modules/welcome/welcome.conf index a430345a2..e8433c48d 100644 --- a/src/modules/welcome/welcome.conf +++ b/src/modules/welcome/welcome.conf @@ -12,6 +12,13 @@ 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. +# +# donateUrl: 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. From 64d4b0a46cbbb6f630cdd348610be7ee5c7d10fd Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 13 Aug 2019 22:43:11 +0200 Subject: [PATCH 213/302] [welcome] Switch API for buttons to an enum + string - Handle buttons and their URL-opening in a more general way with an enum; drop existing three-boot method and special setupDonateButton() - Doesn't compile because consumers haven't changed. --- src/modules/welcome/WelcomePage.cpp | 51 ++++++++++++++++++++++++----- src/modules/welcome/WelcomePage.h | 14 +++++--- 2 files changed, 52 insertions(+), 13 deletions(-) diff --git a/src/modules/welcome/WelcomePage.cpp b/src/modules/welcome/WelcomePage.cpp index 6d0fc0d98..35807e93c 100644 --- a/src/modules/welcome/WelcomePage.cpp +++ b/src/modules/welcome/WelcomePage.cpp @@ -32,6 +32,7 @@ #include "modulesystem/ModuleManager.h" #include "utils/CalamaresUtilsGui.h" #include "utils/Logger.h" +#include "utils/NamedEnum.h" #include "utils/Retranslator.h" #include @@ -244,27 +245,59 @@ WelcomePage::setUpLinks( bool showSupportUrl, bool showKnownIssuesUrl, bool show void -WelcomePage::setupDonateButton( const QString& url ) +WelcomePage::setupButton( Button role, const QString& url ) { + QPushButton* button = nullptr; + CalamaresUtils::ImageType icon = CalamaresUtils::Information; + + switch ( role ) + { + case Button::Donate: + button = ui->donateButton; + icon = CalamaresUtils::Donate; + break; + case Button::KnownIssues: + button = ui->knownIssuesButton; + icon = CalamaresUtils::Bugs; + break; + case Button::ReleaseNotes: + button = ui->releaseNotesButton; + icon = CalamaresUtils::Release; + break; + case Button::Support: + button = ui->supportButton; + icon = CalamaresUtils::Help; + break; + } + if ( !button ) + { + qWarning() << "Unknown button role" << smash( role ); + return; + } + if ( url.isEmpty() ) { - ui->donateButton->hide(); + button->hide(); return; } QUrl u( url ); if ( u.isValid() ) { - ui->donateButton->setIcon( CalamaresUtils::defaultPixmap( - CalamaresUtils::Donate, - CalamaresUtils::Original, - 2 * QSize( CalamaresUtils::defaultFontHeight(), CalamaresUtils::defaultFontHeight() ) ) ); - connect( ui->donateButton, &QPushButton::clicked, [u]() { QDesktopServices::openUrl( u ); } ); + auto size = 2 * QSize( CalamaresUtils::defaultFontHeight(), CalamaresUtils::defaultFontHeight() ) ); + button->setIcon( CalamaresUtils::defaultPixmap( + icon, + CalamaresUtils::Original,size + ); + connect( button, &QPushButton::clicked, [u]() + { + QDesktopServices::openUrl( u ); + } ); } else { - qWarning() << "Donate URL" << url << "is invalid."; - ui->donateButton->hide(); + qWarning() << "Welcome button" << smash( role ) << "URL" << url << "is invalid."; + button->hide(); } } diff --git a/src/modules/welcome/WelcomePage.h b/src/modules/welcome/WelcomePage.h index d8a1bd4f2..3e776a5f0 100644 --- a/src/modules/welcome/WelcomePage.h +++ b/src/modules/welcome/WelcomePage.h @@ -38,10 +38,16 @@ class WelcomePage : public QWidget public: explicit WelcomePage( QWidget* parent = nullptr ); - /// @brief Configure the buttons for URLs from the branding configuration - void setUpLinks( bool showSupportUrl, bool showKnownIssuesUrl, bool showReleaseNotesUrl ); - /// @brief Configure the "Donate" button - void setupDonateButton( const QString& ); + enum class Button + { + Support, + Donate, + KnownIssues, + ReleaseNotes + }; + + /// @brief Configure the button @p n, to open @p url + void setupButton( Button b, const QString& url ); /// @brief Set international language-selector icon void setLanguageIcon( QPixmap ); From 119f84d6c146b86fa659727bd57f64aabb810383 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 13 Aug 2019 22:57:33 +0200 Subject: [PATCH 214/302] [welcome] Remove setupLinks() method, use generic - the generic (enum-based) setupButton() can handle all four of the buttons, so setupLinks() can go away. Only the (re)translation of the text on the button needs to be done, so move that to the main RETRANSLATE. --- src/modules/welcome/WelcomePage.cpp | 84 ++++++----------------------- 1 file changed, 15 insertions(+), 69 deletions(-) diff --git a/src/modules/welcome/WelcomePage.cpp b/src/modules/welcome/WelcomePage.cpp index 35807e93c..8f989c47c 100644 --- a/src/modules/welcome/WelcomePage.cpp +++ b/src/modules/welcome/WelcomePage.cpp @@ -73,18 +73,20 @@ WelcomePage::WelcomePage( QWidget* parent ) cDebug() << "Welcome string" << Calamares::Branding::instance()->welcomeStyleCalamares() << *Calamares::Branding::VersionedName; - CALAMARES_RETRANSLATE( QString message; + CALAMARES_RETRANSLATE( + QString message; - if ( Calamares::Settings::instance()->isSetupMode() ) message - = Calamares::Branding::instance()->welcomeStyleCalamares() - ? 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.

" ); + if ( Calamares::Settings::instance()->isSetupMode() ) message + = Calamares::Branding::instance()->welcomeStyleCalamares() + ? 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.

" ); - ui->mainText->setText( message.arg( *Calamares::Branding::VersionedName ) ); - ui->retranslateUi( this ); ) + ui->mainText->setText( message.arg( *Calamares::Branding::VersionedName ) ); + ui->retranslateUi( this ); + ui->supportButton->setText( tr( "%1 support" ).arg( *Calamares::Branding::ShortProductName ) ); ) ui->aboutButton->setIcon( CalamaresUtils::defaultPixmap( CalamaresUtils::Information, @@ -194,56 +196,6 @@ WelcomePage::initLanguages() } -void -WelcomePage::setUpLinks( bool showSupportUrl, bool showKnownIssuesUrl, bool showReleaseNotesUrl ) -{ - using namespace Calamares; - if ( showSupportUrl && !( *Branding::SupportUrl ).isEmpty() ) - { - CALAMARES_RETRANSLATE( ui->supportButton->setText( tr( "%1 support" ).arg( *Branding::ShortProductName ) ); ) - ui->supportButton->setIcon( CalamaresUtils::defaultPixmap( - CalamaresUtils::Help, - CalamaresUtils::Original, - 2 * QSize( CalamaresUtils::defaultFontHeight(), CalamaresUtils::defaultFontHeight() ) ) ); - connect( ui->supportButton, &QPushButton::clicked, [] { QDesktopServices::openUrl( *Branding::SupportUrl ); } ); - } - else - { - ui->supportButton->hide(); - } - - if ( showKnownIssuesUrl && !( *Branding::KnownIssuesUrl ).isEmpty() ) - { - ui->knownIssuesButton->setIcon( CalamaresUtils::defaultPixmap( - CalamaresUtils::Bugs, - CalamaresUtils::Original, - 2 * QSize( CalamaresUtils::defaultFontHeight(), CalamaresUtils::defaultFontHeight() ) ) ); - connect( ui->knownIssuesButton, &QPushButton::clicked, [] { - QDesktopServices::openUrl( *Branding::KnownIssuesUrl ); - } ); - } - else - { - ui->knownIssuesButton->hide(); - } - - if ( showReleaseNotesUrl && !( *Branding::ReleaseNotesUrl ).isEmpty() ) - { - ui->releaseNotesButton->setIcon( CalamaresUtils::defaultPixmap( - CalamaresUtils::Release, - CalamaresUtils::Original, - 2 * QSize( CalamaresUtils::defaultFontHeight(), CalamaresUtils::defaultFontHeight() ) ) ); - connect( ui->releaseNotesButton, &QPushButton::clicked, [] { - QDesktopServices::openUrl( *Branding::ReleaseNotesUrl ); - } ); - } - else - { - ui->releaseNotesButton->hide(); - } -} - - void WelcomePage::setupButton( Button role, const QString& url ) { @@ -284,15 +236,9 @@ WelcomePage::setupButton( Button role, const QString& url ) QUrl u( url ); if ( u.isValid() ) { - auto size = 2 * QSize( CalamaresUtils::defaultFontHeight(), CalamaresUtils::defaultFontHeight() ) ); - button->setIcon( CalamaresUtils::defaultPixmap( - icon, - CalamaresUtils::Original,size - ); - connect( button, &QPushButton::clicked, [u]() - { - QDesktopServices::openUrl( u ); - } ); + auto size = 2 * QSize( CalamaresUtils::defaultFontHeight(), CalamaresUtils::defaultFontHeight() ); + button->setIcon( CalamaresUtils::defaultPixmap( icon, CalamaresUtils::Original, size ) ); + connect( button, &QPushButton::clicked, [u]() { QDesktopServices::openUrl( u ); } ); } else { From 341965c2b1f72bf34541b89bb90ec894accd38e4 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 13 Aug 2019 23:01:52 +0200 Subject: [PATCH 215/302] [welcome] Use setupButton for all four buttons - the show* settings in welcome.conf are "upgraded" to allow setting the URL directly in the module configuration. --- src/modules/welcome/WelcomeViewStep.cpp | 45 ++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/src/modules/welcome/WelcomeViewStep.cpp b/src/modules/welcome/WelcomeViewStep.cpp index 60dd6f500..b489adc9e 100644 --- a/src/modules/welcome/WelcomeViewStep.cpp +++ b/src/modules/welcome/WelcomeViewStep.cpp @@ -105,15 +105,50 @@ WelcomeViewStep::jobs() const } +/** @brief Look up a URL for a button + * + * Looks up @p key in @p map; if it is a *boolean* value, then + * assume an old-style configuration, and fetch the string from + * the branding settings @p e. If it is a string, not a boolean, + * use it as-is. If not found, or a weird type, returns empty. + * + * This allows switching the showKnownIssuesUrl and similar settings + * in welcome.conf from a boolean (deferring to branding) to an + * actual string for immediate use. Empty strings, as well as + * "false" as a setting, will hide the buttons as before. + */ +static QString +jobOrBrandingSetting( Calamares::Branding::StringEntry e, const QVariantMap& map, const QString& key ) +{ + if ( !map.contains( key ) ) + { + return QString(); + } + auto v = map.value( key ); + if ( v.type() == QVariant::Bool ) + { + return v.toBool() ? ( *e ) : QString(); + } + if ( v.type() == QVariant::String ) + { + return v.toString(); + } + + return QString(); +} + void WelcomeViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { - bool showSupportUrl = CalamaresUtils::getBool( configurationMap, "showSupportUrl", false ); - bool showKnownIssuesUrl = CalamaresUtils::getBool( configurationMap, "showKnownIssuesUrl", false ); - bool showReleaseNotesUrl = CalamaresUtils::getBool( configurationMap, "showReleaseNotesUrl", false ); + using Calamares::Branding; - m_widget->setUpLinks( showSupportUrl, showKnownIssuesUrl, showReleaseNotesUrl ); - m_widget->setupDonateButton( CalamaresUtils::getString( configurationMap, "donateUrl" ) ); + m_widget->setupButton( WelcomePage::Button::Support, + jobOrBrandingSetting( Branding::SupportUrl, configurationMap, "showSupportUrl" ) ); + m_widget->setupButton( WelcomePage::Button::KnownIssues, + jobOrBrandingSetting( Branding::KnownIssuesUrl, configurationMap, "showKnownIssuesUrl" ) ); + m_widget->setupButton( WelcomePage::Button::ReleaseNotes, + jobOrBrandingSetting( Branding::ReleaseNotesUrl, configurationMap, "showReleaseNotesUrl" ) ); + m_widget->setupButton( WelcomePage::Button::Donate, CalamaresUtils::getString( configurationMap, "donateUrl" ) ); if ( configurationMap.contains( "requirements" ) && configurationMap.value( "requirements" ).type() == QVariant::Map ) From 706cc7392520f833c077b5a76879b41efecc564c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 13 Aug 2019 23:07:21 +0200 Subject: [PATCH 216/302] [branding] [welcome] Adjust documentation for welcome-overrides --- src/branding/default/branding.desc | 3 ++- src/modules/welcome/welcome.conf | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/branding/default/branding.desc b/src/branding/default/branding.desc index 3d1079a8c..5d9b29c69 100644 --- a/src/branding/default/branding.desc +++ b/src/branding/default/branding.desc @@ -58,7 +58,8 @@ windowSize: 800px,520px # if it contains substitutions, or you'll get YAML exceptions. # # The *Url* entries are used on the welcome page, and they -# are visible as buttons there if the corresponding *show* keys are set. +# are visible as buttons there if the corresponding *show* keys +# are set to "true" (they can also be overridden). strings: productName: "@{NAME}" shortProductName: Generic diff --git a/src/modules/welcome/welcome.conf b/src/modules/welcome/welcome.conf index e8433c48d..f0f9e7394 100644 --- a/src/modules/welcome/welcome.conf +++ b/src/modules/welcome/welcome.conf @@ -7,7 +7,11 @@ # can check requirements for installation. --- # Display settings for various buttons on the welcome page. -# The URLs themselves come from branding.desc +# 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. showSupportUrl: true showKnownIssuesUrl: true showReleaseNotesUrl: true From c36f963954d3ad0acf4ff7ddadd9227074aaf579 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 13 Aug 2019 23:08:33 +0200 Subject: [PATCH 217/302] [welcome] Adjust names of URLs to be consistent - having show*Url and donateUrl seems inconsistent, although the show*Url settings were originally boolean-only. - add "show" to the Donate button setting, to make them all consistent (putting a boolean there will generate a warning and hide the button, that's all). --- src/modules/welcome/WelcomeViewStep.cpp | 2 +- src/modules/welcome/welcome.conf | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/modules/welcome/WelcomeViewStep.cpp b/src/modules/welcome/WelcomeViewStep.cpp index b489adc9e..17a10f754 100644 --- a/src/modules/welcome/WelcomeViewStep.cpp +++ b/src/modules/welcome/WelcomeViewStep.cpp @@ -148,7 +148,7 @@ WelcomeViewStep::setConfigurationMap( const QVariantMap& configurationMap ) jobOrBrandingSetting( Branding::KnownIssuesUrl, configurationMap, "showKnownIssuesUrl" ) ); m_widget->setupButton( WelcomePage::Button::ReleaseNotes, jobOrBrandingSetting( Branding::ReleaseNotesUrl, configurationMap, "showReleaseNotesUrl" ) ); - m_widget->setupButton( WelcomePage::Button::Donate, CalamaresUtils::getString( configurationMap, "donateUrl" ) ); + m_widget->setupButton( WelcomePage::Button::Donate, CalamaresUtils::getString( configurationMap, "showDonateUrl" ) ); if ( configurationMap.contains( "requirements" ) && configurationMap.value( "requirements" ).type() == QVariant::Map ) diff --git a/src/modules/welcome/welcome.conf b/src/modules/welcome/welcome.conf index f0f9e7394..9488daa5e 100644 --- a/src/modules/welcome/welcome.conf +++ b/src/modules/welcome/welcome.conf @@ -19,9 +19,10 @@ 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. +# the corresponding link. (This button has no corresponding +# branding.desc string) # -# donateUrl: https://kde.org/community/donations/ +# showDonateUrl: https://kde.org/community/donations/ # Requirements checking. These are general, generic, things # that are checked. They may not match with the actual requirements From 0b7dcf7c50559fb7a29486c2eda0751039a423b1 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 13 Aug 2019 23:22:33 +0200 Subject: [PATCH 218/302] [welcome] Fix up tooltips - the "Select language" tooltip was applied to the form, so it would show up inappropriately all over the place - the buttons didn't have useful tooltips. --- src/modules/welcome/WelcomePage.ui | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/modules/welcome/WelcomePage.ui b/src/modules/welcome/WelcomePage.ui index 0787ac6e7..160daa595 100644 --- a/src/modules/welcome/WelcomePage.ui +++ b/src/modules/welcome/WelcomePage.ui @@ -13,9 +13,6 @@ Form - - Select language - @@ -69,7 +66,7 @@ - Select language + Select application and system language @@ -81,6 +78,9 @@ + + Select application and system language + 2 @@ -136,6 +136,9 @@ + + Open donations website + &Donate @@ -146,6 +149,9 @@ + + Open help and support website + &Support @@ -156,6 +162,9 @@ + + Open issues and bug-tracking website + &Known issues @@ -166,6 +175,9 @@ + + Open relead notes website + &Release notes From 257f5da1af78747759dc580eec27a6d1667f2304 Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Wed, 14 Aug 2019 09:58:40 +0200 Subject: [PATCH 219/302] mount: Use a single partitions list sorted by mount point Instead of having a special case for extra mounts to be processed right after the rootfs, a better approach is to add them to the partitions list, and then sort the list by mount point. This way, we make sure every partition is mounted right when it is needed: `/` is obviously mounted first, `/run` is mounted before `/run/udev`, and so on. The overall process is therefore more generic and should suit all use-cases. Signed-off-by: Arnaud Ferraris --- src/modules/mount/main.py | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/src/modules/mount/main.py b/src/modules/mount/main.py index b093d0dfb..1c684c43f 100644 --- a/src/modules/mount/main.py +++ b/src/modules/mount/main.py @@ -37,7 +37,7 @@ _ = gettext.translation("calamares-python", def pretty_name(): return _("Mounting partitions.") -def mount_part(root_mount_point, partition, partitions): +def mount_partition(root_mount_point, partition, partitions): # Create mount point with `+` rather than `os.path.join()` because # `partition["mountPoint"]` starts with a '/'. raw_mount_point = partition["mountPoint"] @@ -126,21 +126,6 @@ def mount_part(root_mount_point, partition, partitions): ["subvol=@home", partition.get("options", "")]), ) -def mount_partitions(root_mount_point, partitions, extra_mounts=None): - """ - Pass back mount point and filesystem for each partition. - - :param root_mount_point: - :param partitions: - :param extra_mounts: - """ - for partition in partitions: - if "mountPoint" not in partition or not partition["mountPoint"]: - continue - mount_part(root_mount_point, partition, partitions) - if partition["mountPoint"] is "/" and extra_mounts is not None: - mount_partitions(root_mount_point, extra_mounts) - def run(): """ @@ -163,16 +148,21 @@ def run(): if not extra_mounts and not extra_mounts_efi: libcalamares.utils.warning("No extra mounts defined. Does mount.conf exist?") - # Sort by mount points to ensure / is mounted before the rest - partitions.sort(key=lambda x: x["mountPoint"]) - mount_partitions(root_mount_point, partitions, extra_mounts) - - all_extra_mounts = extra_mounts if libcalamares.globalstorage.value("firmwareType") == "efi": - mount_partitions(root_mount_point, extra_mounts_efi) - all_extra_mounts.extend(extra_mounts_efi) + extra_mounts.extend(extra_mounts_efi) + + # Add extra mounts to the partitions list and sort by mount points. + # This way, we ensure / is mounted before the rest, and every mount point + # is created on the right partition (e.g. if a partition is to be mounted + # under /tmp, we make sure /tmp is mounted before the partition) + partitions.extend(extra_mounts) + partitions.sort(key=lambda x: x["mountPoint"]) + for partition in partitions: + if "mountPoint" not in partition or not partition["mountPoint"]: + continue + mount_partition(root_mount_point, partition, partitions) libcalamares.globalstorage.insert("rootMountPoint", root_mount_point) # Remember the extra mounts for the unpackfs module - libcalamares.globalstorage.insert("extraMounts", all_extra_mounts) + libcalamares.globalstorage.insert("extraMounts", extra_mounts) From 2e8a106f2c82266448f13591cf3c9206ac7fee64 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 16 Aug 2019 04:21:53 -0400 Subject: [PATCH 220/302] Changes: document new stuff --- CHANGES | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGES b/CHANGES index 3f4aad749..e926da175 100644 --- a/CHANGES +++ b/CHANGES @@ -23,6 +23,13 @@ This release contains contributions from (alphabetically by first name): ## Modules ## +- The *partition* module now understands the units *KB*, *MB*, *GB* which + are powers-of-ten sizes, alongside the powers-of-two sizes that it already + used. (thanks to Arnaud) +- The *welcome* module now supports a *Donate* button if *showDonateUrl* + is set to a non-empty URL. #1197 +- The *welcome* module can have URLs for the various buttons configured + directly in the module configuration (rather than in `branding.desc`). # 3.2.12 (2019-08-07) # From 395c375c603f401e4c0ac780fb243c39b1b3c990 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 19 Aug 2019 06:28:32 -0400 Subject: [PATCH 221/302] [mount] Winnow partition list - Simplify the iteration by first determining which partitions are mountable (at all). - This guards against the very rare case that a partition does not have a mountPoint at all (the if guarded against that) where the lambda passed to sort() would get a KeyError. --- src/modules/mount/main.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/modules/mount/main.py b/src/modules/mount/main.py index 1c684c43f..d33b4681b 100644 --- a/src/modules/mount/main.py +++ b/src/modules/mount/main.py @@ -155,11 +155,9 @@ def run(): # This way, we ensure / is mounted before the rest, and every mount point # is created on the right partition (e.g. if a partition is to be mounted # under /tmp, we make sure /tmp is mounted before the partition) - partitions.extend(extra_mounts) - partitions.sort(key=lambda x: x["mountPoint"]) - for partition in partitions: - if "mountPoint" not in partition or not partition["mountPoint"]: - continue + mountable_partitions = [ p for p in partitions + extra_mounts if "mountPoint" in p and p["mountPoint"] ] + mountable_partitions.sort(key=lambda x: x["mountPoint"]) + for partition in mountable_partitions: mount_partition(root_mount_point, partition, partitions) libcalamares.globalstorage.insert("rootMountPoint", root_mount_point) From 52af9dbaad1775de5fa4b6f2c053ee7f73fc301b Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 19 Aug 2019 06:31:37 -0400 Subject: [PATCH 222/302] [mount] Add docstrings to methods --- src/modules/mount/main.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/modules/mount/main.py b/src/modules/mount/main.py index d33b4681b..b10c5c0bf 100644 --- a/src/modules/mount/main.py +++ b/src/modules/mount/main.py @@ -38,6 +38,12 @@ def pretty_name(): return _("Mounting partitions.") def mount_partition(root_mount_point, partition, partitions): + """ + Do a single mount of @p partition inside @p root_mount_point. + + The @p partitions are used to handle btrfs special-cases: + then subvolumes are created for root and home. + """ # Create mount point with `+` rather than `os.path.join()` because # `partition["mountPoint"]` starts with a '/'. raw_mount_point = partition["mountPoint"] @@ -129,9 +135,8 @@ def mount_partition(root_mount_point, partition, partitions): def run(): """ - Define mountpoints. - - :return: + Mount all the partitions from GlobalStorage and from the job configuration. + Partitions are mounted in-lexical-order of their mountPoint. """ partitions = libcalamares.globalstorage.value("partitions") From 5b4152133d5721a6dda6b2a6bba14074c05cf96b Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 19 Aug 2019 06:45:05 -0400 Subject: [PATCH 223/302] [packagechooser] Look for AppStream libs --- src/modules/packagechooser/CMakeLists.txt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/modules/packagechooser/CMakeLists.txt b/src/modules/packagechooser/CMakeLists.txt index 70a86a3bb..ec3c15826 100644 --- a/src/modules/packagechooser/CMakeLists.txt +++ b/src/modules/packagechooser/CMakeLists.txt @@ -9,7 +9,19 @@ if ( Qt5Xml_FOUND ) add_definitions( -DHAVE_XML ) list( APPEND _extra_libraries Qt5::Xml ) endif() - + +find_package(AppStreamQt) +set_package_properties( + AppStreamQt PROPERTIES + DESCRIPTION "Support for AppStream (cache) data" + URL "https://github.com/ximion/appstream" + PURPOSE "AppStream provides package data" + TYPE OPTIONAL +) +if ( AppStreamQt_FOUND ) + add_definitions( -DHAVE_APPSTREAM ) + list( APPEND _extra_libraries AppStreamQt ) +endif() calamares_add_plugin( packagechooser TYPE viewmodule From 2f20ad30bf067a1380177421b0221373702e3eac Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 19 Aug 2019 06:55:36 -0400 Subject: [PATCH 224/302] [packagechooser] Refactor AppData XML support into separate file - Put the implementation entirely in a separate file, keep the not-supported one in PackageModel.cpp (but only in an #ifdef). - Makes the various optional-data-sources more similar. --- src/modules/packagechooser/CMakeLists.txt | 3 + src/modules/packagechooser/ItemAppData.cpp | 234 ++++++++++++++++++++ src/modules/packagechooser/PackageModel.cpp | 212 +----------------- 3 files changed, 239 insertions(+), 210 deletions(-) create mode 100644 src/modules/packagechooser/ItemAppData.cpp diff --git a/src/modules/packagechooser/CMakeLists.txt b/src/modules/packagechooser/CMakeLists.txt index ec3c15826..e93a5816f 100644 --- a/src/modules/packagechooser/CMakeLists.txt +++ b/src/modules/packagechooser/CMakeLists.txt @@ -1,5 +1,6 @@ find_package( Qt5 COMPONENTS Core Gui Widgets REQUIRED ) set( _extra_libraries "" ) +set( _extra_src "" ) ### OPTIONAL AppData XML support in PackageModel # @@ -8,6 +9,7 @@ find_package(Qt5 COMPONENTS Xml) if ( Qt5Xml_FOUND ) add_definitions( -DHAVE_XML ) list( APPEND _extra_libraries Qt5::Xml ) + list( APPEND _extra_src ItemAppData.cpp ) endif() find_package(AppStreamQt) @@ -30,6 +32,7 @@ calamares_add_plugin( packagechooser PackageChooserPage.cpp PackageChooserViewStep.cpp PackageModel.cpp + ${_extra_src} RESOURCES packagechooser.qrc UI diff --git a/src/modules/packagechooser/ItemAppData.cpp b/src/modules/packagechooser/ItemAppData.cpp new file mode 100644 index 000000000..7c80a1c3d --- /dev/null +++ b/src/modules/packagechooser/ItemAppData.cpp @@ -0,0 +1,234 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 . + */ + +/** @brief Loading items from AppData XML files. + * + * Only used if QtXML is found, implements PackageItem::fromAppData(). + */ +#include "PackageModel.h" + +#include "utils/Logger.h" +#include "utils/Variant.h" + +#include +#include +#include + +/** @brief try to load the given @p fileName XML document + * + * Returns a QDomDocument, which will be valid iff the file can + * be read and contains valid XML data. + */ +static inline QDomDocument +loadAppData( const QString& fileName ) +{ + QFile file( fileName ); + if ( !file.open( QIODevice::ReadOnly ) ) + { + return QDomDocument(); + } + QDomDocument doc( "AppData" ); + if ( !doc.setContent( &file ) ) + { + file.close(); + return QDomDocument(); + } + file.close(); + return doc; +} + +/** @brief gets the text of child element @p tagName + */ +static inline QString +getChildText( const QDomNode& n, const QString& tagName ) +{ + QDomElement e = n.firstChildElement( tagName ); + return e.isNull() ? QString() : e.text(); +} + +/** @brief Gets a suitable screenshot path + * + * The element contains zero or more + * elements, which can have a *type* associated with them. + * Scan the screenshot elements, return the path + * for the one labeled with type=default or, if there is no + * default, the first element. + */ +static inline QString +getScreenshotPath( const QDomNode& n ) +{ + QDomElement shotsNode = n.firstChildElement( "screenshots" ); + if ( shotsNode.isNull() ) + { + return QString(); + } + + const QDomNodeList shotList = shotsNode.childNodes(); + int firstScreenshot = -1; // Use which screenshot node? + for ( int i = 0; i < shotList.count(); ++i ) + { + if ( !shotList.at( i ).isElement() ) + { + continue; + } + QDomElement e = shotList.at( i ).toElement(); + if ( e.tagName() != "screenshot" ) + { + continue; + } + // If none has the "type=default" attribute, use the first one + if ( firstScreenshot < 0 ) + { + firstScreenshot = i; + } + // But type=default takes precedence. + if ( e.hasAttribute( "type" ) && e.attribute( "type" ) == "default" ) + { + firstScreenshot = i; + break; + } + } + + if ( firstScreenshot >= 0 ) + { + return shotList.at( firstScreenshot ).firstChildElement( "image" ).text(); + } + + return QString(); +} + +/** @brief Returns language of the given element @p e + * + * Transforms the attribute value for xml:lang to something + * suitable for TranslatedString (e.g. [lang]). + */ +static inline QString +getLanguage( const QDomElement& e ) +{ + QString language = e.attribute( "xml:lang" ); + if ( !language.isEmpty() ) + { + language.replace( '-', '_' ); + language.prepend( '[' ); + language.append( ']' ); + } + return language; +} + +/** @brief Scan the list of @p children for @p tagname elements and add them to the map + * + * Uses @p mapname instead of @p tagname for the entries in map @p m + * to allow renaming from XML to map keys (in particular for + * TranslatedString). Also transforms xml:lang attributes to suitable + * key-decorations on @p mapname. + */ +static inline void +fillMap( QVariantMap& m, const QDomNodeList& children, const QString& tagname, const QString& mapname ) +{ + for ( int i = 0; i < children.count(); ++i ) + { + if ( !children.at( i ).isElement() ) + { + continue; + } + + QDomElement e = children.at( i ).toElement(); + if ( e.tagName() != tagname ) + { + continue; + } + + m[ mapname + getLanguage( e ) ] = e.text(); + } +} + +/** @brief gets the and elements +* +* Builds up a map of the elements (which may have a *lang* +* attribute to indicate translations and paragraphs of the +* element (also with lang). Uses the +* elements to supplement the description if no description +* is available for a given language. +* +* Returns a map with keys suitable for use by TranslatedString. +*/ +static inline QVariantMap +getNameAndSummary( const QDomNode& n ) +{ + QVariantMap m; + + const QDomNodeList children = n.childNodes(); + fillMap( m, children, "name", "name" ); + fillMap( m, children, "summary", "description" ); + + const QDomElement description = n.firstChildElement( "description" ); + if ( !description.isNull() ) + { + fillMap( m, description.childNodes(), "p", "description" ); + } + + return m; +} + +PackageItem +PackageItem::fromAppData( const QVariantMap& item_map ) +{ + QString fileName = CalamaresUtils::getString( item_map, "appdata" ); + if ( fileName.isEmpty() ) + { + cWarning() << "Can't load AppData without a suitable key."; + return PackageItem(); + } + cDebug() << "Loading AppData XML from" << fileName; + + QDomDocument doc = loadAppData( fileName ); + if ( doc.isNull() ) + { + return PackageItem(); + } + + QDomElement componentNode = doc.documentElement(); + if ( !componentNode.isNull() && componentNode.tagName() == "component" ) + { + // An "id" entry in the Calamares config overrides ID in the AppData + QString id = CalamaresUtils::getString( item_map, "id" ); + if ( id.isEmpty() ) + { + id = getChildText( componentNode, "id" ); + } + if ( id.isEmpty() ) + { + return PackageItem(); + } + + // A "screenshot" entry in the Calamares config overrides AppData + QString screenshotPath = CalamaresUtils::getString( item_map, "screenshot" ); + if ( screenshotPath.isEmpty() ) + { + screenshotPath = getScreenshotPath( componentNode ); + } + + QVariantMap map = getNameAndSummary( componentNode ); + map.insert( "id", id ); + map.insert( "screenshot", screenshotPath ); + + return PackageItem( map ); + } + + return PackageItem(); +} diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index 59c6973ba..e15559552 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -21,12 +21,6 @@ #include "utils/Logger.h" #include "utils/Variant.h" -#ifdef HAVE_XML -#include -#include -#include -#endif - const NamedEnumTable< PackageChooserMode >& roleNames() { @@ -94,217 +88,15 @@ PackageItem::PackageItem::PackageItem( const QVariantMap& item_map ) } } -#ifdef HAVE_XML -/** @brief try to load the given @p fileName XML document - * - * Returns a QDomDocument, which will be valid iff the file can - * be read and contains valid XML data. - */ -static inline QDomDocument -loadAppData( const QString& fileName ) -{ - QFile file( fileName ); - if ( !file.open( QIODevice::ReadOnly ) ) - { - return QDomDocument(); - } - QDomDocument doc( "AppData" ); - if ( !doc.setContent( &file ) ) - { - file.close(); - return QDomDocument(); - } - file.close(); - return doc; -} - -/** @brief gets the text of child element @p tagName - */ -static inline QString -getChildText( const QDomNode& n, const QString& tagName ) -{ - QDomElement e = n.firstChildElement( tagName ); - return e.isNull() ? QString() : e.text(); -} - -/** @brief Gets a suitable screenshot path - * - * The element contains zero or more - * elements, which can have a *type* associated with them. - * Scan the screenshot elements, return the path - * for the one labeled with type=default or, if there is no - * default, the first element. - */ -static inline QString -getScreenshotPath( const QDomNode& n ) -{ - QDomElement shotsNode = n.firstChildElement( "screenshots" ); - if ( shotsNode.isNull() ) - { - return QString(); - } - - const QDomNodeList shotList = shotsNode.childNodes(); - int firstScreenshot = -1; // Use which screenshot node? - for ( int i = 0; i < shotList.count(); ++i ) - { - if ( !shotList.at( i ).isElement() ) - { - continue; - } - QDomElement e = shotList.at( i ).toElement(); - if ( e.tagName() != "screenshot" ) - { - continue; - } - // If none has the "type=default" attribute, use the first one - if ( firstScreenshot < 0 ) - { - firstScreenshot = i; - } - // But type=default takes precedence. - if ( e.hasAttribute( "type" ) && e.attribute( "type" ) == "default" ) - { - firstScreenshot = i; - break; - } - } - - if ( firstScreenshot >= 0 ) - { - return shotList.at( firstScreenshot ).firstChildElement( "image" ).text(); - } - - return QString(); -} - -/** @brief Returns language of the given element @p e - * - * Transforms the attribute value for xml:lang to something - * suitable for TranslatedString (e.g. [lang]). - */ -static inline QString -getLanguage( const QDomElement& e ) -{ - QString language = e.attribute( "xml:lang" ); - if ( !language.isEmpty() ) - { - language.replace( '-', '_' ); - language.prepend( '[' ); - language.append( ']' ); - } - return language; -} - -/** @brief Scan the list of @p children for @p tagname elements and add them to the map - * - * Uses @p mapname instead of @p tagname for the entries in map @p m - * to allow renaming from XML to map keys (in particular for - * TranslatedString). Also transforms xml:lang attributes to suitable - * key-decorations on @p mapname. - */ -static inline void -fillMap( QVariantMap& m, const QDomNodeList& children, const QString& tagname, const QString& mapname ) -{ - for ( int i = 0; i < children.count(); ++i ) - { - if ( !children.at( i ).isElement() ) - { - continue; - } - - QDomElement e = children.at( i ).toElement(); - if ( e.tagName() != tagname ) - { - continue; - } - - m[ mapname + getLanguage( e ) ] = e.text(); - } -} - -/** @brief gets the and elements -* -* Builds up a map of the elements (which may have a *lang* -* attribute to indicate translations and paragraphs of the -* element (also with lang). Uses the -* elements to supplement the description if no description -* is available for a given language. -* -* Returns a map with keys suitable for use by TranslatedString. -*/ -static inline QVariantMap -getNameAndSummary( const QDomNode& n ) -{ - QVariantMap m; - - const QDomNodeList children = n.childNodes(); - fillMap( m, children, "name", "name" ); - fillMap( m, children, "summary", "description" ); - - const QDomElement description = n.firstChildElement( "description" ); - if ( !description.isNull() ) - { - fillMap( m, description.childNodes(), "p", "description" ); - } - - return m; -} -#endif +#ifndef HAVE_XML PackageItem PackageItem::fromAppData( const QVariantMap& item_map ) { -#ifdef HAVE_XML - QString fileName = CalamaresUtils::getString( item_map, "appdata" ); - if ( fileName.isEmpty() ) - { - cWarning() << "Can't load AppData without a suitable key."; - return PackageItem(); - } - cDebug() << "Loading AppData XML from" << fileName; - - QDomDocument doc = loadAppData( fileName ); - if ( doc.isNull() ) - { - return PackageItem(); - } - - QDomElement componentNode = doc.documentElement(); - if ( !componentNode.isNull() && componentNode.tagName() == "component" ) - { - // An "id" entry in the Calamares config overrides ID in the AppData - QString id = CalamaresUtils::getString( item_map, "id" ); - if ( id.isEmpty() ) - { - id = getChildText( componentNode, "id" ); - } - if ( id.isEmpty() ) - { - return PackageItem(); - } - - // A "screenshot" entry in the Calamares config overrides AppData - QString screenshotPath = CalamaresUtils::getString( item_map, "screenshot" ); - if ( screenshotPath.isEmpty() ) - { - screenshotPath = getScreenshotPath( componentNode ); - } - - QVariantMap map = getNameAndSummary( componentNode ); - map.insert( "id", id ); - map.insert( "screenshot", screenshotPath ); - - return PackageItem( map ); - } - - return PackageItem(); -#else cWarning() << "Loading AppData XML is not supported."; - return PackageItem(); -#endif } +#endif PackageListModel::PackageListModel( QObject* parent ) From eaa0c02f8db46a18d1b7928ff00296d0a24d4417 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 19 Aug 2019 07:10:38 -0400 Subject: [PATCH 225/302] [packagechooser] Initial support for appstream items - Use *appstream* as key in one of the items for the package- chooser to load data from the AppStream cache in the system. - Usable for some applications; for DE-selection not so much. - Currently unimplemented. --- src/modules/packagechooser/CMakeLists.txt | 1 + src/modules/packagechooser/ItemAppStream.cpp | 33 +++++++++++++++++++ .../packagechooser/PackageChooserViewStep.cpp | 4 +++ src/modules/packagechooser/PackageModel.cpp | 9 +++++ src/modules/packagechooser/PackageModel.h | 14 ++++++++ .../packagechooser/packagechooser.conf | 18 +++++++--- 6 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 src/modules/packagechooser/ItemAppStream.cpp diff --git a/src/modules/packagechooser/CMakeLists.txt b/src/modules/packagechooser/CMakeLists.txt index e93a5816f..eb84c9bab 100644 --- a/src/modules/packagechooser/CMakeLists.txt +++ b/src/modules/packagechooser/CMakeLists.txt @@ -23,6 +23,7 @@ set_package_properties( if ( AppStreamQt_FOUND ) add_definitions( -DHAVE_APPSTREAM ) list( APPEND _extra_libraries AppStreamQt ) + list( APPEND _extra_src ItemAppStream.cpp ) endif() calamares_add_plugin( packagechooser diff --git a/src/modules/packagechooser/ItemAppStream.cpp b/src/modules/packagechooser/ItemAppStream.cpp new file mode 100644 index 000000000..287e5a139 --- /dev/null +++ b/src/modules/packagechooser/ItemAppStream.cpp @@ -0,0 +1,33 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 . + */ + +/** @brief Loading items from AppData XML files. + * + * Only used if QtXML is found, implements PackageItem::fromAppData(). + */ +#include "PackageModel.h" + +#include "utils/Logger.h" +#include "utils/Variant.h" + +PackageItem +PackageItem::fromAppStream( const QVariantMap& map ) +{ + cWarning() << "AppStream loading not implemented."; + return PackageItem(); +} diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index c2e849d5f..412658394 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -219,6 +219,10 @@ PackageChooserViewStep::fillModel( const QVariantList& items ) { m_model->addPackage( PackageItem::fromAppData( item_map ) ); } + else if ( item_map.contains( "appstream" ) ) + { + m_model->addPackage( PackageItem::fromAppStream( item_map ) ); + } else { m_model->addPackage( PackageItem( item_map ) ); diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index e15559552..bc80109f3 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -98,6 +98,15 @@ PackageItem::fromAppData( const QVariantMap& item_map ) } #endif +#ifndef HAVE_APPSTREAM +PackageItem +PackageItem::fromAppStream( const QVariantMap& item_map ) +{ + cWarning() << "Loading AppStream data is not supported."; + return PackageItem(); +} +#endif + PackageListModel::PackageListModel( QObject* parent ) : QAbstractListModel( parent ) diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index 869e124f0..49b4bc0dd 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -93,6 +93,20 @@ struct PackageItem * return invalid PackageItems. */ static PackageItem fromAppData( const QVariantMap& map ); + + /** @brief Loads an item from AppStream data. + * + * The @p map must have a key *appstream*. That is used as the + * primary source of information from the AppStream cache, but + * keys *id* and *screenshotPath* may be used to override parts + * of the AppStream data -- so that the ID is under the control + * of Calamares, and the screenshot can be forced to a local path + * available on the installation medium. + * + * Requires AppStreamQt, if not present will return invalid + * PackageItems. + */ + static PackageItem fromAppStream( const QVariantMap& map ); }; using PackageList = QVector< PackageItem >; diff --git a/src/modules/packagechooser/packagechooser.conf b/src/modules/packagechooser/packagechooser.conf index e9b2d9329..eebe4dfb4 100644 --- a/src/modules/packagechooser/packagechooser.conf +++ b/src/modules/packagechooser/packagechooser.conf @@ -20,14 +20,15 @@ # or one-or-more). mode: required -# Items to display in the chooser. In general, this should be a +# Items to display in the chooser. In general, this should be a # pretty short list to avoid overwhelming the UI. This is a list # of objects, and the items are displayed in list order. # # Either provide the data for an item in the list (using the keys -# below), or use existing AppData XML files as a source for the data. +# below), or use existing AppData XML files, or use AppStream cache +# as a source for the data. # -# For data provided by the list: the item has an id, which is used in +# For data provided by the list: the item has an id, which is used in # setting the value of *packagechooser_*). The following fields # are mandatory: # @@ -60,6 +61,14 @@ mode: required # be loaded and the screenshot will be missing. An item with *appdata* # **may** specify an ID or screenshot path, as above. This will override # the settings from AppData. +# +# For data provided by AppStream cache: the item has an *appstream* +# key which matches the AppStream identifier in the cache (e.g. +# *org.kde.kwrite.desktop*). Data is retrieved from the AppStream +# cache for that ID. The package name is set from the AppStream data. +# +# An item for AppStream may also contain an *id* and a *screenshot* +# key which will override the data from AppStream. items: - id: "" package: "" @@ -81,4 +90,5 @@ items: - id: calamares appdata: ../io.calamares.calamares.appdata.xml screenshot: ":/images/calamares.png" - + - id: kate + appstream: org.kde.kwrite.desktop From fa2f5763c64e486eac428d91fe9683e1571655c7 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 19 Aug 2019 07:25:28 -0400 Subject: [PATCH 226/302] [packagechooser] Load AppStream data - Get the id, name, and description from AppStream data Missing: - No translations - No screenshots --- src/modules/packagechooser/ItemAppStream.cpp | 62 ++++++++++++++++++-- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/src/modules/packagechooser/ItemAppStream.cpp b/src/modules/packagechooser/ItemAppStream.cpp index 287e5a139..769973575 100644 --- a/src/modules/packagechooser/ItemAppStream.cpp +++ b/src/modules/packagechooser/ItemAppStream.cpp @@ -25,9 +25,63 @@ #include "utils/Logger.h" #include "utils/Variant.h" -PackageItem -PackageItem::fromAppStream( const QVariantMap& map ) +#include + +static PackageItem +fromComponent( const AppStream::Component& component ) { - cWarning() << "AppStream loading not implemented."; - return PackageItem(); + cDebug() << "Loaded" << component.id(); + + QVariantMap map; + map.insert( "id", component.id() ); + map.insert( "name", component.name() ); + map.insert( "description", component.description() ); + // map.insert( "screenshot", component.screenshots() ); + return PackageItem( map ); +} + +PackageItem +PackageItem::fromAppStream( const QVariantMap& item_map ) +{ + QString appstreamId = CalamaresUtils::getString( item_map, "appstream" ); + if ( appstreamId.isEmpty() ) + { + cWarning() << "Can't load AppStream without a suitable appstreamId."; + return PackageItem(); + } + cDebug() << "Loading AppStream data for" << appstreamId; + + AppStream::Pool pool; + if ( !pool.load() ) + { + cWarning() << "AppStream load failed" << pool.lastError(); + return PackageItem(); + } + + auto itemList = pool.componentsById( appstreamId ); + if ( itemList.count() < 1 ) + { + cWarning() << "No AppStream data for" << appstreamId; + return PackageItem(); + } + if ( itemList.count() > 1 ) + { + cDebug() << "Multiple AppStream data for" << appstreamId << "using first."; + } + + auto r = fromComponent( itemList.first() ); + if ( r.isValid() ) + { + QString id = CalamaresUtils::getString( item_map, "id" ); + QString screenshotPath = CalamaresUtils::getString( item_map, "screenshot" ); + if ( !id.isEmpty() ) + { + r.id = id; + } + if ( !screenshotPath.isEmpty() ) + { + r.screenshot = screenshotPath; + } + } + return r; } From 17abbeda96737b006bd286813fb3b0c103a28d7f Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 19 Aug 2019 10:02:43 -0400 Subject: [PATCH 227/302] [packagechooser] Try to load a screenshot - The smallest size image of the default (or, if there is no default, the first) screenshot is used. - Remote URLs are not supported by QPixmap, so most will not load anyway. --- src/modules/packagechooser/ItemAppStream.cpp | 63 ++++++++++++++++++-- 1 file changed, 59 insertions(+), 4 deletions(-) diff --git a/src/modules/packagechooser/ItemAppStream.cpp b/src/modules/packagechooser/ItemAppStream.cpp index 769973575..392797846 100644 --- a/src/modules/packagechooser/ItemAppStream.cpp +++ b/src/modules/packagechooser/ItemAppStream.cpp @@ -22,21 +22,76 @@ */ #include "PackageModel.h" +#include "locale/LabelModel.h" #include "utils/Logger.h" #include "utils/Variant.h" +#include #include +#include -static PackageItem -fromComponent( const AppStream::Component& component ) +/// @brief Return number of pixels in a size, for < ordering purposes +static inline quint64 +sizeOrder( const QSize& size ) { - cDebug() << "Loaded" << component.id(); + return size.width() * size.height(); +} +/// @brief Sets a screenshot in @p map from @p screenshot, if a usable one is found +static void +setScreenshot( QVariantMap& map, const AppStream::Screenshot& screenshot ) +{ + if ( screenshot.images().count() < 1 ) + { + return; + } + + // Pick the smallest + QUrl url; + quint64 size = sizeOrder( screenshot.images().first().size() ); + for ( const auto& img : screenshot.images() ) + { + if ( sizeOrder( img.size() ) <= size ) + { + url = img.url(); + } + } + + if ( url.isValid() ) + { + map.insert( "screenshot", url.toString() ); + } +} + +/// @brief Interpret an AppStream Component +static PackageItem +fromComponent( AppStream::Component& component ) +{ QVariantMap map; map.insert( "id", component.id() ); map.insert( "name", component.name() ); map.insert( "description", component.description() ); - // map.insert( "screenshot", component.screenshots() ); + map.insert( "package", component.packageNames().join(",") ); + + auto screenshots = component.screenshots(); + if ( screenshots.count() > 0 ) + { + bool done = false; + for ( const auto& s : screenshots ) + { + if ( s.isDefault() ) + { + setScreenshot( map, s ); + done = true; + break; + } + } + if ( !done ) + { + setScreenshot( map, screenshots.first() ); + } + } + return PackageItem( map ); } From 0a92ef7655f6c897ada15c75ad0b2470bdd40ce1 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 20 Aug 2019 04:15:35 -0400 Subject: [PATCH 228/302] [packagechooser] Refactor fromApp*() - These don't have to be static methods of PackageItem, a free function is more convenient. - Since it's not API of PackageItem anymore, need to - update tests not to use API - do API-not-available warnings in consumers --- src/modules/packagechooser/ItemAppData.cpp | 2 +- src/modules/packagechooser/ItemAppData.h | 37 ++++++++++++++++++ src/modules/packagechooser/ItemAppStream.cpp | 4 +- src/modules/packagechooser/ItemAppStream.h | 38 +++++++++++++++++++ .../packagechooser/PackageChooserViewStep.cpp | 18 ++++++++- src/modules/packagechooser/PackageModel.cpp | 20 ---------- src/modules/packagechooser/PackageModel.h | 27 ------------- src/modules/packagechooser/Tests.cpp | 12 ++++-- 8 files changed, 102 insertions(+), 56 deletions(-) create mode 100644 src/modules/packagechooser/ItemAppData.h create mode 100644 src/modules/packagechooser/ItemAppStream.h diff --git a/src/modules/packagechooser/ItemAppData.cpp b/src/modules/packagechooser/ItemAppData.cpp index 7c80a1c3d..ed0ba9223 100644 --- a/src/modules/packagechooser/ItemAppData.cpp +++ b/src/modules/packagechooser/ItemAppData.cpp @@ -186,7 +186,7 @@ getNameAndSummary( const QDomNode& n ) } PackageItem -PackageItem::fromAppData( const QVariantMap& item_map ) +fromAppData( const QVariantMap& item_map ) { QString fileName = CalamaresUtils::getString( item_map, "appdata" ); if ( fileName.isEmpty() ) diff --git a/src/modules/packagechooser/ItemAppData.h b/src/modules/packagechooser/ItemAppData.h new file mode 100644 index 000000000..72617ff0c --- /dev/null +++ b/src/modules/packagechooser/ItemAppData.h @@ -0,0 +1,37 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 ITEMAPPDATA_H +#define ITEMAPPDATA_H + +#include "PackageModel.h" + +/** @brief Loads an AppData XML file and returns a PackageItem + * + * The @p map must have a key *appdata*. That is used as the + * primary source of information, but keys *id* and *screenshotPath* + * may be used to override parts of the AppData -- so that the + * ID is under the control of Calamares, and the screenshot can be + * forced to a local path available on the installation medium. + * + * Requires XML support in libcalamares, if not present will + * return invalid PackageItems. + */ +PackageItem fromAppData( const QVariantMap& map ); + +#endif diff --git a/src/modules/packagechooser/ItemAppStream.cpp b/src/modules/packagechooser/ItemAppStream.cpp index 392797846..3ee49f7d0 100644 --- a/src/modules/packagechooser/ItemAppStream.cpp +++ b/src/modules/packagechooser/ItemAppStream.cpp @@ -71,7 +71,7 @@ fromComponent( AppStream::Component& component ) map.insert( "id", component.id() ); map.insert( "name", component.name() ); map.insert( "description", component.description() ); - map.insert( "package", component.packageNames().join(",") ); + map.insert( "package", component.packageNames().join( "," ) ); auto screenshots = component.screenshots(); if ( screenshots.count() > 0 ) @@ -96,7 +96,7 @@ fromComponent( AppStream::Component& component ) } PackageItem -PackageItem::fromAppStream( const QVariantMap& item_map ) +fromAppStream( const QVariantMap& item_map ) { QString appstreamId = CalamaresUtils::getString( item_map, "appstream" ); if ( appstreamId.isEmpty() ) diff --git a/src/modules/packagechooser/ItemAppStream.h b/src/modules/packagechooser/ItemAppStream.h new file mode 100644 index 000000000..7d820400f --- /dev/null +++ b/src/modules/packagechooser/ItemAppStream.h @@ -0,0 +1,38 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 ITEMAPPSTREAM_H +#define ITEMAPPSTREAM_H + +#include "PackageModel.h" + +/** @brief Loads an item from AppStream data. + * + * The @p map must have a key *appstream*. That is used as the + * primary source of information from the AppStream cache, but + * keys *id* and *screenshotPath* may be used to override parts + * of the AppStream data -- so that the ID is under the control + * of Calamares, and the screenshot can be forced to a local path + * available on the installation medium. + * + * Requires AppStreamQt, if not present will return invalid + * PackageItems. + */ +PackageItem fromAppStream( const QVariantMap& map ); + +#endif diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 412658394..bf45c6726 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -18,6 +18,12 @@ #include "PackageChooserViewStep.h" +#ifdef HAVE_XML +#include "ItemAppData.h" +#endif +#ifdef HAVE_APPSTREAM +#include "ItemAppStream.h" +#endif #include "PackageChooserPage.h" #include "PackageModel.h" @@ -217,11 +223,19 @@ PackageChooserViewStep::fillModel( const QVariantList& items ) if ( item_map.contains( "appdata" ) ) { - m_model->addPackage( PackageItem::fromAppData( item_map ) ); +#ifdef HAVE_XML + m_model->addPackage( fromAppData( item_map ) ); +#else + cWarning() << "Loading AppData XML is not supported."; +#endif } else if ( item_map.contains( "appstream" ) ) { - m_model->addPackage( PackageItem::fromAppStream( item_map ) ); +#ifdef HAVE_APPSTREAM + m_model->addPackage( fromAppStream( item_map ) ); +#else + cWarning() << "Loading AppStream data is not supported."; +#endif } else { diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index bc80109f3..12995fad5 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -88,26 +88,6 @@ PackageItem::PackageItem::PackageItem( const QVariantMap& item_map ) } } - -#ifndef HAVE_XML -PackageItem -PackageItem::fromAppData( const QVariantMap& item_map ) -{ - cWarning() << "Loading AppData XML is not supported."; - return PackageItem(); -} -#endif - -#ifndef HAVE_APPSTREAM -PackageItem -PackageItem::fromAppStream( const QVariantMap& item_map ) -{ - cWarning() << "Loading AppStream data is not supported."; - return PackageItem(); -} -#endif - - PackageListModel::PackageListModel( QObject* parent ) : QAbstractListModel( parent ) { diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index 49b4bc0dd..8362bee33 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -80,33 +80,6 @@ struct PackageItem * A valid item has an untranslated name available. */ bool isValid() const { return !name.isEmpty(); } - - /** @brief Loads an AppData XML file and returns a PackageItem - * - * The @p map must have a key *appdata*. That is used as the - * primary source of information, but keys *id* and *screenshotPath* - * may be used to override parts of the AppData -- so that the - * ID is under the control of Calamares, and the screenshot can be - * forced to a local path available on the installation medium. - * - * Requires XML support in libcalamares, if not present will - * return invalid PackageItems. - */ - static PackageItem fromAppData( const QVariantMap& map ); - - /** @brief Loads an item from AppStream data. - * - * The @p map must have a key *appstream*. That is used as the - * primary source of information from the AppStream cache, but - * keys *id* and *screenshotPath* may be used to override parts - * of the AppStream data -- so that the ID is under the control - * of Calamares, and the screenshot can be forced to a local path - * available on the installation medium. - * - * Requires AppStreamQt, if not present will return invalid - * PackageItems. - */ - static PackageItem fromAppStream( const QVariantMap& map ); }; using PackageList = QVector< PackageItem >; diff --git a/src/modules/packagechooser/Tests.cpp b/src/modules/packagechooser/Tests.cpp index 537ecbd3c..639d06d65 100644 --- a/src/modules/packagechooser/Tests.cpp +++ b/src/modules/packagechooser/Tests.cpp @@ -18,6 +18,12 @@ #include "Tests.h" +#ifdef HAVE_XML +#include "ItemAppData.h" +#endif +#ifdef HAVE_APPSTREAM +#include "ItemAppStream.h" +#endif #include "PackageModel.h" #include "utils/Logger.h" @@ -62,8 +68,8 @@ PackageChooserTests::testAppData() QVariantMap m; m.insert( "appdata", appdataName ); - PackageItem p1 = PackageItem::fromAppData( m ); #ifdef HAVE_XML + PackageItem p1 = fromAppData( m ); QVERIFY( p1.isValid() ); QCOMPARE( p1.id, "io.calamares.calamares.desktop" ); QCOMPARE( p1.name.get(), "Calamares" ); @@ -76,12 +82,10 @@ PackageChooserTests::testAppData() m.insert( "id", "calamares" ); m.insert( "screenshot", ":/images/calamares.png" ); - PackageItem p2 = PackageItem::fromAppData( m ); + PackageItem p2 = fromAppData( m ); QVERIFY( p2.isValid() ); QCOMPARE( p2.id, "calamares" ); QCOMPARE( p2.description.get( QLocale( "nl" ) ), "Calamares is een installatieprogramma voor Linux distributies." ); QVERIFY( !p2.screenshot.isNull() ); -#else - QVERIFY( !p1.isValid() ); #endif } From d8af11adeee88b41ff210ed9e06ffcfd890cd219 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 20 Aug 2019 04:38:24 -0400 Subject: [PATCH 229/302] [packagechooser] Build AppStream Pool first - Don't build a Pool for each PackageItem loaded - Do make it load all languages instead of only the current one --- src/modules/packagechooser/ItemAppStream.cpp | 9 +-------- src/modules/packagechooser/ItemAppStream.h | 7 ++++++- .../packagechooser/PackageChooserViewStep.cpp | 18 +++++++++++++++++- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/modules/packagechooser/ItemAppStream.cpp b/src/modules/packagechooser/ItemAppStream.cpp index 3ee49f7d0..fe4af95b4 100644 --- a/src/modules/packagechooser/ItemAppStream.cpp +++ b/src/modules/packagechooser/ItemAppStream.cpp @@ -96,7 +96,7 @@ fromComponent( AppStream::Component& component ) } PackageItem -fromAppStream( const QVariantMap& item_map ) +fromAppStream( AppStream::Pool& pool, const QVariantMap& item_map ) { QString appstreamId = CalamaresUtils::getString( item_map, "appstream" ); if ( appstreamId.isEmpty() ) @@ -106,13 +106,6 @@ fromAppStream( const QVariantMap& item_map ) } cDebug() << "Loading AppStream data for" << appstreamId; - AppStream::Pool pool; - if ( !pool.load() ) - { - cWarning() << "AppStream load failed" << pool.lastError(); - return PackageItem(); - } - auto itemList = pool.componentsById( appstreamId ); if ( itemList.count() < 1 ) { diff --git a/src/modules/packagechooser/ItemAppStream.h b/src/modules/packagechooser/ItemAppStream.h index 7d820400f..c44b84b06 100644 --- a/src/modules/packagechooser/ItemAppStream.h +++ b/src/modules/packagechooser/ItemAppStream.h @@ -21,6 +21,11 @@ #include "PackageModel.h" +namespace AppStream +{ +class Pool; +} + /** @brief Loads an item from AppStream data. * * The @p map must have a key *appstream*. That is used as the @@ -33,6 +38,6 @@ * Requires AppStreamQt, if not present will return invalid * PackageItems. */ -PackageItem fromAppStream( const QVariantMap& map ); +PackageItem fromAppStream( AppStream::Pool& pool, const QVariantMap& map ); #endif diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index bf45c6726..7758986ba 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -23,6 +23,8 @@ #endif #ifdef HAVE_APPSTREAM #include "ItemAppStream.h" +#include +#include #endif #include "PackageChooserPage.h" #include "PackageModel.h" @@ -209,6 +211,11 @@ PackageChooserViewStep::fillModel( const QVariantList& items ) return; } +#ifdef HAVE_APPSTREAM + std::unique_ptr< AppStream::Pool > pool; + bool poolOk = false; +#endif + cDebug() << "Loading PackageChooser model items from config"; int item_index = 0; for ( const auto& item_it : items ) @@ -232,7 +239,16 @@ PackageChooserViewStep::fillModel( const QVariantList& items ) else if ( item_map.contains( "appstream" ) ) { #ifdef HAVE_APPSTREAM - m_model->addPackage( fromAppStream( item_map ) ); + if ( !pool ) + { + pool = std::make_unique< AppStream::Pool >(); + pool->setLocale( QStringLiteral( "ALL" ) ); + poolOk = pool->load(); + } + if ( pool && poolOk ) + { + m_model->addPackage( fromAppStream( *pool, item_map ) ); + } #else cWarning() << "Loading AppStream data is not supported."; #endif From 7b699bfc762353cfd22da93ed3cfe2c09d472a1f Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 20 Aug 2019 05:26:26 -0400 Subject: [PATCH 230/302] [libcalamares] Access list of locale Ids - Make it easier to obtain locale-ids (from CALAMARES_TRANSLATION_LANGUAGES) so avoid splitting that string multiple times. --- src/libcalamares/locale/LabelModel.cpp | 3 ++- src/libcalamares/locale/LabelModel.h | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libcalamares/locale/LabelModel.cpp b/src/libcalamares/locale/LabelModel.cpp index 87fca9d85..bcb8af057 100644 --- a/src/libcalamares/locale/LabelModel.cpp +++ b/src/libcalamares/locale/LabelModel.cpp @@ -29,6 +29,7 @@ namespace Locale LabelModel::LabelModel( const QStringList& locales, QObject* parent ) : QAbstractListModel( parent ) + , m_localeIds( locales ) { Q_ASSERT( locales.count() > 0 ); m_locales.reserve( locales.count() ); @@ -132,7 +133,7 @@ LabelModel::find( const QString& countryCode ) const LabelModel* availableTranslations() { - static LabelModel* model = new LabelModel( QString( CALAMARES_TRANSLATION_LANGUAGES ).split( ';' ) ); + static LabelModel* model = new LabelModel( QStringLiteral( CALAMARES_TRANSLATION_LANGUAGES ).split( ';' ) ); return model; } diff --git a/src/libcalamares/locale/LabelModel.h b/src/libcalamares/locale/LabelModel.h index 5082440d3..03daddbf3 100644 --- a/src/libcalamares/locale/LabelModel.h +++ b/src/libcalamares/locale/LabelModel.h @@ -54,6 +54,9 @@ public: */ const Label& locale( int row ) const; + /// @brief Returns all of the locale Ids (e.g. en_US) put into this model. + const QStringList& localeIds() const { return m_localeIds; } + /** @brief Searches for an item that matches @p predicate * * Returns the row number of the first match, or -1 if there isn't one. @@ -67,6 +70,7 @@ public: private: QVector< Label > m_locales; + QStringList m_localeIds; }; /** @brief Returns a model with all available translations. From ffa899b4977cde0d4525f9dad1f16a41c2572e67 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 20 Aug 2019 05:37:52 -0400 Subject: [PATCH 231/302] [packagechooser] Assemble the translated name and description --- src/modules/packagechooser/ItemAppStream.cpp | 28 ++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/modules/packagechooser/ItemAppStream.cpp b/src/modules/packagechooser/ItemAppStream.cpp index fe4af95b4..83837a9ca 100644 --- a/src/modules/packagechooser/ItemAppStream.cpp +++ b/src/modules/packagechooser/ItemAppStream.cpp @@ -69,10 +69,34 @@ fromComponent( AppStream::Component& component ) { QVariantMap map; map.insert( "id", component.id() ); - map.insert( "name", component.name() ); - map.insert( "description", component.description() ); map.insert( "package", component.packageNames().join( "," ) ); + // Assume that the pool has loaded "ALL" locales, but it might be set + // to any of them; get the en_US locale as "untranslated" and then + // loop over Calamares locales (since there is no way to query for + // available locales in the Component) to see if there's anything else. + component.setActiveLocale( QStringLiteral( "en_US" ) ); + QString en_name = component.name(); + QString en_description = component.description(); + map.insert( "name", en_name ); + map.insert( "description", en_description ); + + for ( const QString& locale : CalamaresUtils::Locale::availableTranslations()->localeIds() ) + { + component.setActiveLocale( locale ); + QString name = component.name(); + if ( name != en_name ) + { + map.insert( QStringLiteral( "name[%1]" ).arg( locale ), name ); + } + QString description = component.description(); + if ( description != en_description ) + { + map.insert( QStringLiteral( "description[%1]" ).arg( locale ), description ); + } + } + + auto screenshots = component.screenshots(); if ( screenshots.count() > 0 ) { From 8c5caf9fd05278b1a0a24424808efb288c4fdc42 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 20 Aug 2019 13:56:23 +0200 Subject: [PATCH 232/302] [packagechooser] Add CMake knobs to enable/disable item choices - AppData and AppStream can be disabled independently of finding their requirements (possibly useful if you want to ignore AppStream even when it's installed in your build environment). - Add a little top-level documentation about WITH_ --- CMakeLists.txt | 3 ++ src/modules/packagechooser/CMakeLists.txt | 43 ++++++++++++++--------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5461aa3c8..321989ac0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,9 @@ # SKIP_MODULES : a space or semicolon-separated list of directory names # under src/modules that should not be built. # 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. # BUILD_ : choose additional things to build # DEBUG_ : special developer flags for debugging # diff --git a/src/modules/packagechooser/CMakeLists.txt b/src/modules/packagechooser/CMakeLists.txt index eb84c9bab..eeae655c9 100644 --- a/src/modules/packagechooser/CMakeLists.txt +++ b/src/modules/packagechooser/CMakeLists.txt @@ -5,25 +5,34 @@ set( _extra_src "" ) ### OPTIONAL AppData XML support in PackageModel # # -find_package(Qt5 COMPONENTS Xml) -if ( Qt5Xml_FOUND ) - add_definitions( -DHAVE_XML ) - list( APPEND _extra_libraries Qt5::Xml ) - list( APPEND _extra_src ItemAppData.cpp ) +option( WITH_APPDATA "Support appdata: items in PackageChooser (requires QtXml)" ON ) +if ( WITH_APPDATA ) + find_package(Qt5 COMPONENTS Xml) + if ( Qt5Xml_FOUND ) + add_definitions( -DHAVE_XML ) + list( APPEND _extra_libraries Qt5::Xml ) + list( APPEND _extra_src ItemAppData.cpp ) + endif() endif() -find_package(AppStreamQt) -set_package_properties( - AppStreamQt PROPERTIES - DESCRIPTION "Support for AppStream (cache) data" - URL "https://github.com/ximion/appstream" - PURPOSE "AppStream provides package data" - TYPE OPTIONAL -) -if ( AppStreamQt_FOUND ) - add_definitions( -DHAVE_APPSTREAM ) - list( APPEND _extra_libraries AppStreamQt ) - list( APPEND _extra_src ItemAppStream.cpp ) +### OPTIONAL AppStream support in PackageModel +# +# +option( WITH_APPSTREAM "Support appstream: items in PackageChooser (requires libappstream-qt)" ON ) +if ( WITH_APPSTREAM ) + find_package(AppStreamQt) + set_package_properties( + AppStreamQt PROPERTIES + DESCRIPTION "Support for AppStream (cache) data" + URL "https://github.com/ximion/appstream" + PURPOSE "AppStream provides package data" + TYPE OPTIONAL + ) + if ( AppStreamQt_FOUND ) + add_definitions( -DHAVE_APPSTREAM ) + list( APPEND _extra_libraries AppStreamQt ) + list( APPEND _extra_src ItemAppStream.cpp ) + endif() endif() calamares_add_plugin( packagechooser From 4b35d193b743f83c6d5b6a9f01074a4f7c90e010 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 20 Aug 2019 14:03:52 +0200 Subject: [PATCH 233/302] Changes: mention #1212, AppStream data loading --- CHANGES | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES b/CHANGES index e926da175..66323ff9f 100644 --- a/CHANGES +++ b/CHANGES @@ -23,6 +23,9 @@ This release contains contributions from (alphabetically by first name): ## Modules ## +- The *packagechooser* module can load data from the config-file, + from AppData XML files referred by the config-file, and (new) also + from AppStream caches by referring to an application's AppStream id. #1212 - The *partition* module now understands the units *KB*, *MB*, *GB* which are powers-of-ten sizes, alongside the powers-of-two sizes that it already used. (thanks to Arnaud) From d7602df51e8c12112cbc16ceea9ceceb6900af60 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 20 Aug 2019 09:25:37 -0400 Subject: [PATCH 234/302] [libcalamares] Introduce networking service - The networking service is intended to wrap up use of QNetworkAccessManager and others for consumption within Calamares, and to provide some convenience functions for internet access. - Medium term, it may also monitor network access, so that we can respond to changes in network availability during installation. Currently very minimal and undocumented. --- src/libcalamares/CMakeLists.txt | 3 + src/libcalamares/network/Manager.cpp | 93 ++++++++++++++++++++++++++++ src/libcalamares/network/Manager.h | 55 ++++++++++++++++ 3 files changed, 151 insertions(+) create mode 100644 src/libcalamares/network/Manager.cpp create mode 100644 src/libcalamares/network/Manager.h diff --git a/src/libcalamares/CMakeLists.txt b/src/libcalamares/CMakeLists.txt index f2063813c..ac9b2df08 100644 --- a/src/libcalamares/CMakeLists.txt +++ b/src/libcalamares/CMakeLists.txt @@ -36,6 +36,9 @@ set( libSources locale/Lookup.cpp locale/TranslatableConfiguration.cpp + # Network service + network/Manager.cpp + # Partition service partition/PartitionSize.cpp diff --git a/src/libcalamares/network/Manager.cpp b/src/libcalamares/network/Manager.cpp new file mode 100644 index 000000000..c229ab036 --- /dev/null +++ b/src/libcalamares/network/Manager.cpp @@ -0,0 +1,93 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 "Manager.h" + +#include +#include +#include +#include + +namespace CalamaresUtils +{ +namespace Network +{ +struct Manager::Private +{ + std::unique_ptr< QNetworkAccessManager > m_nam; + QUrl m_hasInternetUrl; + bool m_hasInternet; + + Private(); +}; +} // namespace Network +} // namespace CalamaresUtils +CalamaresUtils::Network::Manager::Private::Private() + : m_nam( std::make_unique< QNetworkAccessManager >() ) + , m_hasInternet( false ) +{ +} + +CalamaresUtils::Network::Manager::Manager() + : d( std::make_unique< Private >() ) +{ +} + +CalamaresUtils::Network::Manager::~Manager() {} + +CalamaresUtils::Network::Manager& +CalamaresUtils::Network::Manager::instance() +{ + static auto* s_manager = new CalamaresUtils::Network::Manager(); + return *s_manager; +} + +bool +CalamaresUtils::Network::Manager::hasInternet() +{ + return d->m_hasInternet; +} + +bool +CalamaresUtils::Network::Manager::checkHasInternet() +{ + bool b = false; + if ( d->m_hasInternetUrl.isValid() ) + { + b = synchronousPing( d->m_hasInternetUrl ); + } + d->m_hasInternet = b; + return b; +} + +void +CalamaresUtils::Network::Manager::setCheckHasInternetUrl( const QUrl& url ) +{ + d->m_hasInternetUrl = url; +} + +bool +CalamaresUtils::Network::Manager::synchronousPing( const QUrl& url ) +{ + QNetworkRequest req = QNetworkRequest( url ); + QNetworkReply* reply = d->m_nam->get( req ); + QEventLoop loop; + connect( reply, &QNetworkReply::finished, &loop, &QEventLoop::quit ); + loop.exec(); + return reply->bytesAvailable(); +} diff --git a/src/libcalamares/network/Manager.h b/src/libcalamares/network/Manager.h new file mode 100644 index 000000000..a9903e115 --- /dev/null +++ b/src/libcalamares/network/Manager.h @@ -0,0 +1,55 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 LIBCALAMARES_NETWORK_MANAGER_H +#define LIBCALAMARES_NETWORK_MANAGER_H + +#include "DllMacro.h" + +#include +#include + +#include + +namespace CalamaresUtils +{ +namespace Network +{ +class DLLEXPORT Manager : QObject +{ + Q_OBJECT + + Manager(); + +public: + static Manager& instance(); + virtual ~Manager(); + + bool synchronousPing( const QUrl& url ); + + void setCheckHasInternetUrl( const QUrl& url ); + bool checkHasInternet(); + bool hasInternet(); + +private: + struct Private; + std::unique_ptr< Private > d; +}; +} // namespace Network +} // namespace CalamaresUtils +#endif // LIBCALAMARES_NETWORK_MANAGER_H From b8d56bb4a63100cfc5fa1d0b7b284be9d6deeebc Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 20 Aug 2019 09:51:39 -0400 Subject: [PATCH 235/302] [libcalamares] Add tests for network service --- src/libcalamares/CMakeLists.txt | 10 +++++++ src/libcalamares/network/Tests.cpp | 43 ++++++++++++++++++++++++++++++ src/libcalamares/network/Tests.h | 37 +++++++++++++++++++++++++ 3 files changed, 90 insertions(+) create mode 100644 src/libcalamares/network/Tests.cpp create mode 100644 src/libcalamares/network/Tests.h diff --git a/src/libcalamares/CMakeLists.txt b/src/libcalamares/CMakeLists.txt index ac9b2df08..87338ae6c 100644 --- a/src/libcalamares/CMakeLists.txt +++ b/src/libcalamares/CMakeLists.txt @@ -197,6 +197,16 @@ if ( ECM_FOUND AND BUILD_TESTING ) Qt5::Test ) calamares_automoc( libcalamareslocaletest ) + + ecm_add_test( + network/Tests.cpp + TEST_NAME + libcalamaresnetworktest + LINK_LIBRARIES + calamares + Qt5::Test + ) + calamares_automoc( libcalamaresnetworktest ) endif() if( BUILD_TESTING ) diff --git a/src/libcalamares/network/Tests.cpp b/src/libcalamares/network/Tests.cpp new file mode 100644 index 000000000..a13a74c86 --- /dev/null +++ b/src/libcalamares/network/Tests.cpp @@ -0,0 +1,43 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 "Tests.h" + +#include "Manager.h" + +#include + +QTEST_GUILESS_MAIN( NetworkTests ) + +NetworkTests::NetworkTests() +{ +} + +NetworkTests::~NetworkTests() +{ +} + +void NetworkTests::initTestCase() +{ +} + +void NetworkTests::testInstance() +{ + auto& nam = CalamaresUtils::Network::Manager::instance(); + QVERIFY( !nam.hasInternet() ); +} diff --git a/src/libcalamares/network/Tests.h b/src/libcalamares/network/Tests.h new file mode 100644 index 000000000..56f87cc67 --- /dev/null +++ b/src/libcalamares/network/Tests.h @@ -0,0 +1,37 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 LIBCALAMARES_NETWORK_TESTS_H +#define LIBCALAMARES_NETWORK_TESTS_H + +#include + +class NetworkTests : public QObject +{ + Q_OBJECT +public: + NetworkTests(); + ~NetworkTests() override; + +private Q_SLOTS: + void initTestCase(); + + void testInstance(); +}; + +#endif From 8d3530154f007793a7e50223512a155ef68395e5 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 20 Aug 2019 09:57:04 -0400 Subject: [PATCH 236/302] [libcalamares] Expand network service test - Do an actual ping (also to check for memory leaks) --- src/libcalamares/network/Tests.cpp | 25 +++++++++++++++---------- src/libcalamares/network/Tests.h | 1 + 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/libcalamares/network/Tests.cpp b/src/libcalamares/network/Tests.cpp index a13a74c86..559a955fe 100644 --- a/src/libcalamares/network/Tests.cpp +++ b/src/libcalamares/network/Tests.cpp @@ -24,20 +24,25 @@ QTEST_GUILESS_MAIN( NetworkTests ) -NetworkTests::NetworkTests() +NetworkTests::NetworkTests() {} + +NetworkTests::~NetworkTests() {} + +void +NetworkTests::initTestCase() { } -NetworkTests::~NetworkTests() -{ -} - -void NetworkTests::initTestCase() -{ -} - -void NetworkTests::testInstance() +void +NetworkTests::testInstance() { auto& nam = CalamaresUtils::Network::Manager::instance(); QVERIFY( !nam.hasInternet() ); } + +void +NetworkTests::testPing() +{ + auto& nam = CalamaresUtils::Network::Manager::instance(); + QVERIFY( nam.synchronousPing( QUrl( "https://www.kde.org" ) ) ); +} diff --git a/src/libcalamares/network/Tests.h b/src/libcalamares/network/Tests.h index 56f87cc67..b63f7eff0 100644 --- a/src/libcalamares/network/Tests.h +++ b/src/libcalamares/network/Tests.h @@ -32,6 +32,7 @@ private Q_SLOTS: void initTestCase(); void testInstance(); + void testPing(); }; #endif From 82622373bc8778e5b4f4563723871b35b5d7e1a8 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 20 Aug 2019 16:05:22 +0200 Subject: [PATCH 237/302] [libcalamares] Remove superfluous ; (warnings--) --- src/libcalamares/utils/PluginFactory.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcalamares/utils/PluginFactory.h b/src/libcalamares/utils/PluginFactory.h index 84694a83a..e8236a888 100644 --- a/src/libcalamares/utils/PluginFactory.h +++ b/src/libcalamares/utils/PluginFactory.h @@ -58,8 +58,8 @@ public: template < class impl, class ParentType > static QObject* createInstance( QWidget* parentWidget, QObject* parent, const QVariantList& args ) { - Q_UNUSED( parentWidget ); - Q_UNUSED( args ); + Q_UNUSED( parentWidget ) + Q_UNUSED( args ) ParentType* p = nullptr; if ( parent ) { From 11d52df04c64a7af54db5634e78a89bf2f95f3fa Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 20 Aug 2019 10:18:49 -0400 Subject: [PATCH 238/302] [libcalamares] Add API docs to network service --- src/libcalamares/network/Manager.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/libcalamares/network/Manager.h b/src/libcalamares/network/Manager.h index a9903e115..f357d8d70 100644 --- a/src/libcalamares/network/Manager.h +++ b/src/libcalamares/network/Manager.h @@ -37,13 +37,36 @@ class DLLEXPORT Manager : QObject Manager(); public: + /** @brief Gets the single Manager instance. + * + * Typical code will use `auto& nam = Manager::instance();` + * to keep the reference. + */ static Manager& instance(); virtual ~Manager(); + /** @brief Checks if the given @p url returns data. + * + * Returns @c true if it does; @c false means no data, typically + * because of an error or no network access. + */ bool synchronousPing( const QUrl& url ); + /// @brief Set the URL which is used for the general "is there internet" check. void setCheckHasInternetUrl( const QUrl& url ); + /** @brief Do an explicit check for internet connectivity. + * + * This **may** do a ping to the configured check URL, but can also + * use other mechanisms. + */ bool checkHasInternet(); + /** @brief Is there internet connectivity? + * + * This returns the result of the last explicit check, or if there + * is other information about the state of the internet connection, + * whatever is known. @c true means you can expect (all) internet + * connectivity to be present. + */ bool hasInternet(); private: From 4389c254df1165bbb524e819db766aeea71d8ea2 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 20 Aug 2019 10:22:03 -0400 Subject: [PATCH 239/302] [libcalamares] Rely directly on QNAM's networkAccessible() --- src/libcalamares/network/Manager.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libcalamares/network/Manager.cpp b/src/libcalamares/network/Manager.cpp index c229ab036..716c93f6a 100644 --- a/src/libcalamares/network/Manager.cpp +++ b/src/libcalamares/network/Manager.cpp @@ -66,8 +66,9 @@ CalamaresUtils::Network::Manager::hasInternet() bool CalamaresUtils::Network::Manager::checkHasInternet() { - bool b = false; - if ( d->m_hasInternetUrl.isValid() ) + bool b = d->m_nam->networkAccessible() == QNetworkAccessManager::Accessible; + + if ( !b && d->m_hasInternetUrl.isValid() ) { b = synchronousPing( d->m_hasInternetUrl ); } From e06500863101b6d3506c5710b81ab35e948fe2f6 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 20 Aug 2019 10:57:02 -0400 Subject: [PATCH 240/302] [welcome] Switch to the network service - simplify configuration - use existing ping- and hasInternet() --- .../welcome/checker/GeneralRequirements.cpp | 41 ++++++++----------- .../welcome/checker/GeneralRequirements.h | 1 - 2 files changed, 16 insertions(+), 26 deletions(-) diff --git a/src/modules/welcome/checker/GeneralRequirements.cpp b/src/modules/welcome/checker/GeneralRequirements.cpp index 0e6133d3f..4787fe51d 100644 --- a/src/modules/welcome/checker/GeneralRequirements.cpp +++ b/src/modules/welcome/checker/GeneralRequirements.cpp @@ -25,12 +25,14 @@ #include "partman_devices.h" #include "modulesystem/Requirement.h" +#include "network/Manager.h" #include "widgets/WaitingWidget.h" #include "utils/CalamaresUtilsGui.h" #include "utils/Logger.h" #include "utils/Retranslator.h" #include "utils/CalamaresUtilsSystem.h" #include "utils/Units.h" +#include "utils/Variant.h" #include "Settings.h" #include "JobQueue.h" @@ -245,16 +247,16 @@ GeneralRequirements::setConfigurationMap( const QVariantMap& configurationMap ) incompleteConfiguration = true; } - if ( configurationMap.contains( "internetCheckUrl" ) && - configurationMap.value( "internetCheckUrl" ).type() == QVariant::String ) + QUrl checkInternetUrl; + QString checkInternetSetting = CalamaresUtils::getString( configurationMap, "internetCheckUrl" ); + if ( !checkInternetSetting.isEmpty() ) { - m_checkHasInternetUrl = configurationMap.value( "internetCheckUrl" ).toString().trimmed(); - if ( m_checkHasInternetUrl.isEmpty() || - !QUrl( m_checkHasInternetUrl ).isValid() ) + checkInternetUrl = QUrl( checkInternetSetting.trimmed() ); + if ( !checkInternetUrl.isValid() ) { - cWarning() << "GeneralRequirements entry 'internetCheckUrl' is invalid in welcome.conf" << m_checkHasInternetUrl + cWarning() << "GeneralRequirements entry 'internetCheckUrl' is invalid in welcome.conf" << checkInternetSetting << "reverting to default (http://example.com)."; - m_checkHasInternetUrl = "http://example.com"; + checkInternetUrl = QUrl( "http://example.com" ); incompleteConfiguration = true; } } @@ -262,10 +264,13 @@ GeneralRequirements::setConfigurationMap( const QVariantMap& configurationMap ) { cWarning() << "GeneralRequirements entry 'internetCheckUrl' is undefined in welcome.conf," "reverting to default (http://example.com)."; - - m_checkHasInternetUrl = "http://example.com"; + checkInternetUrl = "http://example.com"; incompleteConfiguration = true; } + if ( checkInternetUrl.isValid() ) + { + CalamaresUtils::Network::Manager::instance().setCheckHasInternetUrl( checkInternetUrl ); + } if ( incompleteConfiguration ) { @@ -357,22 +362,8 @@ GeneralRequirements::checkHasPower() bool GeneralRequirements::checkHasInternet() { - // default to true in the QNetworkAccessManager::UnknownAccessibility case - QNetworkAccessManager qnam; - bool hasInternet = qnam.networkAccessible() == QNetworkAccessManager::Accessible; - - if ( !hasInternet && qnam.networkAccessible() == QNetworkAccessManager::UnknownAccessibility ) - { - QNetworkRequest req = QNetworkRequest( QUrl( m_checkHasInternetUrl ) ); - QNetworkReply* reply = qnam.get( req ); - QEventLoop loop; - connect( reply, &QNetworkReply::finished, - &loop, &QEventLoop::quit ); - loop.exec(); - if( reply->bytesAvailable() ) - hasInternet = true; - } - + auto& nam = CalamaresUtils::Network::Manager::instance(); + bool hasInternet = nam.checkHasInternet(); Calamares::JobQueue::instance()->globalStorage()->insert( "hasInternet", hasInternet ); return hasInternet; } diff --git a/src/modules/welcome/checker/GeneralRequirements.h b/src/modules/welcome/checker/GeneralRequirements.h index 1efe118a6..8e5a6cd54 100644 --- a/src/modules/welcome/checker/GeneralRequirements.h +++ b/src/modules/welcome/checker/GeneralRequirements.h @@ -48,7 +48,6 @@ private: qreal m_requiredStorageGiB; qreal m_requiredRamGiB; - QString m_checkHasInternetUrl; }; #endif // REQUIREMENTSCHECKER_H From eae931f2ed21e82abb1461042251a8e9dcd370c6 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 21 Aug 2019 03:43:51 -0400 Subject: [PATCH 241/302] [libcalamares] Ping only when accessibility is unknown - Restores exact functionality of previous version (noted by Kevin Kofler) - Short-circuit ping if the URL is bad. --- src/libcalamares/network/Manager.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/libcalamares/network/Manager.cpp b/src/libcalamares/network/Manager.cpp index 716c93f6a..b0c068c6e 100644 --- a/src/libcalamares/network/Manager.cpp +++ b/src/libcalamares/network/Manager.cpp @@ -66,14 +66,14 @@ CalamaresUtils::Network::Manager::hasInternet() bool CalamaresUtils::Network::Manager::checkHasInternet() { - bool b = d->m_nam->networkAccessible() == QNetworkAccessManager::Accessible; + bool hasInternet = d->m_nam->networkAccessible() == QNetworkAccessManager::Accessible; - if ( !b && d->m_hasInternetUrl.isValid() ) + if ( !hasInternet && ( d->m_nam->networkAccessible() == QNetworkAccessManager::UnknownAccessibility ) ) { - b = synchronousPing( d->m_hasInternetUrl ); + hasInternet = synchronousPing( d->m_hasInternetUrl ); } - d->m_hasInternet = b; - return b; + d->m_hasInternet = hasInternet; + return hasInternet; } void @@ -85,6 +85,11 @@ CalamaresUtils::Network::Manager::setCheckHasInternetUrl( const QUrl& url ) bool CalamaresUtils::Network::Manager::synchronousPing( const QUrl& url ) { + if ( !url.isValid() ) + { + return false; + } + QNetworkRequest req = QNetworkRequest( url ); QNetworkReply* reply = d->m_nam->get( req ); QEventLoop loop; From 310a1d76cf6ff00f9120a1ea785587ff89178cd8 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 21 Aug 2019 11:56:49 +0200 Subject: [PATCH 242/302] [calamares] Reduce warnings now that getInteger is qint64 --- src/calamares/CalamaresWindow.cpp | 4 ++-- src/libcalamares/utils/CommandList.cpp | 2 +- src/modules/contextualprocess/ContextualProcessJob.cpp | 2 +- src/modules/shellprocess/ShellProcessJob.cpp | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/calamares/CalamaresWindow.cpp b/src/calamares/CalamaresWindow.cpp index 1638d6392..ac00bafd4 100644 --- a/src/calamares/CalamaresWindow.cpp +++ b/src/calamares/CalamaresWindow.cpp @@ -48,11 +48,11 @@ windowDimensionToPixels( const Calamares::Branding::WindowDimension& u ) } if ( u.unit() == Calamares::Branding::WindowDimensionUnit::Pixies ) { - return u.value(); + return static_cast< int >( u.value() ); } if ( u.unit() == Calamares::Branding::WindowDimensionUnit::Fonties ) { - return u.value() * CalamaresUtils::defaultFontHeight(); + return static_cast< int >( u.value() * CalamaresUtils::defaultFontHeight() ); } return 0; } diff --git a/src/libcalamares/utils/CommandList.cpp b/src/libcalamares/utils/CommandList.cpp index 85b4cd1e3..1a3075a43 100644 --- a/src/libcalamares/utils/CommandList.cpp +++ b/src/libcalamares/utils/CommandList.cpp @@ -36,7 +36,7 @@ static CommandLine get_variant_object( const QVariantMap& m ) { QString command = CalamaresUtils::getString( m, "command" ); - int timeout = CalamaresUtils::getInteger( m, "timeout", -1 ); + qint64 timeout = CalamaresUtils::getInteger( m, "timeout", -1 ); if ( !command.isEmpty() ) { diff --git a/src/modules/contextualprocess/ContextualProcessJob.cpp b/src/modules/contextualprocess/ContextualProcessJob.cpp index 1be4950c9..c65261b23 100644 --- a/src/modules/contextualprocess/ContextualProcessJob.cpp +++ b/src/modules/contextualprocess/ContextualProcessJob.cpp @@ -152,7 +152,7 @@ void ContextualProcessJob::setConfigurationMap( const QVariantMap& configurationMap ) { bool dontChroot = CalamaresUtils::getBool( configurationMap, "dontChroot", false ); - int timeout = CalamaresUtils::getInteger( configurationMap, "timeout", 10 ); + qint64 timeout = CalamaresUtils::getInteger( configurationMap, "timeout", 10 ); if ( timeout < 1 ) { timeout = 10; diff --git a/src/modules/shellprocess/ShellProcessJob.cpp b/src/modules/shellprocess/ShellProcessJob.cpp index 59d37d34b..ff73e83af 100644 --- a/src/modules/shellprocess/ShellProcessJob.cpp +++ b/src/modules/shellprocess/ShellProcessJob.cpp @@ -69,7 +69,7 @@ void ShellProcessJob::setConfigurationMap( const QVariantMap& configurationMap ) { bool dontChroot = CalamaresUtils::getBool( configurationMap, "dontChroot", false ); - int timeout = CalamaresUtils::getInteger( configurationMap, "timeout", 10 ); + qint64 timeout = CalamaresUtils::getInteger( configurationMap, "timeout", 10 ); if ( timeout < 1 ) { timeout = 10; From dbe0ccf2e14bcd75c86ab83de2c7300a27a3b3b1 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 21 Aug 2019 11:58:58 +0200 Subject: [PATCH 243/302] [calamares] Apply coding style --- src/calamares/progresstree/ProgressTreeView.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/calamares/progresstree/ProgressTreeView.cpp b/src/calamares/progresstree/ProgressTreeView.cpp index 5c81e3851..d4f652363 100644 --- a/src/calamares/progresstree/ProgressTreeView.cpp +++ b/src/calamares/progresstree/ProgressTreeView.cpp @@ -76,9 +76,10 @@ ProgressTreeView::setModel( QAbstractItemModel* model ) QTreeView::setModel( model ); expandAll(); - connect( Calamares::ViewManager::instance(), - &Calamares::ViewManager::currentStepChanged, - this, - [this]() { viewport()->update(); }, - Qt::UniqueConnection ); + connect( + Calamares::ViewManager::instance(), + &Calamares::ViewManager::currentStepChanged, + this, + [this]() { viewport()->update(); }, + Qt::UniqueConnection ); } From 85f541073558b3e206b742ccc97cfa1e4745cd72 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 21 Aug 2019 12:00:26 +0200 Subject: [PATCH 244/302] [libcalamaresui] Apply coding style --- src/libcalamaresui/Branding.cpp | 120 ++++++++++++---------- src/libcalamaresui/viewpages/ViewStep.cpp | 8 +- 2 files changed, 74 insertions(+), 54 deletions(-) diff --git a/src/libcalamaresui/Branding.cpp b/src/libcalamaresui/Branding.cpp index 98dbab06c..c0ee71089 100644 --- a/src/libcalamaresui/Branding.cpp +++ b/src/libcalamaresui/Branding.cpp @@ -87,7 +87,7 @@ const QStringList Branding::s_styleEntryStrings = // clang-format on // *INDENT-ON* -const NamedEnumTable& +const NamedEnumTable< Branding::WindowDimensionUnit >& Branding::WindowDimension::suffixes() { using Unit = Branding::WindowDimensionUnit; @@ -110,16 +110,23 @@ Branding::WindowDimension::suffixes() * the @p transform function, which may change strings. */ static void -loadStrings( QMap& map, const YAML::Node& doc, const std::string& key, const std::function< QString(const QString&) >& transform ) +loadStrings( QMap< QString, QString >& map, + const YAML::Node& doc, + const std::string& key, + const std::function< QString( const QString& ) >& transform ) { if ( !doc[ key ].IsMap() ) - throw YAML::Exception( YAML::Mark(), std::string("Branding configuration is not a map: ") + key ); + { + throw YAML::Exception( YAML::Mark(), std::string( "Branding configuration is not a map: " ) + key ); + } const auto& config = CalamaresUtils::yamlMapToVariant( doc[ key ] ).toMap(); map.clear(); for ( auto it = config.constBegin(); it != config.constEnd(); ++it ) + { map.insert( it.key(), transform( it.value().toString() ) ); + } } /** @brief Load the @p map with strings from @p config @@ -129,8 +136,7 @@ loadStrings( QMap& map, const YAML::Node& doc, const std::stri * documentation for details. */ -Branding::Branding( const QString& brandingFilePath, - QObject* parent ) +Branding::Branding( const QString& brandingFilePath, QObject* parent ) : QObject( parent ) , m_descriptorPath( brandingFilePath ) , m_slideshowAPI( 1 ) @@ -141,7 +147,9 @@ Branding::Branding( const QString& brandingFilePath, QDir componentDir( componentDirectory() ); if ( !componentDir.exists() ) + { bail( "Bad component directory path." ); + } QFile file( brandingFilePath ); if ( file.exists() && file.open( QFile::ReadOnly | QFile::Text ) ) @@ -153,8 +161,7 @@ Branding::Branding( const QString& brandingFilePath, YAML::Node doc = YAML::Load( ba.constData() ); Q_ASSERT( doc.IsMap() ); - m_componentName = QString::fromStdString( doc[ "componentName" ] - .as< std::string >() ); + m_componentName = QString::fromStdString( doc[ "componentName" ].as< std::string >() ); if ( m_componentName != componentDir.dirName() ) bail( "The branding component name should match the name of the " "component directory." ); @@ -165,8 +172,7 @@ Branding::Branding( const QString& brandingFilePath, // Copy the os-release information into a QHash for use by KMacroExpander. KOSRelease relInfo; - QHash< QString, QString > relMap{ - std::initializer_list< std::pair< QString, QString > > { + QHash< QString, QString > relMap { std::initializer_list< std::pair< QString, QString > > { { QStringLiteral( "NAME" ), relInfo.name() }, { QStringLiteral( "VERSION" ), relInfo.version() }, { QStringLiteral( "ID" ), relInfo.id() }, @@ -182,9 +188,10 @@ Branding::Branding( const QString& brandingFilePath, { QStringLiteral( "BUILD_ID" ), relInfo.buildId() }, { QStringLiteral( "VARIANT" ), relInfo.variant() }, { QStringLiteral( "VARIANT_ID" ), relInfo.variantId() }, - { QStringLiteral( "LOGO" ), relInfo.logo() } - } }; - auto expand = [&]( const QString& s ) -> QString { return KMacroExpander::expandMacros( s, relMap, QLatin1Char( '@' ) ); }; + { QStringLiteral( "LOGO" ), relInfo.logo() } } }; + auto expand = [&]( const QString& s ) -> QString { + return KMacroExpander::expandMacros( s, relMap, QLatin1Char( '@' ) ); + }; #else auto expand = []( const QString& s ) -> QString { return s; }; #endif @@ -192,26 +199,23 @@ Branding::Branding( const QString& brandingFilePath, // Massage the strings, images and style sections. loadStrings( m_strings, doc, "strings", expand ); - loadStrings( m_images, doc, "images", - [&]( const QString& s ) -> QString + loadStrings( m_images, doc, "images", [&]( const QString& s ) -> QString { + // See also image() + const QString imageName( expand( s ) ); + QFileInfo imageFi( componentDir.absoluteFilePath( imageName ) ); + if ( !imageFi.exists() ) { - // See also image() - const QString imageName( expand( s ) ); - QFileInfo imageFi( componentDir.absoluteFilePath( imageName ) ); - if ( !imageFi.exists() ) + const auto icon = QIcon::fromTheme( imageName ); + // Not found, bail out with the filename used + if ( icon.isNull() ) { - const auto icon = QIcon::fromTheme( imageName ); - // Not found, bail out with the filename used - if ( icon.isNull() ) - bail( QString( "Image file %1 does not exist." ).arg( imageFi.absoluteFilePath() ) ); - return imageName; // Not turned into a path + bail( QString( "Image file %1 does not exist." ).arg( imageFi.absoluteFilePath() ) ); } - return imageFi.absoluteFilePath(); + return imageName; // Not turned into a path } - ); - loadStrings( m_style, doc, "style", - []( const QString& s ) -> QString { return s; } - ); + return imageFi.absoluteFilePath(); + } ); + loadStrings( m_style, doc, "style", []( const QString& s ) -> QString { return s; } ); if ( doc[ "slideshow" ].IsSequence() ) { @@ -222,8 +226,7 @@ Branding::Branding( const QString& brandingFilePath, QString pathString = slideShowPictures[ i ]; QFileInfo imageFi( componentDir.absoluteFilePath( pathString ) ); if ( !imageFi.exists() ) - bail( QString( "Slideshow file %1 does not exist." ) - .arg( imageFi.absoluteFilePath() ) ); + bail( QString( "Slideshow file %1 does not exist." ).arg( imageFi.absoluteFilePath() ) ); slideShowPictures[ i ] = imageFi.absoluteFilePath(); } @@ -232,19 +235,19 @@ Branding::Branding( const QString& brandingFilePath, } else if ( doc[ "slideshow" ].IsScalar() ) { - QString slideshowPath = QString::fromStdString( doc[ "slideshow" ] - .as< std::string >() ); + QString slideshowPath = QString::fromStdString( doc[ "slideshow" ].as< std::string >() ); QFileInfo slideshowFi( componentDir.absoluteFilePath( slideshowPath ) ); - if ( !slideshowFi.exists() || - !slideshowFi.fileName().toLower().endsWith( ".qml" ) ) + if ( !slideshowFi.exists() || !slideshowFi.fileName().toLower().endsWith( ".qml" ) ) bail( QString( "Slideshow file %1 does not exist or is not a valid QML file." ) - .arg( slideshowFi.absoluteFilePath() ) ); + .arg( slideshowFi.absoluteFilePath() ) ); m_slideshowPath = slideshowFi.absoluteFilePath(); } else + { bail( "Syntax error in slideshow sequence." ); + } - int api = doc[ "slideshowAPI" ].IsScalar() ? doc[ "slideshowAPI" ].as() : -1; + int api = doc[ "slideshowAPI" ].IsScalar() ? doc[ "slideshowAPI" ].as< int >() : -1; if ( ( api < 1 ) || ( api > 2 ) ) { cWarning() << "Invalid or missing *slideshowAPI* in branding file."; @@ -260,11 +263,11 @@ Branding::Branding( const QString& brandingFilePath, QDir translationsDir( componentDir.filePath( "lang" ) ); if ( !translationsDir.exists() ) + { cWarning() << "the branding component" << componentDir.absolutePath() << "does not ship translations."; + } m_translationsPathPrefix = translationsDir.absolutePath(); - m_translationsPathPrefix.append( QString( "%1calamares-%2" ) - .arg( QDir::separator() ) - .arg( m_componentName ) ); + m_translationsPathPrefix.append( QString( "%1calamares-%2" ).arg( QDir::separator() ).arg( m_componentName ) ); } else { @@ -286,7 +289,7 @@ Branding::Branding( const QString& brandingFilePath, QString Branding::componentDirectory() const { - QFileInfo fi ( m_descriptorPath ); + QFileInfo fi( m_descriptorPath ); return fi.absoluteDir().absolutePath(); } @@ -325,7 +328,7 @@ Branding::image( Branding::ImageEntry imageEntry, const QSize& size ) const } else { - auto icon = QIcon::fromTheme(path); + auto icon = QIcon::fromTheme( path ); Q_ASSERT( !icon.isNull() ); return icon.pixmap( size ); @@ -333,7 +336,7 @@ Branding::image( Branding::ImageEntry imageEntry, const QSize& size ) const } QPixmap -Branding::image(const QString& imageName, const QSize& size) const +Branding::image( const QString& imageName, const QSize& size ) const { QDir componentDir( componentDirectory() ); QFileInfo imageFi( componentDir.absoluteFilePath( imageName ) ); @@ -342,7 +345,9 @@ Branding::image(const QString& imageName, const QSize& size) const const auto icon = QIcon::fromTheme( imageName ); // Not found, bail out with the filename used if ( icon.isNull() ) + { return QPixmap(); + } return icon.pixmap( size ); } return ImageRegistry::instance()->pixmap( imageFi.absoluteFilePath(), size ); @@ -360,7 +365,9 @@ Branding::stylesheet() const return stylesheetFile.readAll(); } else + { cWarning() << "The branding component" << fi.absoluteDir().absolutePath() << "does not ship stylesheet.qss."; + } return QString(); } @@ -369,7 +376,9 @@ Branding::setGlobals( GlobalStorage* globalStorage ) const { QVariantMap brandingMap; for ( const QString& key : s_stringEntryStrings ) + { brandingMap.insert( key, m_strings.value( key ) ); + } globalStorage->insert( "branding", brandingMap ); } @@ -384,15 +393,17 @@ Branding::WindowDimension::isValid() const static inline QString getString( const YAML::Node& doc, const char* key ) { - if ( doc[key] ) - return QString::fromStdString( doc[key].as< std::string >() ); + if ( doc[ key ] ) + { + return QString::fromStdString( doc[ key ].as< std::string >() ); + } return QString(); } void Branding::initSimpleSettings( const YAML::Node& doc ) { - static const NamedEnumTable< WindowExpansion > expansionNames{ + static const NamedEnumTable< WindowExpansion > expansionNames { { QStringLiteral( "normal" ), WindowExpansion::Normal }, { QStringLiteral( "fullscreen" ), WindowExpansion::Fullscreen }, { QStringLiteral( "noexpand" ), WindowExpansion::Fixed } @@ -403,7 +414,10 @@ Branding::initSimpleSettings( const YAML::Node& doc ) m_welcomeExpandingLogo = doc[ "welcomeExpandingLogo" ].as< bool >( true ); m_windowExpansion = expansionNames.find( getString( doc, "windowExpanding" ), ok ); if ( !ok ) - cWarning() << "Branding module-setting *windowExpanding* interpreted as" << expansionNames.find( m_windowExpansion, ok ); + { + cWarning() << "Branding module-setting *windowExpanding* interpreted as" + << expansionNames.find( m_windowExpansion, ok ); + } QString windowSize = getString( doc, "windowSize" ); if ( !windowSize.isEmpty() ) @@ -411,24 +425,26 @@ Branding::initSimpleSettings( const YAML::Node& doc ) auto l = windowSize.split( ',' ); if ( l.count() == 2 ) { - m_windowWidth = WindowDimension( l[0] ); - m_windowHeight = WindowDimension( l[1] ); + m_windowWidth = WindowDimension( l[ 0 ] ); + m_windowHeight = WindowDimension( l[ 1 ] ); } } if ( !m_windowWidth.isValid() ) + { m_windowWidth = WindowDimension( CalamaresUtils::windowPreferredWidth, WindowDimensionUnit::Pixies ); + } if ( !m_windowHeight.isValid() ) + { m_windowHeight = WindowDimension( CalamaresUtils::windowPreferredHeight, WindowDimensionUnit::Pixies ); + } } [[noreturn]] void Branding::bail( const QString& message ) { - cError() << "FATAL in" - << m_descriptorPath - << "\n" + message; + cError() << "FATAL in" << m_descriptorPath << "\n" + message; ::exit( EXIT_FAILURE ); } -} +} // namespace Calamares diff --git a/src/libcalamaresui/viewpages/ViewStep.cpp b/src/libcalamaresui/viewpages/ViewStep.cpp index af1e347eb..7fe7ff88d 100644 --- a/src/libcalamaresui/viewpages/ViewStep.cpp +++ b/src/libcalamaresui/viewpages/ViewStep.cpp @@ -73,10 +73,14 @@ ViewStep::setModuleInstanceKey( const QString& instanceKey ) void -ViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { Q_UNUSED( configurationMap ) } +ViewStep::setConfigurationMap( const QVariantMap& configurationMap ) +{ + Q_UNUSED( configurationMap ) +} -RequirementsList ViewStep::checkRequirements() +RequirementsList +ViewStep::checkRequirements() { return RequirementsList(); } From 9aae9b2f02ba92d94864b1162c294085994ae52b Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 22 Aug 2019 10:26:15 +0200 Subject: [PATCH 245/302] [libcalamares] Restore Q_DELCARE_INTERFACE - This **may** be the cause of build failures on aarch64. --- src/libcalamares/utils/PluginFactory.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcalamares/utils/PluginFactory.h b/src/libcalamares/utils/PluginFactory.h index e8236a888..d60e84b6f 100644 --- a/src/libcalamares/utils/PluginFactory.h +++ b/src/libcalamares/utils/PluginFactory.h @@ -102,6 +102,6 @@ public: K_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY( name, CalamaresPluginFactory, pluginRegistrations ) -// Q_DECLARE_INTERFACE( Calamares::PluginFactory, CalamaresPluginFactory_iid ) +Q_DECLARE_INTERFACE( Calamares::PluginFactory, CalamaresPluginFactory_iid ) #endif From 0b2855d6e092822b13d3821b91f017cc5879ee20 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 22 Aug 2019 10:29:39 +0200 Subject: [PATCH 246/302] [libcalamares] Fix build (bad class name) --- src/libcalamares/utils/PluginFactory.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcalamares/utils/PluginFactory.h b/src/libcalamares/utils/PluginFactory.h index d60e84b6f..57ef44fb7 100644 --- a/src/libcalamares/utils/PluginFactory.h +++ b/src/libcalamares/utils/PluginFactory.h @@ -102,6 +102,6 @@ public: K_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY( name, CalamaresPluginFactory, pluginRegistrations ) -Q_DECLARE_INTERFACE( Calamares::PluginFactory, CalamaresPluginFactory_iid ) +Q_DECLARE_INTERFACE( CalamaresPluginFactory, CalamaresPluginFactory_iid ) #endif From 8ea1ea666237de767eddd09bc5596b719589d733 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 22 Aug 2019 16:03:21 +0200 Subject: [PATCH 247/302] [libcalamares] Add synchronousGet() to network service - Synchronous download of a given URL; not something to do from the GUI thread. - Use it from the GeoIP service, which downloads in a separate thread to do GeoIP lookups. - Drop now-unused headers. - Adjust tests for GeoIP to use network service --- src/libcalamares/geoip/GeoIPTests.cpp | 26 +++----------------------- src/libcalamares/geoip/Handler.cpp | 25 +++---------------------- src/libcalamares/network/Manager.cpp | 18 ++++++++++++++++++ src/libcalamares/network/Manager.h | 8 ++++++++ 4 files changed, 32 insertions(+), 45 deletions(-) diff --git a/src/libcalamares/geoip/GeoIPTests.cpp b/src/libcalamares/geoip/GeoIPTests.cpp index c24b6d98f..3400bb24f 100644 --- a/src/libcalamares/geoip/GeoIPTests.cpp +++ b/src/libcalamares/geoip/GeoIPTests.cpp @@ -24,9 +24,7 @@ #endif #include "Handler.h" -#include -#include -#include +#include "network/Manager.h" #include @@ -197,27 +195,9 @@ GeoIPTests::testSplitTZ() } -static QByteArray -synchronous_get( const char* urlstring ) -{ - QUrl url( urlstring ); - QNetworkAccessManager manager; - QEventLoop loop; - - qDebug() << "Fetching" << url; - - QObject::connect( &manager, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit ); - - QNetworkRequest request( url ); - QNetworkReply* reply = manager.get( request ); - loop.exec(); - reply->deleteLater(); - return reply->readAll(); -} - #define CHECK_GET( t, selector, url ) \ { \ - auto tz = GeoIP##t( selector ).processReply( synchronous_get( url ) ); \ + auto tz = GeoIP##t( selector ).processReply( CalamaresUtils::Network::Manager::instance().synchronousGet( QUrl( url ) ) ); \ qDebug() << tz; \ QCOMPARE( default_tz, tz ); \ auto tz2 = CalamaresUtils::GeoIP::Handler( "" #t, url, selector ).get(); \ @@ -236,7 +216,7 @@ GeoIPTests::testGet() GeoIPJSON default_handler; // Call the KDE service the definitive source. - auto default_tz = default_handler.processReply( synchronous_get( "https://geoip.kde.org/v1/calamares" ) ); + auto default_tz = default_handler.processReply( CalamaresUtils::Network::Manager::instance().synchronousGet( QUrl( "https://geoip.kde.org/v1/calamares" ) ) ); // This is bogus, because the test isn't always run by me // QCOMPARE( default_tz.first, QStringLiteral("Europe") ); diff --git a/src/libcalamares/geoip/Handler.cpp b/src/libcalamares/geoip/Handler.cpp index 6017c404f..99e55e926 100644 --- a/src/libcalamares/geoip/Handler.cpp +++ b/src/libcalamares/geoip/Handler.cpp @@ -23,14 +23,11 @@ #include "GeoIPXML.h" #endif +#include "network/Manager.h" #include "utils/Logger.h" #include "utils/NamedEnum.h" #include "utils/Variant.h" -#include -#include -#include - #include static const NamedEnumTable< CalamaresUtils::GeoIP::Handler::Type >& @@ -87,22 +84,6 @@ Handler::Handler( const QString& implementation, const QString& url, const QStri Handler::~Handler() {} -static QByteArray -synchronous_get( const QString& urlstring ) -{ - QUrl url( urlstring ); - QNetworkAccessManager manager; - QEventLoop loop; - - QObject::connect( &manager, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit ); - - QNetworkRequest request( url ); - QNetworkReply* reply = manager.get( request ); - loop.exec(); - reply->deleteLater(); - return reply->readAll(); -} - static std::unique_ptr< Interface > create_interface( Handler::Type t, const QString& selector ) { @@ -131,7 +112,7 @@ do_query( Handler::Type type, const QString& url, const QString& selector ) return RegionZonePair(); } - return interface->processReply( synchronous_get( url ) ); + return interface->processReply( CalamaresUtils::Network::Manager::instance().synchronousGet( url ) ); } static QString @@ -143,7 +124,7 @@ do_raw_query( Handler::Type type, const QString& url, const QString& selector ) return QString(); } - return interface->rawReply( synchronous_get( url ) ); + return interface->rawReply( CalamaresUtils::Network::Manager::instance().synchronousGet( url ) ); } RegionZonePair diff --git a/src/libcalamares/network/Manager.cpp b/src/libcalamares/network/Manager.cpp index b0c068c6e..c98863835 100644 --- a/src/libcalamares/network/Manager.cpp +++ b/src/libcalamares/network/Manager.cpp @@ -95,5 +95,23 @@ CalamaresUtils::Network::Manager::synchronousPing( const QUrl& url ) QEventLoop loop; connect( reply, &QNetworkReply::finished, &loop, &QEventLoop::quit ); loop.exec(); + reply->deleteLater(); return reply->bytesAvailable(); } + +QByteArray +CalamaresUtils::Network::Manager::synchronousGet( const QUrl& url ) +{ + if ( !url.isValid() ) + { + return QByteArray(); + } + + QNetworkRequest request( url ); + QNetworkReply* reply = d->m_nam->get( request ); + QEventLoop loop; + connect( reply, &QNetworkReply::finished, &loop, &QEventLoop::quit ); + loop.exec(); + reply->deleteLater(); + return reply->readAll(); +} diff --git a/src/libcalamares/network/Manager.h b/src/libcalamares/network/Manager.h index f357d8d70..1c965d27e 100644 --- a/src/libcalamares/network/Manager.h +++ b/src/libcalamares/network/Manager.h @@ -21,6 +21,7 @@ #include "DllMacro.h" +#include #include #include @@ -52,6 +53,13 @@ public: */ bool synchronousPing( const QUrl& url ); + /** @brief Downloads the data from a given @p url + * + * Returns the data as a QByteArray, or an empty + * array if any error occurred. + */ + QByteArray synchronousGet( const QUrl& url ); + /// @brief Set the URL which is used for the general "is there internet" check. void setCheckHasInternetUrl( const QUrl& url ); /** @brief Do an explicit check for internet connectivity. From b8bad1c0b4b25c20b4254e4d292ec1c6639d5acf Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 22 Aug 2019 16:16:29 +0200 Subject: [PATCH 248/302] [welcome] Drop unused includes --- src/modules/welcome/checker/GeneralRequirements.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/modules/welcome/checker/GeneralRequirements.cpp b/src/modules/welcome/checker/GeneralRequirements.cpp index 4787fe51d..1881558b8 100644 --- a/src/modules/welcome/checker/GeneralRequirements.cpp +++ b/src/modules/welcome/checker/GeneralRequirements.cpp @@ -44,13 +44,9 @@ #include #include #include -#include #include #include #include -#include -#include -#include #include #include From b66f3434af597c990feb4370ce1b488156a501bc Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 23 Aug 2019 03:09:53 -0400 Subject: [PATCH 249/302] [displaymanager] Consistent Copyright notices --- src/modules/displaymanager/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index 639edbea7..0b644dd4b 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -3,13 +3,13 @@ # # === This file is part of Calamares - === # -# Copyright 2019 Dominic Hayes # Copyright 2014-2018, Philip Müller # Copyright 2014-2015, Teo Mrnjavac # Copyright 2014, Kevin Kofler # Copyright 2017, Alf Gaida # Copyright 2017, Bernhard Landauer # Copyright 2017, Adriaan de Groot +# Copyright 2019, Dominic Hayes # # Calamares is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by From 333a1f6e840c43324665027b5dd91cba038a3760 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 23 Aug 2019 03:12:48 -0400 Subject: [PATCH 250/302] [displaymanager] Non-existent DMs don't exist - Returning True for a non-existent DM is weird - Avoid suggestive parenthesis in return type --- src/modules/displaymanager/main.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index 0b644dd4b..9cb7b088e 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -8,7 +8,7 @@ # Copyright 2014, Kevin Kofler # Copyright 2017, Alf Gaida # Copyright 2017, Bernhard Landauer -# Copyright 2017, Adriaan de Groot +# Copyright 2017, 2019, Adriaan de Groot # Copyright 2019, Dominic Hayes # # Calamares is free software: you can redistribute it and/or modify @@ -117,14 +117,11 @@ class DisplayManager(metaclass=abc.ABCMeta): in the target system. """ if self.executable is None: - return True + return False bin_path = "{!s}/usr/bin/{!s}".format(self.root_mount_point, self.executable) sbin_path = "{!s}/usr/sbin/{!s}".format(self.root_mount_point, self.executable) - return ( - os.path.exists(bin_path) - or os.path.exists(sbin_path) - ) + return os.path.exists(bin_path) or os.path.exists(sbin_path) # The four abstract methods below are called in the order listed here. # They must all be implemented by subclasses, but not all of them From 1c61181624893a6d1e2d1d876281c7319d4372a2 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 23 Aug 2019 03:25:41 -0400 Subject: [PATCH 251/302] [displaymanager] Handle variations in GDM executable name - Debian https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=934504 - Instead of hard-coding one or the other, search for gdm and gdm3 --- src/modules/displaymanager/main.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index 9cb7b088e..1fcafb58b 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -249,6 +249,21 @@ class DMgdm(DisplayManager): name = "gdm" executable = "gdm" + def have_dm(self): + """ + GDM exists with different executable names, so search + for one of them and use it. + """ + for executable in ( "gdm", "gdm3" ): + bin_path = "{!s}/usr/bin/{!s}".format(self.root_mount_point, executable) + sbin_path = "{!s}/usr/sbin/{!s}".format(self.root_mount_point, executable) + if os.path.exists(bin_path) or os.path.exists(sbin_path): + # Keep the found-executable name around for later + self.executable = executable + return True + + return False + def set_autologin(self, username, do_autologin, default_desktop_environment): # Systems with GDM as Desktop Manager gdm_conf_path = os.path.join(self.root_mount_point, "etc/gdm/custom.conf") From 383bd97a9cfde98f3a0a0bac30197b00064b8987 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 23 Aug 2019 03:40:10 -0400 Subject: [PATCH 252/302] [displaymanager] Handle variations in config file - GDM3 uses a different config file than previous GDM --- src/modules/displaymanager/main.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index 1fcafb58b..f85a8aecc 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -248,25 +248,33 @@ class DMmdm(DisplayManager): class DMgdm(DisplayManager): name = "gdm" executable = "gdm" + config = None # Set by have_dm() def have_dm(self): """ GDM exists with different executable names, so search for one of them and use it. """ - for executable in ( "gdm", "gdm3" ): + for executable, config in ( + ( "gdm", "etc/gdm/custom.conf" ), + ( "gdm3", "etc/gdm3/daemon.conf" ) + ): bin_path = "{!s}/usr/bin/{!s}".format(self.root_mount_point, executable) sbin_path = "{!s}/usr/sbin/{!s}".format(self.root_mount_point, executable) if os.path.exists(bin_path) or os.path.exists(sbin_path): # Keep the found-executable name around for later self.executable = executable + self.config = config return True return False def set_autologin(self, username, do_autologin, default_desktop_environment): + if self.config is None: + raise ValueError( "No config file for GDM has been set." ) + # Systems with GDM as Desktop Manager - gdm_conf_path = os.path.join(self.root_mount_point, "etc/gdm/custom.conf") + gdm_conf_path = os.path.join(self.root_mount_point, self.config) if os.path.exists(gdm_conf_path): with open(gdm_conf_path, 'r') as gdm_conf: From af1aa701bc2c22b79049c8ba44dfc4b417c2cbf5 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 23 Aug 2019 12:09:30 +0200 Subject: [PATCH 253/302] [libcalamares] Shuffle namespace lines around - put all the definitions inside namespace {} to avoid needlessly long source lines. --- src/libcalamares/network/Manager.cpp | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/libcalamares/network/Manager.cpp b/src/libcalamares/network/Manager.cpp index c98863835..66721c812 100644 --- a/src/libcalamares/network/Manager.cpp +++ b/src/libcalamares/network/Manager.cpp @@ -35,36 +35,35 @@ struct Manager::Private Private(); }; -} // namespace Network -} // namespace CalamaresUtils -CalamaresUtils::Network::Manager::Private::Private() + +Manager::Private::Private() : m_nam( std::make_unique< QNetworkAccessManager >() ) , m_hasInternet( false ) { } -CalamaresUtils::Network::Manager::Manager() +Manager::Manager() : d( std::make_unique< Private >() ) { } -CalamaresUtils::Network::Manager::~Manager() {} +Manager::~Manager() {} -CalamaresUtils::Network::Manager& -CalamaresUtils::Network::Manager::instance() +Manager& +Manager::instance() { - static auto* s_manager = new CalamaresUtils::Network::Manager(); + static auto* s_manager = new Manager(); return *s_manager; } bool -CalamaresUtils::Network::Manager::hasInternet() +Manager::hasInternet() { return d->m_hasInternet; } bool -CalamaresUtils::Network::Manager::checkHasInternet() +Manager::checkHasInternet() { bool hasInternet = d->m_nam->networkAccessible() == QNetworkAccessManager::Accessible; @@ -77,13 +76,13 @@ CalamaresUtils::Network::Manager::checkHasInternet() } void -CalamaresUtils::Network::Manager::setCheckHasInternetUrl( const QUrl& url ) +Manager::setCheckHasInternetUrl( const QUrl& url ) { d->m_hasInternetUrl = url; } bool -CalamaresUtils::Network::Manager::synchronousPing( const QUrl& url ) +Manager::synchronousPing( const QUrl& url ) { if ( !url.isValid() ) { @@ -100,7 +99,7 @@ CalamaresUtils::Network::Manager::synchronousPing( const QUrl& url ) } QByteArray -CalamaresUtils::Network::Manager::synchronousGet( const QUrl& url ) +Manager::synchronousGet( const QUrl& url ) { if ( !url.isValid() ) { @@ -115,3 +114,6 @@ CalamaresUtils::Network::Manager::synchronousGet( const QUrl& url ) reply->deleteLater(); return reply->readAll(); } + +} // namespace Network +} // namespace CalamaresUtils From 1f2b3b734d683e1ed2f89bc575179703dae0eec0 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 23 Aug 2019 12:18:59 +0200 Subject: [PATCH 254/302] [libcalamares] Extend synchronous API with options --- src/libcalamares/network/Manager.cpp | 27 +++++++++++++++++--- src/libcalamares/network/Manager.h | 38 ++++++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/src/libcalamares/network/Manager.cpp b/src/libcalamares/network/Manager.cpp index 66721c812..857a93b69 100644 --- a/src/libcalamares/network/Manager.cpp +++ b/src/libcalamares/network/Manager.cpp @@ -27,6 +27,23 @@ namespace CalamaresUtils { namespace Network { +void +RequestOptions::applyToRequest( QNetworkRequest* request ) const +{ + if ( m_flags & Flag::FollowRedirect ) + { + // Follows all redirects except unsafe ones (https to http). + request->setAttribute( QNetworkRequest::FollowRedirectsAttribute, true ); + } + + if ( m_flags & Flag::FakeUserAgent ) + { + // Not everybody likes the default User Agent used by this class (looking at you, + // sourceforge.net), so let's set a more descriptive one. + request->setRawHeader( "User-Agent", "Mozilla/5.0 (compatible; Calamares)" ); + } +} + struct Manager::Private { std::unique_ptr< QNetworkAccessManager > m_nam; @@ -82,16 +99,17 @@ Manager::setCheckHasInternetUrl( const QUrl& url ) } bool -Manager::synchronousPing( const QUrl& url ) +Manager::synchronousPing( const QUrl& url, const RequestOptions& options ) { if ( !url.isValid() ) { return false; } - QNetworkRequest req = QNetworkRequest( url ); - QNetworkReply* reply = d->m_nam->get( req ); + QNetworkRequest request = QNetworkRequest( url ); + QNetworkReply* reply = d->m_nam->get( request ); QEventLoop loop; + options.applyToRequest( &request ); connect( reply, &QNetworkReply::finished, &loop, &QEventLoop::quit ); loop.exec(); reply->deleteLater(); @@ -99,7 +117,7 @@ Manager::synchronousPing( const QUrl& url ) } QByteArray -Manager::synchronousGet( const QUrl& url ) +Manager::synchronousGet( const QUrl& url, const RequestOptions& options ) { if ( !url.isValid() ) { @@ -109,6 +127,7 @@ Manager::synchronousGet( const QUrl& url ) QNetworkRequest request( url ); QNetworkReply* reply = d->m_nam->get( request ); QEventLoop loop; + options.applyToRequest( &request ); connect( reply, &QNetworkReply::finished, &loop, &QEventLoop::quit ); loop.exec(); reply->deleteLater(); diff --git a/src/libcalamares/network/Manager.h b/src/libcalamares/network/Manager.h index 1c965d27e..7f12925ef 100644 --- a/src/libcalamares/network/Manager.h +++ b/src/libcalamares/network/Manager.h @@ -25,12 +25,46 @@ #include #include +#include #include +class QNetworkRequest; + namespace CalamaresUtils { namespace Network { +class DLLEXPORT RequestOptions +{ +public: + enum Flag + { + FollowRedirect = 0x1, + FakeUserAgent = 0x100 + }; + Q_DECLARE_FLAGS( Flags, Flag ) + + RequestOptions() + : m_flags( 0 ) + , m_timeout( -1 ) + { + } + + RequestOptions( Flags f, std::chrono::milliseconds timeout = std::chrono::milliseconds( -1 ) ) + : m_flags( f ) + , m_timeout( timeout ) + { + } + + void applyToRequest( QNetworkRequest* ) const; + +private: + Flags m_flags; + std::chrono::milliseconds m_timeout; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS( RequestOptions::Flags ); + class DLLEXPORT Manager : QObject { Q_OBJECT @@ -51,14 +85,14 @@ public: * Returns @c true if it does; @c false means no data, typically * because of an error or no network access. */ - bool synchronousPing( const QUrl& url ); + bool synchronousPing( const QUrl& url, const RequestOptions& options = RequestOptions() ); /** @brief Downloads the data from a given @p url * * Returns the data as a QByteArray, or an empty * array if any error occurred. */ - QByteArray synchronousGet( const QUrl& url ); + QByteArray synchronousGet( const QUrl& url, const RequestOptions& options = RequestOptions() ); /// @brief Set the URL which is used for the general "is there internet" check. void setCheckHasInternetUrl( const QUrl& url ); From 85f0d386980b5aec0539a442cde608adfbc68107 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 23 Aug 2019 14:59:35 +0200 Subject: [PATCH 255/302] [libcalamares] Refactor synchronous get - Add timeout support - Refactor into a static helper method --- src/libcalamares/network/Manager.cpp | 39 ++++++++++++++++++---------- src/libcalamares/network/Manager.h | 9 +++++-- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/libcalamares/network/Manager.cpp b/src/libcalamares/network/Manager.cpp index 857a93b69..d5e27e611 100644 --- a/src/libcalamares/network/Manager.cpp +++ b/src/libcalamares/network/Manager.cpp @@ -22,6 +22,7 @@ #include #include #include +#include namespace CalamaresUtils { @@ -98,6 +99,28 @@ Manager::setCheckHasInternetUrl( const QUrl& url ) d->m_hasInternetUrl = url; } +static QNetworkReply* +synchronousRun( const std::unique_ptr< QNetworkAccessManager >& nam, const QUrl& url, const RequestOptions& options ) +{ + QNetworkRequest request = QNetworkRequest( url ); + QNetworkReply* reply = nam->get( request ); + QEventLoop loop; + QTimer timer; + + options.applyToRequest( &request ); + if ( options.hasTimeout() ) + { + timer.setSingleShot( true ); + QObject::connect( &timer, &QTimer::timeout, &loop, &QEventLoop::quit ); + timer.start( options.timeout() ); + } + + QObject::connect( reply, &QNetworkReply::finished, &loop, &QEventLoop::quit ); + loop.exec(); + reply->deleteLater(); + return reply; +} + bool Manager::synchronousPing( const QUrl& url, const RequestOptions& options ) { @@ -106,13 +129,7 @@ Manager::synchronousPing( const QUrl& url, const RequestOptions& options ) return false; } - QNetworkRequest request = QNetworkRequest( url ); - QNetworkReply* reply = d->m_nam->get( request ); - QEventLoop loop; - options.applyToRequest( &request ); - connect( reply, &QNetworkReply::finished, &loop, &QEventLoop::quit ); - loop.exec(); - reply->deleteLater(); + auto reply = synchronousRun( d->m_nam, url, options ); return reply->bytesAvailable(); } @@ -124,13 +141,7 @@ Manager::synchronousGet( const QUrl& url, const RequestOptions& options ) return QByteArray(); } - QNetworkRequest request( url ); - QNetworkReply* reply = d->m_nam->get( request ); - QEventLoop loop; - options.applyToRequest( &request ); - connect( reply, &QNetworkReply::finished, &loop, &QEventLoop::quit ); - loop.exec(); - reply->deleteLater(); + auto reply = synchronousRun( d->m_nam, url, options ); return reply->readAll(); } diff --git a/src/libcalamares/network/Manager.h b/src/libcalamares/network/Manager.h index 7f12925ef..fef75ffb8 100644 --- a/src/libcalamares/network/Manager.h +++ b/src/libcalamares/network/Manager.h @@ -37,6 +37,8 @@ namespace Network class DLLEXPORT RequestOptions { public: + using milliseconds = std::chrono::milliseconds; + enum Flag { FollowRedirect = 0x1, @@ -50,7 +52,7 @@ public: { } - RequestOptions( Flags f, std::chrono::milliseconds timeout = std::chrono::milliseconds( -1 ) ) + RequestOptions( Flags f, milliseconds timeout = milliseconds( -1 ) ) : m_flags( f ) , m_timeout( timeout ) { @@ -58,9 +60,12 @@ public: void applyToRequest( QNetworkRequest* ) const; + bool hasTimeout() const { return m_timeout > milliseconds( 0 ); } + auto timeout() const { return m_timeout; } + private: Flags m_flags; - std::chrono::milliseconds m_timeout; + milliseconds m_timeout; }; Q_DECLARE_OPERATORS_FOR_FLAGS( RequestOptions::Flags ); From d422c782ba2c638515422bf394d2d0160620558d Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 23 Aug 2019 17:15:51 +0200 Subject: [PATCH 256/302] [libcalamares] Correct include path - no need for the subdirectories, and this confuses MOC Reported-by: Jonathan Riddell Fix-by: Harald Sitter --- src/libcalamares/utils/PluginFactory.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcalamares/utils/PluginFactory.h b/src/libcalamares/utils/PluginFactory.h index 57ef44fb7..958a7858a 100644 --- a/src/libcalamares/utils/PluginFactory.h +++ b/src/libcalamares/utils/PluginFactory.h @@ -24,7 +24,7 @@ #ifndef UTILS_PLUGINFACTORY_H #define UTILS_PLUGINFACTORY_H -#include +#include #define CalamaresPluginFactory_iid "io.calamares.PluginFactory" From 0f6b2dbe2dd8766c3fb581fe0027467dc98255d8 Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Fri, 23 Aug 2019 17:26:45 +0200 Subject: [PATCH 257/302] [unpackfs] Enable to use "/" as a source If we don't have/need an image for the rootfs, we might want to configure the `/` directory as a source for unpackfs. Unfortunately, this raises an error: - unpackfs first creates a temporary directory - it then creates a subdirectory for each source, using the source path's basename - when the source is `/`, the basename is an empty string, therefore the module tries to create an already existing directory In order to prevent this error, we use the `os.makedirs` function with parameter `exist_ok=True` instead of `os.mkdir`. Signed-off-by: Arnaud Ferraris --- src/modules/unpackfs/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/unpackfs/main.py b/src/modules/unpackfs/main.py index e956dc070..90c258cd7 100644 --- a/src/modules/unpackfs/main.py +++ b/src/modules/unpackfs/main.py @@ -208,7 +208,7 @@ class UnpackOperation: imgbasename = os.path.splitext( os.path.basename(entry.source))[0] imgmountdir = os.path.join(source_mount_path, imgbasename) - os.mkdir(imgmountdir) + os.makedirs(imgmountdir, exist_ok=True) self.mount_image(entry, imgmountdir) From ededebbc6c399395e61351fb7ffc56fb1c8b96b7 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 24 Aug 2019 15:23:07 +0200 Subject: [PATCH 258/302] [libcalamares] Return reply early if the request is bad --- src/libcalamares/network/Manager.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libcalamares/network/Manager.cpp b/src/libcalamares/network/Manager.cpp index d5e27e611..b4e37d895 100644 --- a/src/libcalamares/network/Manager.cpp +++ b/src/libcalamares/network/Manager.cpp @@ -107,6 +107,12 @@ synchronousRun( const std::unique_ptr< QNetworkAccessManager >& nam, const QUrl& QEventLoop loop; QTimer timer; + if ( reply->error() ) + { + reply->deleteLater(); + return reply; + } + options.applyToRequest( &request ); if ( options.hasTimeout() ) { From 71828d82743419686beeb1273a91d3f46ed36efd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Sat, 24 Aug 2019 09:44:31 -0400 Subject: [PATCH 259/302] [officechooser] update text and pics --- .../officechooser/images/FreeOffice.jpg | Bin 66350 -> 71701 bytes .../officechooser/images/choose-office.jpg | Bin 55210 -> 37633 bytes src/modules/officechooser/officechooser.conf | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/officechooser/images/FreeOffice.jpg b/src/modules/officechooser/images/FreeOffice.jpg index a4337d2c2a8d477690694a941764d9b1adac208c..205d5abc3238424a01c53aad7bb4dfe5da072483 100644 GIT binary patch literal 71701 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

A)Ll0Q3-eWmBxsD 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 Yy=c1*F$IkN+5hjeJQSp;!M|4jFEhp_jQ{`u literal 66350 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

^T78p)c& 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 HDu4gk7p>5h diff --git a/src/modules/officechooser/images/choose-office.jpg b/src/modules/officechooser/images/choose-office.jpg index b960e0f6347afbc72b2b204120dea6aeac2f59dd..98526400d316cb13a010bb3eda5dca0f4287e3dd 100644 GIT binary patch literal 37633 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 GUHCslH)M+d literal 55210 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%0AO2Z|InMe$j(#C`Ml>Lh`E`b3 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 b^8(_J Date: Sat, 24 Aug 2019 16:29:13 -0400 Subject: [PATCH 260/302] [libcalamares] Disable Q_DELCARE_INTERFACE once more --- src/libcalamares/utils/PluginFactory.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcalamares/utils/PluginFactory.h b/src/libcalamares/utils/PluginFactory.h index 958a7858a..86fe1d4cf 100644 --- a/src/libcalamares/utils/PluginFactory.h +++ b/src/libcalamares/utils/PluginFactory.h @@ -102,6 +102,6 @@ public: K_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY( name, CalamaresPluginFactory, pluginRegistrations ) -Q_DECLARE_INTERFACE( CalamaresPluginFactory, CalamaresPluginFactory_iid ) +// Q_DECLARE_INTERFACE( CalamaresPluginFactory, CalamaresPluginFactory_iid ) #endif From 87ea14f68abf0a04189f8f91f0e7ffa926334f5c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 26 Aug 2019 10:15:22 +0200 Subject: [PATCH 261/302] [libcalamares] Drop INTERFACES again - The compile failure came from bad #include paths, so restoring this interface declaration wasn't a fix. - Reported to cause runtime failures on both KaOS and Manjaro. --- src/libcalamares/utils/PluginFactory.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/libcalamares/utils/PluginFactory.h b/src/libcalamares/utils/PluginFactory.h index 958a7858a..65ee6eee9 100644 --- a/src/libcalamares/utils/PluginFactory.h +++ b/src/libcalamares/utils/PluginFactory.h @@ -101,7 +101,4 @@ public: #define CALAMARES_PLUGIN_FACTORY_DEFINITION( name, pluginRegistrations ) \ K_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY( name, CalamaresPluginFactory, pluginRegistrations ) - -Q_DECLARE_INTERFACE( CalamaresPluginFactory, CalamaresPluginFactory_iid ) - #endif From f0be7fd4aa01ff9247ab1413ffaff973902d92b3 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 26 Aug 2019 14:43:41 +0200 Subject: [PATCH 262/302] [libcalamares] Make failures in the internal methods obvious - internally, timeout and error will return nullptr --- src/libcalamares/network/Manager.cpp | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/libcalamares/network/Manager.cpp b/src/libcalamares/network/Manager.cpp index b4e37d895..fd58c5408 100644 --- a/src/libcalamares/network/Manager.cpp +++ b/src/libcalamares/network/Manager.cpp @@ -99,6 +99,14 @@ Manager::setCheckHasInternetUrl( const QUrl& url ) d->m_hasInternetUrl = url; } +/** @brief Does a request synchronously, returns the request itself + * + * The extra options for the request are taken from @p options, + * including the timeout setting. + * + * On failure, returns nullptr (e.g. bad URL, timeout). The request + * is marked for later automatic deletion, so don't store the pointer. + */ static QNetworkReply* synchronousRun( const std::unique_ptr< QNetworkAccessManager >& nam, const QUrl& url, const RequestOptions& options ) { @@ -107,10 +115,11 @@ synchronousRun( const std::unique_ptr< QNetworkAccessManager >& nam, const QUrl& QEventLoop loop; QTimer timer; + // Bail out early if the request is bad if ( reply->error() ) { reply->deleteLater(); - return reply; + return nullptr; } options.applyToRequest( &request ); @@ -123,6 +132,12 @@ synchronousRun( const std::unique_ptr< QNetworkAccessManager >& nam, const QUrl& QObject::connect( reply, &QNetworkReply::finished, &loop, &QEventLoop::quit ); loop.exec(); + if ( options.hasTimeout() && !timer.isActive() ) + { + reply->deleteLater(); + return nullptr; + } + reply->deleteLater(); return reply; } @@ -135,8 +150,8 @@ Manager::synchronousPing( const QUrl& url, const RequestOptions& options ) return false; } - auto reply = synchronousRun( d->m_nam, url, options ); - return reply->bytesAvailable(); + auto* reply = synchronousRun( d->m_nam, url, options ); + return reply && reply->bytesAvailable(); } QByteArray @@ -147,8 +162,8 @@ Manager::synchronousGet( const QUrl& url, const RequestOptions& options ) return QByteArray(); } - auto reply = synchronousRun( d->m_nam, url, options ); - return reply->readAll(); + auto* reply = synchronousRun( d->m_nam, url, options ); + return reply ? reply->readAll() : QByteArray(); } } // namespace Network From e2c6591a77c36dd7d6aea62aa66fb3946f53f716 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 26 Aug 2019 15:24:58 +0200 Subject: [PATCH 263/302] [libcalamares] Refactor request internals - distinguish timeouts from other failures - git synchronousPing() a more detailed result, which is still bool-compatible. --- src/libcalamares/network/Manager.cpp | 27 +++++++++++++++++---------- src/libcalamares/network/Manager.h | 28 ++++++++++++++++++++++++---- 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/src/libcalamares/network/Manager.cpp b/src/libcalamares/network/Manager.cpp index fd58c5408..6c2d6caab 100644 --- a/src/libcalamares/network/Manager.cpp +++ b/src/libcalamares/network/Manager.cpp @@ -107,7 +107,7 @@ Manager::setCheckHasInternetUrl( const QUrl& url ) * On failure, returns nullptr (e.g. bad URL, timeout). The request * is marked for later automatic deletion, so don't store the pointer. */ -static QNetworkReply* +static QPair< RequestStatus, QNetworkReply* > synchronousRun( const std::unique_ptr< QNetworkAccessManager >& nam, const QUrl& url, const RequestOptions& options ) { QNetworkRequest request = QNetworkRequest( url ); @@ -119,7 +119,7 @@ synchronousRun( const std::unique_ptr< QNetworkAccessManager >& nam, const QUrl& if ( reply->error() ) { reply->deleteLater(); - return nullptr; + return qMakePair( RequestStatus( RequestStatus::Failed ), nullptr ); } options.applyToRequest( &request ); @@ -135,23 +135,30 @@ synchronousRun( const std::unique_ptr< QNetworkAccessManager >& nam, const QUrl& if ( options.hasTimeout() && !timer.isActive() ) { reply->deleteLater(); - return nullptr; + return qMakePair( RequestStatus( RequestStatus::Timeout ), nullptr ); } reply->deleteLater(); - return reply; + return qMakePair( RequestStatus( RequestStatus::Ok ), reply ); } -bool +RequestStatus Manager::synchronousPing( const QUrl& url, const RequestOptions& options ) { if ( !url.isValid() ) { - return false; + return RequestStatus::Failed; } - auto* reply = synchronousRun( d->m_nam, url, options ); - return reply && reply->bytesAvailable(); + auto reply = synchronousRun( d->m_nam, url, options ); + if ( reply.first ) + { + return reply.second->bytesAvailable() ? RequestStatus::Ok : RequestStatus::Empty; + } + else + { + return reply.first; + } } QByteArray @@ -162,8 +169,8 @@ Manager::synchronousGet( const QUrl& url, const RequestOptions& options ) return QByteArray(); } - auto* reply = synchronousRun( d->m_nam, url, options ); - return reply ? reply->readAll() : QByteArray(); + auto reply = synchronousRun( d->m_nam, url, options ); + return reply.first ? reply.second->readAll() : QByteArray(); } } // namespace Network diff --git a/src/libcalamares/network/Manager.h b/src/libcalamares/network/Manager.h index fef75ffb8..33a1ba350 100644 --- a/src/libcalamares/network/Manager.h +++ b/src/libcalamares/network/Manager.h @@ -70,6 +70,22 @@ private: Q_DECLARE_OPERATORS_FOR_FLAGS( RequestOptions::Flags ); +struct RequestStatus +{ + enum State + { + Ok, + Timeout, // Timeout exceeded + Failed, // bad Url + Empty // for ping(), response is empty + }; + + RequestStatus( State s = Ok ); + operator bool() const { return m_s == Ok; } + + State m_s; +}; + class DLLEXPORT Manager : QObject { Q_OBJECT @@ -87,15 +103,19 @@ public: /** @brief Checks if the given @p url returns data. * - * Returns @c true if it does; @c false means no data, typically - * because of an error or no network access. + * Returns a RequestStatus, which converts to @c true if the ping + * was successful. Other status reasons convert to @c false, + * typically because of no data, a Url error or no network access. + * + * May return Empty if the request was successful but returned + * no data at all. */ - bool synchronousPing( const QUrl& url, const RequestOptions& options = RequestOptions() ); + RequestStatus synchronousPing( const QUrl& url, const RequestOptions& options = RequestOptions() ); /** @brief Downloads the data from a given @p url * * Returns the data as a QByteArray, or an empty - * array if any error occurred. + * array if any error occurred (or no data was returned). */ QByteArray synchronousGet( const QUrl& url, const RequestOptions& options = RequestOptions() ); From a1b0049bbfa16655441acc24a2d8cf4c3c6f2caa Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 26 Aug 2019 15:41:30 +0200 Subject: [PATCH 264/302] [libcalamares] Use more readable names --- src/libcalamares/network/Manager.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/libcalamares/network/Manager.h b/src/libcalamares/network/Manager.h index 33a1ba350..0f2d0c651 100644 --- a/src/libcalamares/network/Manager.h +++ b/src/libcalamares/network/Manager.h @@ -80,10 +80,13 @@ struct RequestStatus Empty // for ping(), response is empty }; - RequestStatus( State s = Ok ); - operator bool() const { return m_s == Ok; } + RequestStatus( State s = Ok ) + : status( s ) + { + } + operator bool() const { return status == Ok; } - State m_s; + State status; }; class DLLEXPORT Manager : QObject From f7215393d1332f91f9e72578137274269c578417 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 26 Aug 2019 15:45:10 +0200 Subject: [PATCH 265/302] [tracking] Use the network service - drop own NAM handling - use timeout mechanism - report timeout as fatal error (like it already did), other errors are ignored. --- src/modules/tracking/TrackingJobs.cpp | 47 +++++---------------------- src/modules/tracking/TrackingJobs.h | 8 ----- 2 files changed, 9 insertions(+), 46 deletions(-) diff --git a/src/modules/tracking/TrackingJobs.cpp b/src/modules/tracking/TrackingJobs.cpp index bf71b541a..f101c8e6c 100644 --- a/src/modules/tracking/TrackingJobs.cpp +++ b/src/modules/tracking/TrackingJobs.cpp @@ -18,12 +18,10 @@ #include "TrackingJobs.h" +#include "network/Manager.h" #include "utils/CalamaresUtilsSystem.h" #include "utils/Logger.h" -#include -#include -#include #include #include @@ -31,13 +29,11 @@ TrackingInstallJob::TrackingInstallJob( const QString& url ) : m_url( url ) - , m_networkManager( nullptr ) { } TrackingInstallJob::~TrackingInstallJob() { - delete m_networkManager; } QString @@ -61,48 +57,23 @@ TrackingInstallJob::prettyStatusMessage() const Calamares::JobResult TrackingInstallJob::exec() { - m_networkManager = new QNetworkAccessManager(); + using CalamaresUtils::Network::Manager; + using CalamaresUtils::Network::RequestOptions; + using CalamaresUtils::Network::RequestStatus; - QNetworkRequest request; - request.setUrl( QUrl( m_url ) ); - // Follows all redirects except unsafe ones (https to http). - request.setAttribute( QNetworkRequest::FollowRedirectsAttribute, true ); - // Not everybody likes the default User Agent used by this class (looking at you, - // sourceforge.net), so let's set a more descriptive one. - request.setRawHeader( "User-Agent", "Mozilla/5.0 (compatible; Calamares)" ); - - QTimer timeout; - timeout.setSingleShot( true ); - - QEventLoop loop; - - connect( m_networkManager, &QNetworkAccessManager::finished, this, &TrackingInstallJob::dataIsHere ); - connect( m_networkManager, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit ); - connect( &timeout, &QTimer::timeout, &loop, &QEventLoop::quit ); - - m_networkManager->get( request ); // The semaphore is released when data is received - timeout.start( std::chrono::milliseconds( 5000 ) ); - - loop.exec(); - - if ( !timeout.isActive() ) + auto result = Manager::instance().synchronousPing( + QUrl( m_url ), + RequestOptions( RequestOptions::FollowRedirect | RequestOptions::FakeUserAgent, + RequestOptions::milliseconds( 5000 ) ) ); + if ( result.status == RequestStatus::Timeout ) { cWarning() << "install-tracking request timed out."; return Calamares::JobResult::error( tr( "Internal error in install-tracking." ), tr( "HTTP request timed out." ) ); } - timeout.stop(); - return Calamares::JobResult::ok(); } -void -TrackingInstallJob::dataIsHere( QNetworkReply* reply ) -{ - cDebug() << "Installation feedback request OK"; - reply->deleteLater(); -} - QString TrackingMachineNeonJob::prettyName() const { diff --git a/src/modules/tracking/TrackingJobs.h b/src/modules/tracking/TrackingJobs.h index a379441c9..7351c3346 100644 --- a/src/modules/tracking/TrackingJobs.h +++ b/src/modules/tracking/TrackingJobs.h @@ -21,13 +21,10 @@ #include "Job.h" -class QNetworkAccessManager; -class QNetworkReply; class QSemaphore; class TrackingInstallJob : public Calamares::Job { - Q_OBJECT public: TrackingInstallJob( const QString& url ); ~TrackingInstallJob() override; @@ -37,13 +34,8 @@ public: QString prettyStatusMessage() const override; Calamares::JobResult exec() override; -public slots: - void dataIsHere( QNetworkReply* ); - private: const QString m_url; - - QNetworkAccessManager* m_networkManager; }; class TrackingMachineNeonJob : public Calamares::Job From ee29c45433b1549e7923ec00a168cf95987282c7 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 26 Aug 2019 16:01:14 +0200 Subject: [PATCH 266/302] [netinstall] Point documentation towards netinstall README.md --- src/modules/netinstall/netinstall.conf | 7 +++++++ src/modules/netinstall/netinstall.yaml | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/src/modules/netinstall/netinstall.conf b/src/modules/netinstall/netinstall.conf index fe99eb2be..fa160d34c 100644 --- a/src/modules/netinstall/netinstall.conf +++ b/src/modules/netinstall/netinstall.conf @@ -4,6 +4,13 @@ # groupsUrl: http://example.org/netinstall.php # or it can be a locally installed file: # groupsUrl: file:///usr/share/calamares/netinstall.yaml +# +# Note that the contents of the groups file is the **inmportant** +# part of the configuration of this module. It specifies what +# the user may select and what commands are to be run. +# +# The format of the groups file is documented in `README.md`. +# # groupsUrl: file:///usr/share/calamares/netinstall.yaml # If the installation can proceed without netinstall (e.g. the Live CD diff --git a/src/modules/netinstall/netinstall.yaml b/src/modules/netinstall/netinstall.yaml index 8e9037f4d..e00f06c73 100644 --- a/src/modules/netinstall/netinstall.yaml +++ b/src/modules/netinstall/netinstall.yaml @@ -1,3 +1,7 @@ +# Example configuration with groups and packages, taken from Chakra Linux. +# +# This example is rather limited. See `README.md` for full documentation +# on the configuration format. - name: "Default" description: "Default group" hidden: true From 56792fdcb578f41e9e2285c6918afb042b815a01 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 26 Aug 2019 16:26:06 +0200 Subject: [PATCH 267/302] [netinstall] Polish the README - describe the format better - more consistent typography - refer to `packages.conf` for details on shell commands --- src/modules/netinstall/README.md | 134 +++++++++++++++++++------------ 1 file changed, 82 insertions(+), 52 deletions(-) diff --git a/src/modules/netinstall/README.md b/src/modules/netinstall/README.md index 6478a844e..855754822 100644 --- a/src/modules/netinstall/README.md +++ b/src/modules/netinstall/README.md @@ -1,86 +1,116 @@ # Netinstall module -The netinstall module allows distribution maintainers to ship minimal ISOs with only a basic set of preinstall packages. -At installation time, the user is presented with the choice to install groups of packages from a predefined list. +The netinstall module allows distribution maintainers to ship minimal ISOs with +only a basic set of preinstall packages. At installation time, the user is +presented with the choice to install groups of packages from a predefined list. Calamares will then invoke the correct backend to install the packages. -## Configuration of the packages -Every distribution can choose which groups to display and which packages should be in the groups. +## Module Configuration -The *netinstall.conf* file should have this format: +The `netinstall.conf` file is self-describing, and at the very +lease should contain a *groupsUrl* key: +``` ---- groupsUrl: +``` -The URL must point to a YAML file. Here is a short example of how the YAML file should look. +The URL must point to a YAML file, the *groups* file. See below for +the format of that groups file. The URL may be a local file. - - name: "Group name" - description: "Description of the group" - packages: - - lsb-release - - avahi - - grub - - name: "Second group name" + +## Groups Configuration + + Here is a short example +of how the YAML file should look. + +``` + - name: "Group name" + description: "Description of the group" + packages: + - lsb-release + - avahi + - grub + - name: "Second group name" ... +``` -The file is composed of a list of entry, each describing one group. The keys *name*, *description* and *packages* are required. +The file is composed of a list of entries, each describing one group. The +keys *name*, *description* and *packages* are required for each group. -More keys are supported: +More keys (per group) are supported: - - hidden: if true, do not show the group on the page. Defaults to false. - - selected: if true, display the group as selected. Defaults to false. - - critical: if true, make the installation process fail if installing - any of the packages in the group fails. Otherwise, just log a warning. - Defaults to false. - - subgroups: if present this follows the same structure as the top level - of the YAML file, allowing there to be sub-groups of packages to an - arbitary depth - - pre-install: an optional command to run within the new system before - the group's packages are installed. It will run before each package in - the group is installed. - - post-install: an optional command to run within the new system after - the group's packages are installed. It will run after each package in - the group is installed. + - *hidden*: if true, do not show the group on the page. Defaults to false. + - *selected*: if true, display the group as selected. Defaults to false. + - critical*: if true, make the installation process fail if installing + any of the packages in the group fails. Otherwise, just log a warning. + Defaults to false. + - *subgroups*: if present this follows the same structure as the top level + of the YAML file, allowing there to be sub-groups of packages to an + arbitary depth + - *pre-install*: an optional command to run within the new system before + the group's packages are installed. It will run before each package in + the group is installed. + - *post-install*: an optional command to run within the new system after + the group's packages are installed. It will run after each package in + the group is installed. -If you set both *hidden* and *selected* for a group, you are basically creating a "default" group of packages -which will always be installed in the user's system. +If you set both *hidden* and *selected* for a group, you are basically creating +a "default" group of packages which will always be installed in the user's +system. -## Configuration of the module +> The note below applies to Calamares up-to-and-including 3.2.13, but will +> change in a later release. -Here is the set of instructions to have the module work in your Calamares. As of July 2016, this has been successfully -tested using the live installation of Chakra Fermi. +The *pre-install* and *post-install* commands are **not** passed to +a shell; see the **packages** module configuration (i.e. `packages.conf`) +for details. To use a full shell pipeline, call the shell explicitly. -First, if the module is used, we need to require a working Internet connection, otherwise the module will be -unable to fetch the package groups and to perform the installation. Requirements for the Calamares instance -are configured in the **welcome.conf** file (configuration for the **welcome** module). Make sure *internet* -is listed below *required*. -In the *settings.conf* file, decide where the **netinstall** page should be displayed. I put it just after the -**welcome** page, but any position between that and just before **partition** should make no difference. -If not present, add the **packages** job in the **exec** list. This is the job that calls the package manager -to install packages. Make sure it is configured to use the correct package manager for your distribution; this -is configured in src/modules/packages/packages.conf. +## Overall Configuration -The **exec** list in *settings.conf* should contain the following items in +Here is the set of instructions to have the module work in your Calamares. + +First, if the module is used, we need to require a working Internet connection, +otherwise the module will be unable to fetch the package groups and to perform +the installation. Requirements for the Calamares instance are configured in the +`welcome.conf` file (configuration for the **welcome** module). Make sure +*internet* is listed under the *required* checks. + +In the `settings.conf` file, decide where the **netinstall** page should be +displayed. I put it just after the **welcome** page, but any position between +that and just before **partition** should make no difference. + +If not present, add the **packages** job in the *exec* list. This is the job +that calls the package manager to install packages. Make sure it is configured +to use the correct package manager for your distribution; this is configured in +`packages.conf`. + +The *exec* list in `settings.conf` should contain the following items in order (it's ok for other jobs to be listed inbetween them, though): +``` - unpackfs - networkcfg - packages +``` -**unpackfs** creates the chroot where the installation is performed, and unpacks the root image with the filesystem -structure; **networkcfg** set ups a working network in the chroot; and finally **packages** can install packages -in the chroot. +**unpackfs** creates the chroot where the installation is performed, and unpacks +the root image with the filesystem structure; **networkcfg** set ups a working +network in the chroot; and finally **packages** can install packages in the +chroot. ## Common issues -If launching the package manager command returns you negative exit statuses and nothing is actually invoked, this -is likely an error in the setup of the chroot; check that the parameter **rootMountPoint** is set to the correct -value in the Calamares configuration. +If launching the package manager command returns you negative exit statuses and +nothing is actually invoked, this is likely an error in the setup of the chroot; +check that the parameter **rootMountPoint** is set to the correct value in the +Calamares configuration. -If the command is run, but exits with error, check that the network is working in the chroot. Make sure /etc/resolv.conf -exists and that it's not empty. +If the command is run, but exits with error, check that the network is +working in the chroot. Make sure `/etc/resolv.conf` exists and that +it's not empty. From d063d60e37c25eff193ed3d3a96bd7aef0a168d7 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 26 Aug 2019 16:42:05 +0200 Subject: [PATCH 268/302] [packages] Explain pre-script isn't actually a shell script --- src/modules/packages/packages.conf | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/modules/packages/packages.conf b/src/modules/packages/packages.conf index 94f3cfdb6..e42e8e9b8 100644 --- a/src/modules/packages/packages.conf +++ b/src/modules/packages/packages.conf @@ -31,9 +31,9 @@ backend: dummy # # Set "update_db" to 'true' for refreshing the database on the # target system. On target installations, which got installed by -# unsquashing, a full system update may be needed. Otherwise +# unsquashing, a full system update may be needed. Otherwise # post-installing additional packages may result in conflicts. -# Therefore set also "update_system" to 'true'. +# Therefore set also "update_system" to 'true'. # skip_if_no_internet: false update_db: true @@ -87,9 +87,25 @@ update_system: false # pre-script: touch /tmp/installing-vi # post-script: rm -f /tmp/installing-vi # -# The pre- and post-scripts are optional, but you cannot leave both out: using -# "package: vi" with neither script option will trick Calamares into -# trying to install a package named "package: vi", which is unlikely to work. +# The pre- and post-scripts are optional, but you cannot leave both out +# if you do use the *package* key: using "package: vi" with neither script +# option will trick Calamares into trying to install a package named +# "package: vi", which is unlikely to work. +# +# The pre- and post-scripts are **not** executed by a shell unless you +# explicitly invoke `/bin/sh` in them. The command-lines are passed +# to exec(), which does not understand shell syntax. In other words: +# +# pre-script: ls | wc -l +# +# Will fail, because `|` is passed as a command-line argument to ls, +# as are `wc`, and `-l`. No shell pipeline is set up, and ls is likely +# to complain. Invoke the shell explicitly: +# +# pre-script: /bin/sh -c \"ls | wc -l\" +# +# The above note on shell-expansion applies to versions up-to-and-including +# Calamares 3.2.12, but will change in future. # # Any package name may be localized; this is used to install localization # packages for software based on the selected system locale. By including @@ -104,7 +120,7 @@ update_system: false # # Take care that just plain `LOCALE` will not be replaced, so `foo-LOCALE` will # be left unchanged, while `foo-$LOCALE` will be changed. However, `foo-LOCALE` -# **will** be removed from the list of packages (i.e. not installed), if +# **will** be removed from the list of packages (i.e. not installed), if # English is selected. If a non-English locale is selected, then `foo-LOCALE` # will be installed, unchanged (no language-name-substitution occurs). # From 5868f102f25c3f4e96936d2419871cfc24fa97a0 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 26 Aug 2019 16:49:58 +0200 Subject: [PATCH 269/302] [packagechooser] Less-bad "no selection" image - It's only "less bad", not actually a good image, composed from Breeze "empty" and "generic packages" icon. --- .../packagechooser/images/no-selection.png | Bin 4618 -> 1709 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/modules/packagechooser/images/no-selection.png b/src/modules/packagechooser/images/no-selection.png index f9dbbbac45d0b03667f66be54664fdc5dce71983..437c97051cb9d0d16049ebff1bdc6cffe1ddb8a1 100644 GIT binary patch literal 1709 zcmd^9`BT$J6yI+Mm;eGwXF}Bmt1XNpBzR(_K&+I2q~Mi7DuE~pB4VhN5+g^zY7a)x zVW`mn83v2+MFcD01kJ$!MwF{k2#|vY6ha_`1QG~G(jdx@{RiBco%i-#`}yp=eZL(J zC9bvIU<&|P8ypmH6adJgLI7oB5s{b5V=V%m6cmvRfJ5{0h6=VjYy`k2Iym6KaeARz zCP<)+ekRgtZl#^wbnIYo@RlT1W9~M2Vav^+WA^G^|IM=3^dAyMGIj}$VoTl{caF{2 zc1Gh$ZFsTm3vw{JrK`ED-7)4nTbGwDm^V;A_07PrCZ=#V3^B9hqOy$mvhv`Z6vZ1|E1k zUcQk=i60rCJ05~$i2ceXM2GgJ3yF#9i{bBRcdm0cw= z(mEm5B~PRlaWa0&JgZl=JNh@IEXwKQhsZ^hx%t90F=l^y>=PJas*=^vHCPJLl`ErN?+r{u4f*Yc!51T1rLO3sU2ot2l9IO2(h{z9-2k z#-VG+?Cj)*rkfrf9{;?}!Gw}~FjwkwI-owjB3xAL%Scl7Ks-r5+s9&^bQT(985-j$ z7QfcpCr{ap1asHd0hAkXB7w~;K=6W?R0L>5f^0NEI)5~dzN`p5leo}5IN8BK=T*hS z8FPz64{kSZMG2Wp+D`L?nj0QLXu*gQK1RxeKyCaWawCxinCh3d85$ z7GNr2mCi8C6VJ>%o3M6XiI5C}!vdqWDc@Y@Ka--uCg&>c)h| zr@fVxl2kK(pRx3P-2p5OvCmkso_Qkt3C*N-`k93AqNZp5ZgQ8fP3_4ceve#V`o6oX z#?ODvVGDx6YVm0n36yl0C!dQ=Y!5f)=aTA}ey!^(Bxoc7tKM0z)YKWSLlJ7G1r)Y^ zJ!=OIddES^E~TyDuJJR+IF;{&2)mtyOzs-OAZfL)W`WIvPJgrw*$w<^Vd!NA(sw}w zFH78~K*>gf>^s1wjRvi%#<1n&Hl){?K){Gy;W>@TTJ?)8S-`$8b5dHUUvGHf7|R3L z1Hk6O(m+@o56M?Ztv<>|{=Y9=6OZt!fH&lc62lT8Y}0MS$i4ABMOIz4bw|j0?R}1n zbBQAK>-#V%2;Gs@@b?isM)JPckJiJ`BU wydCia1Lb90lj*6q{2^Qwfk%B9@1PHFwr;kvMwtJ0mo6KFzYPs|_zgAtKayIY1ONa4 literal 4618 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 From 9dbd3a765bf76aff56ddcdce0943004bccc365bb Mon Sep 17 00:00:00 2001 From: Kevin Kofler Date: Mon, 26 Aug 2019 19:02:15 +0200 Subject: [PATCH 270/302] [netinstall] Fix typo in netinstall.conf comment s/inmportant/important/ --- src/modules/netinstall/netinstall.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/netinstall/netinstall.conf b/src/modules/netinstall/netinstall.conf index fa160d34c..fd59c24c6 100644 --- a/src/modules/netinstall/netinstall.conf +++ b/src/modules/netinstall/netinstall.conf @@ -5,7 +5,7 @@ # or it can be a locally installed file: # groupsUrl: file:///usr/share/calamares/netinstall.yaml # -# Note that the contents of the groups file is the **inmportant** +# Note that the contents of the groups file is the **important** # part of the configuration of this module. It specifies what # the user may select and what commands are to be run. # From 6035a74a93c070c960c0cd4701a6c6f810bdb30c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 26 Aug 2019 20:34:32 +0200 Subject: [PATCH 271/302] [packagechooser] Align the screenshot - hcenter + vcenter the screenshot - make it expand as necessary - fill in some sample text --- src/modules/packagechooser/page_package.ui | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/modules/packagechooser/page_package.ui b/src/modules/packagechooser/page_package.ui index 17a960549..496c478a1 100644 --- a/src/modules/packagechooser/page_package.ui +++ b/src/modules/packagechooser/page_package.ui @@ -37,21 +37,36 @@ - TextLabel + Product Name + + + 1 + 0 + + TextLabel + + Qt::AlignCenter + + + + 0 + 2 + + - TextLabel + Long Product Description true From d8a587e16e3b45cb99abf289a6c7ec021c0b62c4 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 26 Aug 2019 21:40:16 +0200 Subject: [PATCH 272/302] [packagechooser] Scale screenshot - if the screenshot is too large, scale it down - (doesn't react to window resizes though) --- .../packagechooser/PackageChooserPage.cpp | 42 ++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index 6f565c914..f0a6579b4 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -52,6 +52,37 @@ PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent } } +/** @brief size the given @p pixmap to @p size + * + * This is "smart" in the sense that it tries to keep the image un-scaled + * (if it's just a little too big) and otherwise scales as needed. + * + * Returns a copy if any modifications are done. + */ +static QPixmap +smartClip( const QPixmap& pixmap, QSize size ) +{ + auto pixSize = pixmap.size(); + if ( ( pixSize.width() <= size.width() ) && ( pixSize.height() <= size.height() ) ) + { + return pixmap; + } + + // only slightly bigger? Trim the edges + constexpr int margin = 16; + if ( ( pixSize.width() <= size.width() + margin ) && ( pixSize.height() <= size.height() + margin ) ) + { + int x = pixSize.width() <= size.width() ? 0 : ( pixSize.width() - size.width() / 2 ); + int new_width = pixSize.width() <= size.width() ? pixSize.width() : size.width(); + int y = pixSize.height() <= size.height() ? 0 : ( pixSize.height() - size.height() / 2 ); + int new_height = pixSize.height() <= size.height() ? pixSize.height() : size.height(); + + return pixmap.copy( x, y, new_width, new_height ); + } + + return pixmap.scaled( size, Qt::KeepAspectRatio ); +} + void PackageChooserPage::currentChanged( const QModelIndex& index ) { @@ -66,8 +97,17 @@ PackageChooserPage::currentChanged( const QModelIndex& index ) const auto* model = ui->products->model(); ui->productName->setText( model->data( index, PackageListModel::NameRole ).toString() ); - ui->productScreenshot->setPixmap( model->data( index, PackageListModel::ScreenshotRole ).value< QPixmap >() ); ui->productDescription->setText( model->data( index, PackageListModel::DescriptionRole ).toString() ); + + QPixmap currentScreenshot = model->data( index, PackageListModel::ScreenshotRole ).value< QPixmap >(); + if ( currentScreenshot.isNull() ) + { + ui->productScreenshot->setPixmap( m_introduction.screenshot ); + } + else + { + ui->productScreenshot->setPixmap( smartClip( currentScreenshot, ui->productScreenshot->size() ) ); + } } } From eb21c90861f399236357b1f68cd22bb04a1111c6 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 26 Aug 2019 16:54:35 +0200 Subject: [PATCH 273/302] [libcalamares] Avoid implicit 0-to-flags conversion - clang complains about using 0 as a Flags value, so make the default (empty) initialization explicit. --- src/libcalamares/network/Manager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcalamares/network/Manager.h b/src/libcalamares/network/Manager.h index 0f2d0c651..041314f13 100644 --- a/src/libcalamares/network/Manager.h +++ b/src/libcalamares/network/Manager.h @@ -47,7 +47,7 @@ public: Q_DECLARE_FLAGS( Flags, Flag ) RequestOptions() - : m_flags( 0 ) + : m_flags( Flags() ) , m_timeout( -1 ) { } From 3f101bcdb70ae2e6f34b2b17898f8ce26f8e1edf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Tue, 27 Aug 2019 02:26:50 -0400 Subject: [PATCH 274/302] Revert "[libcalamares] Disable Q_DELCARE_INTERFACE once more" This reverts commit ab986233c32f15661db3114f3f2bfeebbe07f6e0. --- src/libcalamares/utils/PluginFactory.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcalamares/utils/PluginFactory.h b/src/libcalamares/utils/PluginFactory.h index 86fe1d4cf..958a7858a 100644 --- a/src/libcalamares/utils/PluginFactory.h +++ b/src/libcalamares/utils/PluginFactory.h @@ -102,6 +102,6 @@ public: K_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY( name, CalamaresPluginFactory, pluginRegistrations ) -// Q_DECLARE_INTERFACE( CalamaresPluginFactory, CalamaresPluginFactory_iid ) +Q_DECLARE_INTERFACE( CalamaresPluginFactory, CalamaresPluginFactory_iid ) #endif From e0bb53aff4130a2c06cbecd86c2fd7b715c5c4bb Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 27 Aug 2019 13:34:26 +0200 Subject: [PATCH 275/302] [dummycpp] Replace QProcess::execute() - hangs unpredictably during testing - replace with the Calamares process-invocation runCommand(), which is also synchronous but doesn't hang (or, hasn't, in testing so far) --- src/modules/dummycpp/DummyCppJob.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/modules/dummycpp/DummyCppJob.cpp b/src/modules/dummycpp/DummyCppJob.cpp index a38cddc40..5a2ca1803 100644 --- a/src/modules/dummycpp/DummyCppJob.cpp +++ b/src/modules/dummycpp/DummyCppJob.cpp @@ -28,6 +28,7 @@ #include "GlobalStorage.h" #include "JobQueue.h" +#include "utils/CalamaresUtilsSystem.h" #include "utils/Logger.h" DummyCppJob::DummyCppJob( QObject* parent ) @@ -113,9 +114,10 @@ Calamares::JobResult DummyCppJob::exec() { // Ported from dummypython - QProcess::execute( "/bin/sh", - QStringList() << "-c" - << "touch ~/calamares-dummycpp" ); + CalamaresUtils::System::runCommand( CalamaresUtils::System::RunLocation::RunInHost, + QStringList() << "/bin/sh" + << "-c" + << "touch ~/calamares-dummycpp" ); QString accumulator = QDateTime::currentDateTimeUtc().toString( Qt::ISODate ) + '\n'; accumulator += QStringLiteral( "Calamares version: " ) + CALAMARES_VERSION_SHORT + '\n'; accumulator += QStringLiteral( "This job's name: " ) + prettyName() + '\n'; From ac8952f2236b74469f72062be54d94e9c0bf6978 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 27 Aug 2019 11:02:27 +0200 Subject: [PATCH 276/302] [libcalamaresui] Improve QML API v2 debugging - log what is being loaded - distinguish "component complete" from actuial loading --- src/libcalamaresui/ExecutionViewStep.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libcalamaresui/ExecutionViewStep.cpp b/src/libcalamaresui/ExecutionViewStep.cpp index 4dd10bd93..7b6b597a3 100644 --- a/src/libcalamaresui/ExecutionViewStep.cpp +++ b/src/libcalamaresui/ExecutionViewStep.cpp @@ -184,7 +184,7 @@ ExecutionViewStep::loadQmlV2Complete() { if ( m_qmlComponent && m_qmlComponent->isReady() && !m_qmlObject ) { - cDebug() << "QML loading complete, API 2"; + cDebug() << "QML component complete, API 2"; // Don't do this again disconnect( m_qmlComponent, &QQmlComponent::statusChanged, this, &ExecutionViewStep::loadQmlV2Complete ); @@ -196,6 +196,8 @@ ExecutionViewStep::loadQmlV2Complete() } else { + cDebug() << Logger::SubEntry << "Loading" << Calamares::Branding::instance()->slideshowPath(); + // setContent() is public API, but not documented publicly. // It is marked \internal in the Qt sources, but does exactly // what is needed: sets up visual parent by replacing the root From 34cb777b0ae7465814b8ce1f698b02a25ec6e274 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 27 Aug 2019 11:11:35 +0200 Subject: [PATCH 277/302] [qml] Disable all the key shortcuts via root.activatedInCalamares --- src/qml/calamares/slideshow/Presentation.qml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/qml/calamares/slideshow/Presentation.qml b/src/qml/calamares/slideshow/Presentation.qml index 4843e15a6..7053fb0ae 100644 --- a/src/qml/calamares/slideshow/Presentation.qml +++ b/src/qml/calamares/slideshow/Presentation.qml @@ -77,6 +77,8 @@ Item { property string fontFamily: "Helvetica" property string codeFontFamily: "Courier New" + property bool activatedInCalamares: false; + // Private API property int _lastShownSlide: 0 @@ -136,17 +138,17 @@ Item { Keys.onLeftPressed: goToPreviousSlide() // navigate with arrow keys - Shortcut { sequence: StandardKey.MoveToNextLine; enabled: root.arrowNavigation; onActivated: goToNextSlide() } - Shortcut { sequence: StandardKey.MoveToPreviousLine; enabled: root.arrowNavigation; onActivated: goToPreviousSlide() } - Shortcut { sequence: StandardKey.MoveToNextChar; enabled: root.arrowNavigation; onActivated: goToNextSlide() } - Shortcut { sequence: StandardKey.MoveToPreviousChar; enabled: root.arrowNavigation; onActivated: goToPreviousSlide() } + Shortcut { sequence: StandardKey.MoveToNextLine; enabled: root.activatedInCalamares && root .arrowNavigation; onActivated: goToNextSlide() } + Shortcut { sequence: StandardKey.MoveToPreviousLine; enabled: root.activatedInCalamares && root.arrowNavigation; onActivated: goToPreviousSlide() } + Shortcut { sequence: StandardKey.MoveToNextChar; enabled: root.activatedInCalamares && root.arrowNavigation; onActivated: goToNextSlide() } + Shortcut { sequence: StandardKey.MoveToPreviousChar; enabled: root.activatedInCalamares && root.arrowNavigation; onActivated: goToPreviousSlide() } // presentation-specific single-key shortcuts (which interfere with normal typing) - Shortcut { sequence: " "; enabled: root.keyShortcutsEnabled; onActivated: goToNextSlide() } + Shortcut { sequence: " "; enabled: root.activatedInCalamares && root.keyShortcutsEnabled; onActivated: goToNextSlide() } // standard shortcuts - Shortcut { sequence: StandardKey.MoveToNextPage; onActivated: goToNextSlide() } - Shortcut { sequence: StandardKey.MoveToPreviousPage; onActivated: goToPreviousSlide() } + Shortcut { sequence: StandardKey.MoveToNextPage; enabled: root.activatedInCalamares; onActivated: goToNextSlide() } + Shortcut { sequence: StandardKey.MoveToPreviousPage; enabled: root.activatedInCalamares; onActivated: goToPreviousSlide() } MouseArea { id: mouseArea From 0a9d0ddf68e9b42a107f72edc30c36b7fb2340a5 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 27 Aug 2019 11:49:27 +0200 Subject: [PATCH 278/302] [qml] In the default (sample) slideshow, activate key shortcuts - with V2 loading, the key shortcuts should be enabled when the slideshow itself is activated, not when it is loaded. --- src/branding/default/show.qml | 10 ++++++++-- src/qml/calamares/slideshow/Presentation.qml | 3 +++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/branding/default/show.qml b/src/branding/default/show.qml index c989676dd..1a174f0b6 100644 --- a/src/branding/default/show.qml +++ b/src/branding/default/show.qml @@ -25,7 +25,7 @@ Presentation id: presentation function nextSlide() { - console.log("Next slide"); + console.log("QML Component (default slideshow) Next slide"); presentation.goToNextSlide(); } @@ -70,7 +70,13 @@ Presentation function onActivate() { presentation.currentSlide = 0; - advanceTimer.running = true + presentation.activatedInCalamares = true; + advanceTimer.running = true; console.log("QML Component (default slideshow) activated"); } + + function onLeave() { + presentation.activatedInCalamares = true; + } + } diff --git a/src/qml/calamares/slideshow/Presentation.qml b/src/qml/calamares/slideshow/Presentation.qml index 7053fb0ae..a4138d588 100644 --- a/src/qml/calamares/slideshow/Presentation.qml +++ b/src/qml/calamares/slideshow/Presentation.qml @@ -8,6 +8,9 @@ * (this and the 'c' key make sense in a *presentation* * slideshow, not in a passive slideshow like Calamares) * - remove quit key + * Copyright 2019, Adriaan de Groot + * - Support "V2" loading + * - Disable shortcuts until the content is visible in Calamares * * SPDX-License-Identifier: LGPL-2.1 * License-Filename: LICENSES/LGPLv2.1-Presentation From 7df6ed31e9547f8a70b6bc3bdf5a672c2c474a47 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 27 Aug 2019 12:01:36 +0200 Subject: [PATCH 279/302] [libcalamaresui] Refactor QML slideshow activation - one function for activation, since we activate from different places and each loader-API may need multiple steps for activation. --- src/libcalamaresui/ExecutionViewStep.cpp | 28 ++++++++++++++---------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/libcalamaresui/ExecutionViewStep.cpp b/src/libcalamaresui/ExecutionViewStep.cpp index 7b6b597a3..c131d9c9a 100644 --- a/src/libcalamaresui/ExecutionViewStep.cpp +++ b/src/libcalamaresui/ExecutionViewStep.cpp @@ -179,6 +179,21 @@ ExecutionViewStep::loadQmlV2() } } +static void +activateSlideShow( QQuickItem* slideshow, QQuickWidget* widget) +{ + if ( Branding::instance()->slideshowAPI() == 2 ) + { + // The QML was already loaded in the constructor, need to start it + callQMLFunction( slideshow, "onActivate" ); + } + else if ( !Calamares::Branding::instance()->slideshowPath().isEmpty() ) + { + // API version 1 assumes onCompleted is the trigger + widget->setSource( QUrl::fromLocalFile( Calamares::Branding::instance()->slideshowPath() ) ); + } +} + void ExecutionViewStep::loadQmlV2Complete() { @@ -208,7 +223,7 @@ ExecutionViewStep::loadQmlV2Complete() { // We're alreay visible! Must have been slow QML loading, and we // passed onActivate already. - callQMLFunction( m_qmlObject, "onActivate" ); + activateSlideShow( m_qmlObject, m_qmlShow ); } } } @@ -217,16 +232,7 @@ ExecutionViewStep::loadQmlV2Complete() void ExecutionViewStep::onActivate() { - if ( Branding::instance()->slideshowAPI() == 2 ) - { - // The QML was already loaded in the constructor, need to start it - callQMLFunction( m_qmlObject, "onActivate" ); - } - else if ( !Calamares::Branding::instance()->slideshowPath().isEmpty() ) - { - // API version 1 assumes onCompleted is the trigger - m_qmlShow->setSource( QUrl::fromLocalFile( Calamares::Branding::instance()->slideshowPath() ) ); - } + activateSlideShow( m_qmlObject, m_qmlShow ); JobQueue* queue = JobQueue::instance(); foreach ( const QString& instanceKey, m_jobInstanceKeys ) From 1e3e53d30a38bd5aa2aec2220a2b806b465ba9ac Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 27 Aug 2019 15:12:47 +0200 Subject: [PATCH 280/302] [libcalamaresui] Set activatedInCalamares special property - when the QML is activated, if the slideshow has this property, set it to true. This enables the keyboard shortcuts. --- src/libcalamaresui/ExecutionViewStep.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/libcalamaresui/ExecutionViewStep.cpp b/src/libcalamaresui/ExecutionViewStep.cpp index c131d9c9a..2b2c47e88 100644 --- a/src/libcalamaresui/ExecutionViewStep.cpp +++ b/src/libcalamaresui/ExecutionViewStep.cpp @@ -191,6 +191,17 @@ activateSlideShow( QQuickItem* slideshow, QQuickWidget* widget) { // API version 1 assumes onCompleted is the trigger widget->setSource( QUrl::fromLocalFile( Calamares::Branding::instance()->slideshowPath() ) ); + slideshow = widget->rootObject(); + } + + if ( slideshow ) + { + static const char propertyName[] = "activatedInCalamares"; + auto active = slideshow->property( propertyName ); + if ( active.isValid() && ( active.type() == QVariant::Bool ) && !active.toBool() ) + { + slideshow->setProperty( propertyName, true ); + } } } From be5388abcd27d2d1825fe6466391cf8369a9814d Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 27 Aug 2019 15:30:45 +0200 Subject: [PATCH 281/302] [libcalamaresui] activate -> change state - since we also need to *disable* the shortcuts, and should tell a V1 slideshow that it no longer is running, - use existing function to set the property to true / false depending. - instead of changeState( true ) or changeStage( false ), use meaningful enum names so that the code at the call site becomes readable; make the boolean part internal to the state-changing method. --- src/libcalamaresui/ExecutionViewStep.cpp | 49 ++++++++++++++++++------ 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/src/libcalamaresui/ExecutionViewStep.cpp b/src/libcalamaresui/ExecutionViewStep.cpp index 2b2c47e88..501995c07 100644 --- a/src/libcalamaresui/ExecutionViewStep.cpp +++ b/src/libcalamaresui/ExecutionViewStep.cpp @@ -179,28 +179,53 @@ ExecutionViewStep::loadQmlV2() } } -static void -activateSlideShow( QQuickItem* slideshow, QQuickWidget* widget) +/// @brief State-change of the slideshow, for changeSlideShowState() +enum class Slideshow { + Start, + Stop +}; + +/** @brief Tells the slideshow we activated or left the show. + * + * If @p state is @c Slideshow::Start, calls suitable activation procedures. + * If @p state is @c Slideshow::Stop, calls deactivation procedures. + * + * Applies V1 and V2 QML activation / deactivation: + * - V1 loads the QML in @p widget on activation. Sets root object property + * *activatedInCalamares* as appropriate. + * - V2 calls onActivate() or onLeave() in the QML as appropriate. Also + * sets the *activatedInCalamares* property. + */ +static void +changeSlideShowState( Slideshow state, QQuickItem* slideshow, QQuickWidget* widget ) +{ + bool activate = state == Slideshow::Start; + if ( Branding::instance()->slideshowAPI() == 2 ) { // The QML was already loaded in the constructor, need to start it - callQMLFunction( slideshow, "onActivate" ); + callQMLFunction( slideshow, activate ? "onActivate" : "onLeave" ); } else if ( !Calamares::Branding::instance()->slideshowPath().isEmpty() ) { // API version 1 assumes onCompleted is the trigger - widget->setSource( QUrl::fromLocalFile( Calamares::Branding::instance()->slideshowPath() ) ); + if ( activate ) + { + widget->setSource( QUrl::fromLocalFile( Calamares::Branding::instance()->slideshowPath() ) ); + } + // needs the root object for property setting, below slideshow = widget->rootObject(); } - + + // V1 API has picked up the root object for use, V2 passed it in. if ( slideshow ) { static const char propertyName[] = "activatedInCalamares"; - auto active = slideshow->property( propertyName ); - if ( active.isValid() && ( active.type() == QVariant::Bool ) && !active.toBool() ) + auto property = slideshow->property( propertyName ); + if ( property.isValid() && ( property.type() == QVariant::Bool ) && ( property.toBool() != activate ) ) { - slideshow->setProperty( propertyName, true ); + slideshow->setProperty( propertyName, activate ); } } } @@ -223,7 +248,7 @@ ExecutionViewStep::loadQmlV2Complete() else { cDebug() << Logger::SubEntry << "Loading" << Calamares::Branding::instance()->slideshowPath(); - + // setContent() is public API, but not documented publicly. // It is marked \internal in the Qt sources, but does exactly // what is needed: sets up visual parent by replacing the root @@ -234,7 +259,7 @@ ExecutionViewStep::loadQmlV2Complete() { // We're alreay visible! Must have been slow QML loading, and we // passed onActivate already. - activateSlideShow( m_qmlObject, m_qmlShow ); + changeSlideShowState( Slideshow::Start, m_qmlObject, m_qmlShow ); } } } @@ -243,7 +268,7 @@ ExecutionViewStep::loadQmlV2Complete() void ExecutionViewStep::onActivate() { - activateSlideShow( m_qmlObject, m_qmlShow ); + changeSlideShowState( Slideshow::Start, m_qmlObject, m_qmlShow ); JobQueue* queue = JobQueue::instance(); foreach ( const QString& instanceKey, m_jobInstanceKeys ) @@ -291,10 +316,10 @@ ExecutionViewStep::updateFromJobQueue( qreal percent, const QString& message ) void ExecutionViewStep::onLeave() { + changeSlideShowState( Slideshow::Stop, m_qmlObject, m_qmlShow ); // API version 2 is explicitly stopped; version 1 keeps running if ( Branding::instance()->slideshowAPI() == 2 ) { - callQMLFunction( m_qmlObject, "onLeave" ); delete m_qmlObject; m_qmlObject = nullptr; } From 03ac0d2cf0f9701e0edbd2cdf2a0ba7544b865cb Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 27 Aug 2019 15:54:06 +0200 Subject: [PATCH 282/302] [qml] Document the new property and how it updates --- CHANGES | 3 +++ src/branding/README.md | 10 ++++++++++ src/branding/default/show.qml | 14 +++++++++----- src/qml/calamares/slideshow/Presentation.qml | 8 +++++++- 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index 66323ff9f..02a7fc4f5 100644 --- a/CHANGES +++ b/CHANGES @@ -20,6 +20,9 @@ This release contains contributions from (alphabetically by first name): (maintained!) upstream version instead. It also gives us KMacroExpander everywhere, which will simplify code for handling substitutions in configuration files. +- *Slideshows* now have a new property *activatedInCalamares* which + controls the keyboard shortcuts (and can control timers and other + properties of the slideshow, too). ## Modules ## diff --git a/src/branding/README.md b/src/branding/README.md index 1b9eb57fd..099163836 100644 --- a/src/branding/README.md +++ b/src/branding/README.md @@ -66,6 +66,16 @@ The setting *slideshowAPI* in `branding.desc` indicates which one to use for a given branding slideshow. Which API to use is really a function of the QML. Expect the version 1 API to be deprecated in the course of Calamares 3.3. +In Calamares 3.2.13 support for activation notification to the QML +parts is improved: + - If the root object has a property *activatedInCalamares* (the examples do), + then that property is set to *true* when the slideshow becomes visible + (activated) and is set to *false* when the slideshow is hidden (e.g. + when the installation phase is done). + - The *actvatedInCalamares* property can be used to set up timers also in V1. + - The keyboard shortcuts in the example slideshow are enabled only while + the slideshow is visible. + ## Translations diff --git a/src/branding/default/show.qml b/src/branding/default/show.qml index 1a174f0b6..dcb0f9257 100644 --- a/src/branding/default/show.qml +++ b/src/branding/default/show.qml @@ -32,7 +32,7 @@ Presentation Timer { id: advanceTimer interval: 1000 - running: false + running: presentation.activatedInCalamares repeat: true onTriggered: nextSlide() } @@ -68,15 +68,19 @@ Presentation centeredText: qsTr("This is a third Slide element.") } + // When this slideshow is loaded as a V1 slideshow, only + // activatedInCalamares is set, which starts the timer (see above). + // + // In V2, also the onActivate() and onLeave() methods are called. + // These example functions log a message (and re-start the slides + // from the first). function onActivate() { - presentation.currentSlide = 0; - presentation.activatedInCalamares = true; - advanceTimer.running = true; console.log("QML Component (default slideshow) activated"); + presentation.currentSlide = 0; } function onLeave() { - presentation.activatedInCalamares = true; + console.log("QML Component (default slideshow) deactivated"); } } diff --git a/src/qml/calamares/slideshow/Presentation.qml b/src/qml/calamares/slideshow/Presentation.qml index a4138d588..1d2fd9c85 100644 --- a/src/qml/calamares/slideshow/Presentation.qml +++ b/src/qml/calamares/slideshow/Presentation.qml @@ -80,7 +80,13 @@ Item { property string fontFamily: "Helvetica" property string codeFontFamily: "Courier New" - property bool activatedInCalamares: false; + // This is set by the C++ part of Calamares when the slideshow + // becomes visible. You can connect it to a timer, or whatever + // else needs to start only when the slideshow becomes visible. + // + // It is used in this example also to keep the keyboard shortcuts + // enabled only while the slideshow is active. + property bool activatedInCalamares: false // Private API property int _lastShownSlide: 0 From 8ab0fb4e5f7b08b1ca4a967cc4ba25a72d9e916c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 27 Aug 2019 15:58:09 +0200 Subject: [PATCH 283/302] [libcalamaresui] Apply coding style (missed earlier) --- src/libcalamaresui/Branding.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libcalamaresui/Branding.cpp b/src/libcalamaresui/Branding.cpp index c0ee71089..edbced5fa 100644 --- a/src/libcalamaresui/Branding.cpp +++ b/src/libcalamaresui/Branding.cpp @@ -226,7 +226,9 @@ Branding::Branding( const QString& brandingFilePath, QObject* parent ) QString pathString = slideShowPictures[ i ]; QFileInfo imageFi( componentDir.absoluteFilePath( pathString ) ); if ( !imageFi.exists() ) + { bail( QString( "Slideshow file %1 does not exist." ).arg( imageFi.absoluteFilePath() ) ); + } slideShowPictures[ i ] = imageFi.absoluteFilePath(); } From e459b82cfeb6f9a57ae483603521bc95c3a8f0e2 Mon Sep 17 00:00:00 2001 From: bill-auger Date: Mon, 26 Aug 2019 08:34:24 -0400 Subject: [PATCH 284/302] fix typo in src/libcalamaresui/ViewManager.cpp --- src/libcalamaresui/ViewManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcalamaresui/ViewManager.cpp b/src/libcalamaresui/ViewManager.cpp index 7baefdbd0..48c71a7ac 100644 --- a/src/libcalamaresui/ViewManager.cpp +++ b/src/libcalamaresui/ViewManager.cpp @@ -140,7 +140,7 @@ ViewManager::ViewManager( QObject* parent ) m_quit->setVisible( false ); } - // onInstallationFailed( "Tile of Failure", "Body of Failure"); // for testing paste functionality + // onInstallationFailed( "Title of Failure", "Body of Failure"); // for testing paste functionality } From 13a58a4ab289d50e7bc12a78e9768c88c9d4dfed Mon Sep 17 00:00:00 2001 From: bill-auger Date: Mon, 26 Aug 2019 08:34:35 -0400 Subject: [PATCH 285/302] update doc comment in src/modules/initcpio/initcpio.conf --- src/modules/initcpio/initcpio.conf | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/modules/initcpio/initcpio.conf b/src/modules/initcpio/initcpio.conf index 8ad71e9f5..517e48392 100644 --- a/src/modules/initcpio/initcpio.conf +++ b/src/modules/initcpio/initcpio.conf @@ -1,8 +1,7 @@ # Run mkinitcpio(8) with the given preset value --- -# There is only one configuration item for this module, -# the kernel to be loaded. This can have the following -# values: +# This key defines the kernel to be loaded. +# It can have the following values: # - empty or unset, interpreted as "all" # - the literal string "$uname" (without quotes, with dollar), # which will use the output of `uname -r` to determine the From 4c3c6f3f91128a33ba4811df89a9f49bc7c6016c Mon Sep 17 00:00:00 2001 From: bill-auger Date: Wed, 28 Aug 2019 02:47:24 -0400 Subject: [PATCH 286/302] eliminate magic number in src/modules/welcome/WelcomePage.cpp --- src/modules/welcome/WelcomePage.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/modules/welcome/WelcomePage.cpp b/src/modules/welcome/WelcomePage.cpp index 8f989c47c..9c520a7fa 100644 --- a/src/modules/welcome/WelcomePage.cpp +++ b/src/modules/welcome/WelcomePage.cpp @@ -124,7 +124,8 @@ WelcomePage::WelcomePage( QWidget* parent ) mb.exec(); } ); - ui->verticalLayout->insertWidget( 3, m_checkingWidget ); + int welcome_text_idx = ui->verticalLayout->indexOf( ui->mainText ); + ui->verticalLayout->insertWidget( welcome_text_idx + 1, m_checkingWidget ); } From bb678e535b4a9340c61f9804d52b9791aff6bdaa Mon Sep 17 00:00:00 2001 From: bill-auger Date: Mon, 26 Aug 2019 07:07:18 -0400 Subject: [PATCH 287/302] add esperanto branding translations, fix mis-configured ones --- .../default/lang/calamares-default_ar.ts | 4 ++-- .../default/lang/calamares-default_en.ts | 2 +- .../default/lang/calamares-default_eo.ts | 17 +++++++++++++++++ .../default/lang/calamares-default_fr.ts | 4 ++-- .../default/lang/calamares-default_nl.ts | 2 +- 5 files changed, 23 insertions(+), 6 deletions(-) create mode 100644 src/branding/default/lang/calamares-default_eo.ts diff --git a/src/branding/default/lang/calamares-default_ar.ts b/src/branding/default/lang/calamares-default_ar.ts index 05463dd72..3c4fe0933 100644 --- a/src/branding/default/lang/calamares-default_ar.ts +++ b/src/branding/default/lang/calamares-default_ar.ts @@ -1,6 +1,6 @@ - + show @@ -11,7 +11,7 @@ This is a third Slide element. - عرض الثالث + عرض الثالث diff --git a/src/branding/default/lang/calamares-default_en.ts b/src/branding/default/lang/calamares-default_en.ts index 30474fc02..b02dbd5b1 100644 --- a/src/branding/default/lang/calamares-default_en.ts +++ b/src/branding/default/lang/calamares-default_en.ts @@ -1,6 +1,6 @@ - + show diff --git a/src/branding/default/lang/calamares-default_eo.ts b/src/branding/default/lang/calamares-default_eo.ts new file mode 100644 index 000000000..7d1ef4e82 --- /dev/null +++ b/src/branding/default/lang/calamares-default_eo.ts @@ -0,0 +1,17 @@ + + + + + show + + + This is a second Slide element. + Ĉi tio estas la dua gliteja. + + + + This is a third Slide element. + Ĉi tio estas la tria gliteja. + + + diff --git a/src/branding/default/lang/calamares-default_fr.ts b/src/branding/default/lang/calamares-default_fr.ts index 9329e61ee..ec5e0411a 100644 --- a/src/branding/default/lang/calamares-default_fr.ts +++ b/src/branding/default/lang/calamares-default_fr.ts @@ -1,6 +1,6 @@ - + show @@ -11,7 +11,7 @@ This is a third Slide element. - La troisième affice ce trouve ici. + La troisième affice ce trouve ici. diff --git a/src/branding/default/lang/calamares-default_nl.ts b/src/branding/default/lang/calamares-default_nl.ts index aad00eaf7..19fd58361 100644 --- a/src/branding/default/lang/calamares-default_nl.ts +++ b/src/branding/default/lang/calamares-default_nl.ts @@ -11,7 +11,7 @@ This is a third Slide element. - Dit is het derde Dia element. + Dit is het derde Dia element. From 5642576cf33857aba43ca1710d196a68c394e794 Mon Sep 17 00:00:00 2001 From: bill-auger Date: Wed, 28 Aug 2019 07:38:49 -0400 Subject: [PATCH 288/302] cross-reference/clarify geoip documentation --- src/modules/locale/LocaleViewStep.cpp | 2 +- src/modules/locale/locale.conf | 12 +++++++++--- src/modules/welcome/welcome.conf | 12 ++++++------ 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/modules/locale/LocaleViewStep.cpp b/src/modules/locale/LocaleViewStep.cpp index 29006ec33..ee5c7699b 100644 --- a/src/modules/locale/LocaleViewStep.cpp +++ b/src/modules/locale/LocaleViewStep.cpp @@ -235,7 +235,7 @@ LocaleViewStep::setConfigurationMap( const QVariantMap& configurationMap ) } else { - // Optional + // Accommodate deprecated geoip configuration m_geoipUrl = CalamaresUtils::getString( configurationMap, "geoipUrl" ); m_geoipStyle = CalamaresUtils::getString( configurationMap, "geoipStyle" ); m_geoipSelector = CalamaresUtils::getString( configurationMap, "geoipSelector" ); diff --git a/src/modules/locale/locale.conf b/src/modules/locale/locale.conf index 7c2ec332c..4beb4fe85 100644 --- a/src/modules/locale/locale.conf +++ b/src/modules/locale/locale.conf @@ -23,6 +23,7 @@ zone: "New_York" # # Enable only when your Distribution is using an # custom path for locale.gen +# #localeGenPath: "PATH_TO/locale.gen" # GeoIP based Language settings: Leave commented out to disable GeoIP. @@ -78,14 +79,19 @@ zone: "New_York" # Europe/Brussels # ``` # -# To accomodate providers of GeoIP timezone data with peculiar timezone +# To accommodate providers of GeoIP timezone data with peculiar timezone # naming conventions, the following cleanups are performed automatically: # - backslashes are removed # - spaces are replaced with _ # # Legacy settings "geoipStyle", "geoipUrl" and "geoipSelector" # in the top-level are still supported, but I'd advise against. +# +# 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/welcome/welcome.conf. +# geoip: - style: "json" - url: "https://geoip.kde.org/v1/calamares" + style: "json" + url: "https://geoip.kde.org/v1/calamares" selector: "" # leave blank for the default diff --git a/src/modules/welcome/welcome.conf b/src/modules/welcome/welcome.conf index 9488daa5e..0361830aa 100644 --- a/src/modules/welcome/welcome.conf +++ b/src/modules/welcome/welcome.conf @@ -69,13 +69,13 @@ requirements: # 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, either comment-out the entire section, or set -# the *style* key to an unsupported format (e.g. `none`, as is -# done here). - +# 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. +# geoip: - style: "none" - url: "https://geoip.kde.org/v1/ubiquity" # extended XML format + style: "none" + url: "https://geoip.kde.org/v1/ubiquity" # extended XML format selector: "CountryCode" # blank uses default, which is wrong # User interface From fc5aa54cb2f18332a8c657ccfad3437944bff534 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 29 Aug 2019 11:01:02 +0200 Subject: [PATCH 289/302] [welcome] Fix code formatting - the RETRANSLATE macro is a real challenge for astyle and clang-format --- src/modules/welcome/WelcomePage.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/modules/welcome/WelcomePage.cpp b/src/modules/welcome/WelcomePage.cpp index 9c520a7fa..05c955a2d 100644 --- a/src/modules/welcome/WelcomePage.cpp +++ b/src/modules/welcome/WelcomePage.cpp @@ -76,13 +76,18 @@ WelcomePage::WelcomePage( QWidget* parent ) CALAMARES_RETRANSLATE( QString message; - if ( Calamares::Settings::instance()->isSetupMode() ) message - = Calamares::Branding::instance()->welcomeStyleCalamares() - ? 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.

" ); + if ( Calamares::Settings::instance()->isSetupMode() ) + { + message = Calamares::Branding::instance()->welcomeStyleCalamares() + ? 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.

" ); + } ui->mainText->setText( message.arg( *Calamares::Branding::VersionedName ) ); ui->retranslateUi( this ); From 535bf01475d0cedccec76ea6724726b59a7e1b28 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 29 Aug 2019 11:06:55 +0200 Subject: [PATCH 290/302] [welcome] Refactor lambdas to full slots - This helps give meaningful names to code chunks - Gives clang-format something to work with - Reduces indentation depth I think this is a bit of a code-style opinion issue: big complicated lambdas doing UI things just don't seem like a good idea. --- src/modules/welcome/WelcomePage.cpp | 111 +++++++++++++++------------- src/modules/welcome/WelcomePage.h | 4 + 2 files changed, 65 insertions(+), 50 deletions(-) diff --git a/src/modules/welcome/WelcomePage.cpp b/src/modules/welcome/WelcomePage.cpp index 05c955a2d..f46300097 100644 --- a/src/modules/welcome/WelcomePage.cpp +++ b/src/modules/welcome/WelcomePage.cpp @@ -73,61 +73,13 @@ WelcomePage::WelcomePage( QWidget* parent ) cDebug() << "Welcome string" << Calamares::Branding::instance()->welcomeStyleCalamares() << *Calamares::Branding::VersionedName; - CALAMARES_RETRANSLATE( - QString message; - - if ( Calamares::Settings::instance()->isSetupMode() ) - { - message = Calamares::Branding::instance()->welcomeStyleCalamares() - ? 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.

" ); - } - - ui->mainText->setText( message.arg( *Calamares::Branding::VersionedName ) ); - ui->retranslateUi( this ); - ui->supportButton->setText( tr( "%1 support" ).arg( *Calamares::Branding::ShortProductName ) ); ) + CALAMARES_RETRANSLATE( retranslate(); ) ui->aboutButton->setIcon( CalamaresUtils::defaultPixmap( CalamaresUtils::Information, CalamaresUtils::Original, 2 * QSize( CalamaresUtils::defaultFontHeight(), CalamaresUtils::defaultFontHeight() ) ) ); - connect( ui->aboutButton, &QPushButton::clicked, this, [this] { - QString title - = Calamares::Settings::instance()->isSetupMode() ? tr( "About %1 setup" ) : tr( "About %1 installer" ); - QMessageBox mb( QMessageBox::Information, - title.arg( CALAMARES_APPLICATION_NAME ), - tr( "

%1


" - "%2
" - "for %3


" - "Copyright 2014-2017 Teo Mrnjavac <teo@kde.org>
" - "Copyright 2017-2019 Adriaan de Groot <groot@kde.org>
" - "Thanks to the Calamares team " - "and the Calamares " - "translators team.

" - "Calamares " - "development is sponsored by
" - "Blue Systems - " - "Liberating Software." ) - .arg( CALAMARES_APPLICATION_NAME ) - .arg( CALAMARES_VERSION ) - .arg( *Calamares::Branding::VersionedName ), - QMessageBox::Ok, - this ); - mb.setIconPixmap( CalamaresUtils::defaultPixmap( - CalamaresUtils::Squid, - CalamaresUtils::Original, - QSize( CalamaresUtils::defaultFontHeight() * 6, CalamaresUtils::defaultFontHeight() * 6 ) ) ); - QGridLayout* layout = reinterpret_cast< QGridLayout* >( mb.layout() ); - if ( layout ) - layout->setColumnMinimumWidth( 2, CalamaresUtils::defaultFontHeight() * 24 ); - mb.exec(); - } ); + connect( ui->aboutButton, &QPushButton::clicked, this, &WelcomePage::showAboutBox ); int welcome_text_idx = ui->verticalLayout->indexOf( ui->mainText ); ui->verticalLayout->insertWidget( welcome_text_idx + 1, m_checkingWidget ); @@ -284,6 +236,65 @@ WelcomePage::setLanguageIcon( QPixmap i ) ui->languageIcon->setPixmap( i ); } +void +WelcomePage::retranslate() +{ + QString message; + + if ( Calamares::Settings::instance()->isSetupMode() ) + { + message = Calamares::Branding::instance()->welcomeStyleCalamares() + ? 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.

" ); + } + + ui->mainText->setText( message.arg( *Calamares::Branding::VersionedName ) ); + ui->retranslateUi( this ); + ui->supportButton->setText( tr( "%1 support" ).arg( *Calamares::Branding::ShortProductName ) ); +} + +void +WelcomePage::showAboutBox() +{ + QString title + = Calamares::Settings::instance()->isSetupMode() ? tr( "About %1 setup" ) : tr( "About %1 installer" ); + QMessageBox mb( QMessageBox::Information, + title.arg( CALAMARES_APPLICATION_NAME ), + tr( "

%1


" + "%2
" + "for %3


" + "Copyright 2014-2017 Teo Mrnjavac <teo@kde.org>
" + "Copyright 2017-2019 Adriaan de Groot <groot@kde.org>
" + "Thanks to the Calamares team " + "and the Calamares " + "translators team.

" + "Calamares " + "development is sponsored by
" + "Blue Systems - " + "Liberating Software." ) + .arg( CALAMARES_APPLICATION_NAME ) + .arg( CALAMARES_VERSION ) + .arg( *Calamares::Branding::VersionedName ), + QMessageBox::Ok, + this ); + mb.setIconPixmap( CalamaresUtils::defaultPixmap( + CalamaresUtils::Squid, + CalamaresUtils::Original, + QSize( CalamaresUtils::defaultFontHeight() * 6, CalamaresUtils::defaultFontHeight() * 6 ) ) ); + QGridLayout* layout = reinterpret_cast< QGridLayout* >( mb.layout() ); + if ( layout ) + { + layout->setColumnMinimumWidth( 2, CalamaresUtils::defaultFontHeight() * 24 ); + } + mb.exec(); +} + void LocaleTwoColumnDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const diff --git a/src/modules/welcome/WelcomePage.h b/src/modules/welcome/WelcomePage.h index 3e776a5f0..3e20ab9ea 100644 --- a/src/modules/welcome/WelcomePage.h +++ b/src/modules/welcome/WelcomePage.h @@ -58,6 +58,10 @@ public: /// @brief Change the language from an external source. void externallySelectedLanguage( int row ); +public slots: + void retranslate(); + void showAboutBox(); + protected: void focusInEvent( QFocusEvent* e ) override; //choose the child widget to focus From e3f933259b57183311620dd02966856480213b33 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 29 Aug 2019 14:46:16 +0200 Subject: [PATCH 291/302] CMake: missing return statement should be an error --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 321989ac0..644427d16 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -198,6 +198,7 @@ if( CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) -Wno-missing-prototypes -Wno-documentation-unknown-command -Wno-unknown-warning-option + -Werror=return-type ) string( APPEND CMAKE_CXX_FLAGS " ${CLANG_WARNINGS}" ) endforeach() From f1971eed86ba230fff69c0f3c7b80a2b2e96819e Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 29 Aug 2019 14:53:03 +0200 Subject: [PATCH 292/302] [libcalamares] Support calling a slot on retranslation - sometimes a slot is easier than a lambda. Introduce a macro CALAMARES_RETRANSLATE_SLOT that calls a given slot in an object on language change. - extend the retranslator with support for calling slots: - use Qt's signal/slot mechanism alongside the private list of functions to call - provide convenience for obtaining the retranslator of an object. --- src/libcalamares/utils/Retranslator.cpp | 18 ++++++++++-------- src/libcalamares/utils/Retranslator.h | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/libcalamares/utils/Retranslator.cpp b/src/libcalamares/utils/Retranslator.cpp index e154350b9..d761263ac 100644 --- a/src/libcalamares/utils/Retranslator.cpp +++ b/src/libcalamares/utils/Retranslator.cpp @@ -118,8 +118,8 @@ translatorLocaleName() return s_translatorLocaleName; } -void -Retranslator::attachRetranslator( QObject* parent, std::function< void( void ) > retranslateFunc ) +Retranslator* +Retranslator::retranslatorFor( QObject* parent ) { Retranslator* r = nullptr; for ( QObject* child : parent->children() ) @@ -127,16 +127,17 @@ Retranslator::attachRetranslator( QObject* parent, std::function< void( void ) > r = qobject_cast< Retranslator* >( child ); if ( r ) { - break; + return r; } } - if ( !r ) - { - r = new Retranslator( parent ); - } + return new Retranslator( parent ); +} - r->m_retranslateFuncList.append( retranslateFunc ); +void +Retranslator::attachRetranslator( QObject* parent, std::function< void( void ) > retranslateFunc ) +{ + retranslatorFor( parent )->m_retranslateFuncList.append( retranslateFunc ); retranslateFunc(); } @@ -159,6 +160,7 @@ Retranslator::eventFilter( QObject* obj, QEvent* e ) { func(); } + emit languageChange(); } } // pass the event on to the base diff --git a/src/libcalamares/utils/Retranslator.h b/src/libcalamares/utils/Retranslator.h index 32e8dcf41..58c60b761 100644 --- a/src/libcalamares/utils/Retranslator.h +++ b/src/libcalamares/utils/Retranslator.h @@ -46,10 +46,17 @@ class Retranslator : public QObject { Q_OBJECT public: + /// @brief Call @p retranslateFunc when the language changes static void attachRetranslator( QObject* parent, std::function< void( void ) > retranslateFunc ); + /// @brief What retranslator belongs to @p parent (may create one) + static Retranslator* retranslatorFor( QObject* parent ); + /// @brief Call @p retranslateFunc when the language changes void addRetranslateFunc( std::function< void( void ) > retranslateFunc ); +signals: + void languageChange(); + protected: bool eventFilter( QObject* obj, QEvent* e ) override; @@ -65,5 +72,12 @@ private: #define CALAMARES_RETRANSLATE( body ) CalamaresUtils::Retranslator::attachRetranslator( this, [=] { body } ); #define CALAMARES_RETRANSLATE_WIDGET( widget, body ) \ CalamaresUtils::Retranslator::attachRetranslator( widget, [=] { body } ); +#define CALAMARES_RETRANSLATE_SLOT( slotfunc ) \ + { \ + this->connect( CalamaresUtils::Retranslator::retranslatorFor( this ), \ + &CalamaresUtils::Retranslator::languageChange, \ + this, \ + slotfunc ); \ + } #endif From 1cde8c20dfa4a23b08d21787992b24519a60b295 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 29 Aug 2019 15:01:41 +0200 Subject: [PATCH 293/302] [libcalamaresui] Simplify retranslation - Use any object method to connect() to --- src/libcalamaresui/ViewManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcalamaresui/ViewManager.cpp b/src/libcalamaresui/ViewManager.cpp index 48c71a7ac..8fb832369 100644 --- a/src/libcalamaresui/ViewManager.cpp +++ b/src/libcalamaresui/ViewManager.cpp @@ -112,7 +112,7 @@ ViewManager::ViewManager( QObject* parent ) m_next = makeButton( m_widget, "go-next" ); m_quit = makeButton( m_widget, "dialog-cancel" ); - CALAMARES_RETRANSLATE( updateButtonLabels(); ) + CALAMARES_RETRANSLATE_SLOT( &ViewManager::updateButtonLabels ) QBoxLayout* bottomLayout = new QHBoxLayout; mainLayout->addLayout( bottomLayout ); From 0aabc894496d40aa013cd98c244fa56ffdf1a5af Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 29 Aug 2019 15:02:12 +0200 Subject: [PATCH 294/302] [partition] [welcome] Simplify retranslation --- src/modules/partition/gui/DeviceInfoWidget.cpp | 2 +- src/modules/welcome/WelcomePage.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/partition/gui/DeviceInfoWidget.cpp b/src/modules/partition/gui/DeviceInfoWidget.cpp index 4d37e3b39..ea318e85c 100644 --- a/src/modules/partition/gui/DeviceInfoWidget.cpp +++ b/src/modules/partition/gui/DeviceInfoWidget.cpp @@ -65,7 +65,7 @@ DeviceInfoWidget::DeviceInfoWidget( QWidget* parent ) m_ptIcon->setPalette( palette ); m_ptLabel->setPalette( palette ); - CALAMARES_RETRANSLATE( retranslateUi(); ) + CALAMARES_RETRANSLATE_SLOT( &DeviceInfoWidget::retranslateUi ) } diff --git a/src/modules/welcome/WelcomePage.cpp b/src/modules/welcome/WelcomePage.cpp index f46300097..02f91f79f 100644 --- a/src/modules/welcome/WelcomePage.cpp +++ b/src/modules/welcome/WelcomePage.cpp @@ -73,7 +73,7 @@ WelcomePage::WelcomePage( QWidget* parent ) cDebug() << "Welcome string" << Calamares::Branding::instance()->welcomeStyleCalamares() << *Calamares::Branding::VersionedName; - CALAMARES_RETRANSLATE( retranslate(); ) + CALAMARES_RETRANSLATE_SLOT( &WelcomePage::retranslate ) ui->aboutButton->setIcon( CalamaresUtils::defaultPixmap( CalamaresUtils::Information, From 61482b38cc5382727ebedae22694851ff5664dd3 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 29 Aug 2019 16:28:00 +0200 Subject: [PATCH 295/302] Changes: give credit for this cycle --- CHANGES | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index 02a7fc4f5..f12963214 100644 --- a/CHANGES +++ b/CHANGES @@ -8,6 +8,8 @@ website will have to do for older versions. This release contains contributions from (alphabetically by first name): - Arnaud Ferraris - Arnaud Rebillout + - Bill Auger + - Kevin Kofler ## Core ## From 9053b9cecf900590e81332e6325c9791325fe018 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 30 Aug 2019 06:20:45 -0400 Subject: [PATCH 296/302] [libcalamares] Fix Qt 5.9 compatibility - not really sure why I went for the Qt 5.10 STL-style iterators FIXES #1236 --- src/libcalamares/locale/TranslatableConfiguration.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libcalamares/locale/TranslatableConfiguration.cpp b/src/libcalamares/locale/TranslatableConfiguration.cpp index 7493c836c..bc39c398e 100644 --- a/src/libcalamares/locale/TranslatableConfiguration.cpp +++ b/src/libcalamares/locale/TranslatableConfiguration.cpp @@ -40,9 +40,9 @@ TranslatedString::TranslatedString( const QVariantMap& map, const QString& key ) QString value = CalamaresUtils::getString( map, key ); m_strings[ QString() ] = value; - for ( auto it = map.constKeyValueBegin(); it != map.constKeyValueEnd(); ++it ) + for ( auto it = map.constBegin(); it != map.constEnd(); ++it ) { - QString subkey = ( *it ).first; + QString subkey = it.key(); if ( subkey == key ) { // Already obtained, above @@ -53,7 +53,7 @@ TranslatedString::TranslatedString( const QVariantMap& map, const QString& key ) if ( subkey.indexOf( QRegularExpression( "\\[([a-zA-Z_@]*)\\]" ), 0, &match ) > 0 ) { QString language = match.captured( 1 ); - m_strings[ language ] = ( *it ).second.toString(); + m_strings[ language ] = it.value().toString(); } } } From 66ee6ac6734242b03f001a14f4669c3fe71005ab Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 30 Aug 2019 06:35:53 -0400 Subject: [PATCH 297/302] [libcalamares] Fix tests for umask != 022 - My usual test environment has umask set to 022, but on one dev box it is 002, leading to test failures (which show the test was bad, not that the umask-setting code is bad) --- src/libcalamares/utils/Tests.cpp | 4 +++- src/libcalamares/utils/UMask.h | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/libcalamares/utils/Tests.cpp b/src/libcalamares/utils/Tests.cpp index 0f7d6cd81..97edd0bc4 100644 --- a/src/libcalamares/utils/Tests.cpp +++ b/src/libcalamares/utils/Tests.cpp @@ -155,8 +155,10 @@ LibCalamaresTests::testUmask() QTemporaryFile ft; QVERIFY( ft.open() ); + // m gets the previous value of the mask (depends on the environment the + // test is run in, might be 002, might be 077), .. mode_t m = CalamaresUtils::setUMask( 022 ); - QCOMPARE( CalamaresUtils::setUMask( m ), m ); + QCOMPARE( CalamaresUtils::setUMask( m ), 022 ); // But now most recently set was 022 for ( mode_t i = 0; i <= 0777 /* octal! */; ++i ) { diff --git a/src/libcalamares/utils/UMask.h b/src/libcalamares/utils/UMask.h index 58b1a56ad..752c8b066 100644 --- a/src/libcalamares/utils/UMask.h +++ b/src/libcalamares/utils/UMask.h @@ -25,7 +25,10 @@ namespace CalamaresUtils { -/// @brief Wrapper for umask(2) +/** @brief Wrapper for umask(2) + * + * Like umask(2), sets the umask and returns the previous value of the mask. + */ DLLEXPORT mode_t setUMask( mode_t u ); /** @brief RAII for setting and re-setting umask. From f156a683a81e7775ad6a573f76cbb243eb2ad6d6 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 30 Aug 2019 06:41:48 -0400 Subject: [PATCH 298/302] Changes: pre-release housekeeping --- CHANGES | 4 +++- CMakeLists.txt | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index f12963214..3921b21e2 100644 --- a/CHANGES +++ b/CHANGES @@ -3,7 +3,8 @@ 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.13 (unreleased) # + +# 3.2.13 (2019-08-30) # This release contains contributions from (alphabetically by first name): - Arnaud Ferraris @@ -39,6 +40,7 @@ This release contains contributions from (alphabetically by first name): - The *welcome* module can have URLs for the various buttons configured directly in the module configuration (rather than in `branding.desc`). + # 3.2.12 (2019-08-07) # This release contains contributions from (alphabetically by first name): diff --git a/CMakeLists.txt b/CMakeLists.txt index 644427d16..f48dda135 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,7 +43,7 @@ project( CALAMARES VERSION 3.2.13 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 64a5a30199c1261bd9421c3cc6ffd3e27f0d68cf Mon Sep 17 00:00:00 2001 From: Calamares CI Date: Fri, 30 Aug 2019 13:17:14 +0200 Subject: [PATCH 299/302] i18n: [calamares] Automatic merge of Transifex translations --- lang/calamares_be.ts | 64 ++++++++++++++++++++--------------------- lang/calamares_it_IT.ts | 46 ++++++++++++++--------------- lang/calamares_pt_PT.ts | 8 +++--- lang/calamares_ru.ts | 2 +- 4 files changed, 60 insertions(+), 60 deletions(-) diff --git a/lang/calamares_be.ts b/lang/calamares_be.ts index 543313cfc..71b4c9da1 100644 --- a/lang/calamares_be.ts +++ b/lang/calamares_be.ts @@ -22,27 +22,27 @@ Master Boot Record of %1 - + Галоўны загрузачны запіс %1 Boot Partition - + Загрузачны раздзел System Partition - + Сістэмны раздзел Do not install a boot loader - + Не ўсталёўваць загрузчык %1 (%2) - + %1 (%2) @@ -50,7 +50,7 @@ Blank Page - + Пустая старонка @@ -58,58 +58,58 @@ Form - + Форма GlobalStorage - + Глабальнае сховішча JobQueue - + Чарга задач Modules - + Модулі Type: - + Тып: none - + няма Interface: - + Інтэрфейс: Tools - + Інструменты Reload Stylesheet - + Перазагрузіць табліцу стыляў Widget Tree - + Дрэва віджэтаў Debug information - + Адладачная інфармацыя @@ -117,12 +117,12 @@ Set up - + Наладзіць Install - + Усталяваць @@ -130,7 +130,7 @@ Job failed (%1) - + Задача схібіла (%1) @@ -432,7 +432,7 @@ The installer will quit and all changes will be lost. Form - + Форма @@ -1035,7 +1035,7 @@ The installer will quit and all changes will be lost. Form - + Форма @@ -1101,7 +1101,7 @@ The installer will quit and all changes will be lost. Form - + Форма @@ -1375,7 +1375,7 @@ The installer will quit and all changes will be lost. Form - + Форма @@ -1869,7 +1869,7 @@ The installer will quit and all changes will be lost. Form - + Форма @@ -1887,7 +1887,7 @@ The installer will quit and all changes will be lost. Form - + Форма @@ -2024,7 +2024,7 @@ The installer will quit and all changes will be lost. Form - + Форма @@ -2224,7 +2224,7 @@ The installer will quit and all changes will be lost. Form - + Форма @@ -2381,7 +2381,7 @@ Output: %1 (%2) language[name] (country[name]) - + %1 (%2) @@ -2408,7 +2408,7 @@ Output: Form - + Форма @@ -2969,7 +2969,7 @@ Output: Form - + Форма @@ -3125,7 +3125,7 @@ Output: Form - + Форма diff --git a/lang/calamares_it_IT.ts b/lang/calamares_it_IT.ts index e55ebf7dd..37ed30e6c 100644 --- a/lang/calamares_it_IT.ts +++ b/lang/calamares_it_IT.ts @@ -117,7 +117,7 @@ Set up - + Installazione @@ -159,12 +159,12 @@ Run command '%1' in target system. - + Esegui il comando '%1' sul sistema di destinazione Run command '%1'. - + Esegui il comando '1%' @@ -243,7 +243,7 @@ Cancel setup without changing the system. - + Annulla l'installazione senza modificare il computer @@ -253,7 +253,7 @@ Setup Failed - + Installazione fallita @@ -273,22 +273,22 @@ Continue with installation? - + Continuare l'installazione? 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> - + Il %1 programma di installazione sta per fare dei cambiamenti sul tuo disco per installare %2. Non sarà possibile annullare questi cambiamenti. &Set up now - + &Installa adesso &Set up - + &Installazione @@ -298,12 +298,12 @@ Setup is complete. Close the setup program. - + Installazione completata. Chiudere il programma di installazione. Cancel setup? - + Annullare l'installazione? @@ -314,7 +314,7 @@ Do you really want to cancel the current setup process? The setup program will quit and all changes will be lost. - + Vuoi davvero annullare il processo di installazione? Il programma di installazione verrrà terminato e tutti i cambiamenti verranno persi. @@ -407,7 +407,7 @@ Il programma d'installazione sarà terminato e tutte le modifiche andranno %1 Setup Program - + %1 Programma di installazione @@ -476,7 +476,7 @@ Il programma d'installazione sarà terminato e tutte le modifiche andranno %1 will be shrunk to %2MiB and a new %3MiB partition will be created for %4. - + %1 sarà ridotta a %2MiB ed una nuova partizione di %3MiB sarà creata per %4 @@ -719,7 +719,7 @@ Il programma d'installazione sarà terminato e tutte le modifiche andranno Create new %2MiB partition on %4 (%3) with file system %1. - + Crea una nuova partizione da %2MiB su %4 (%3) con file system %1 @@ -1155,7 +1155,7 @@ Il programma d'installazione sarà terminato e tutte le modifiche andranno Setup Complete - + Installazione completata @@ -1165,7 +1165,7 @@ Il programma d'installazione sarà terminato e tutte le modifiche andranno The setup of %1 is complete. - + L'installazione di %1 è completa @@ -1201,22 +1201,22 @@ Il programma d'installazione sarà terminato e tutte le modifiche andranno has at least %1 GiB available drive space - + ha almeno %1 GiB di spazio disponibile There is not enough drive space. At least %1 GiB is required. - + Non c'è abbastanza spazio sul disco. E' richiesto almeno %1 GiB has at least %1 GiB working memory - + ha almeno %1 GiB di memoria The system does not have enough working memory. At least %1 GiB is required. - + Il sistema non ha abbastanza memoria. E' richiesto almeno %1 GiB @@ -1241,7 +1241,7 @@ Il programma d'installazione sarà terminato e tutte le modifiche andranno The setup program is not running with administrator rights. - + Il programma di installazione non è stato lanciato con i permessi di amministratore. @@ -1251,7 +1251,7 @@ Il programma d'installazione sarà terminato e tutte le modifiche andranno The screen is too small to display the setup program. - + Lo schermo è troppo piccolo per mostrare il programma di installazione diff --git a/lang/calamares_pt_PT.ts b/lang/calamares_pt_PT.ts index a727717d2..c8d680dda 100644 --- a/lang/calamares_pt_PT.ts +++ b/lang/calamares_pt_PT.ts @@ -1299,7 +1299,7 @@ O instalador será encerrado e todas as alterações serão perdidas. Creating initramfs. - + A criar o initramfs. @@ -1530,20 +1530,20 @@ O instalador será encerrado e todas as alterações serão perdidas. Configuring LUKS key file. - + A configurar o ficheiro chave do LUKS. No partitions are defined. - + Nenhuma partição é definida. Encrypted rootfs setup error - + Erro de configuração do rootfs criptografado diff --git a/lang/calamares_ru.ts b/lang/calamares_ru.ts index 92533e925..b61661e1a 100644 --- a/lang/calamares_ru.ts +++ b/lang/calamares_ru.ts @@ -3155,7 +3155,7 @@ Output: &About - + &О программе From 36d64b094411570298ae5e041b89962cc6af9d55 Mon Sep 17 00:00:00 2001 From: Calamares CI Date: Fri, 30 Aug 2019 13:17:14 +0200 Subject: [PATCH 300/302] i18n: [python] Automatic merge of Transifex translations --- lang/python/be/LC_MESSAGES/python.mo | Bin 521 -> 9733 bytes lang/python/be/LC_MESSAGES/python.po | 155 +++++++++++++----------- lang/python/es/LC_MESSAGES/python.mo | Bin 2843 -> 2859 bytes lang/python/es/LC_MESSAGES/python.po | 4 +- lang/python/pt_PT/LC_MESSAGES/python.mo | Bin 7452 -> 8279 bytes lang/python/pt_PT/LC_MESSAGES/python.po | 24 ++-- 6 files changed, 98 insertions(+), 85 deletions(-) diff --git a/lang/python/be/LC_MESSAGES/python.mo b/lang/python/be/LC_MESSAGES/python.mo index f068d4290b64b3dbe75ebb3b228d7a407a95a433..475d252c597b0c1a4227f0940f3f6004394b6eed 100644 GIT binary patch literal 9733 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 R)%J0|KI5!Eej4Uz^S?0hvz!0` delta 70 zcmZqm>146EC&V(90SFj@SO$nyfS4JGb$}QIEP(htP|^}egVeylWKF@e&8G#k837pU B2mk;8 diff --git a/lang/python/be/LC_MESSAGES/python.po b/lang/python/be/LC_MESSAGES/python.po index ccb6d0192..5baed9bac 100644 --- a/lang/python/be/LC_MESSAGES/python.po +++ b/lang/python/be/LC_MESSAGES/python.po @@ -3,6 +3,9 @@ # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # +# Translators: +# Zmicer Turok , 2019 +# #, fuzzy msgid "" msgstr "" @@ -10,6 +13,7 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" +"Last-Translator: Zmicer Turok , 2019\n" "Language-Team: Belarusian (https://www.transifex.com/calamares/teams/20061/be/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -19,11 +23,11 @@ msgstr "" #: src/modules/grubcfg/main.py:37 msgid "Configure GRUB." -msgstr "" +msgstr "Наладзіць GRUB." #: src/modules/mount/main.py:38 msgid "Mounting partitions." -msgstr "" +msgstr "Мантаванне раздзелаў." #: src/modules/mount/main.py:150 src/modules/initcpiocfg/main.py:187 #: src/modules/initcpiocfg/main.py:191 @@ -35,164 +39,170 @@ msgstr "" #: src/modules/fstab/main.py:316 src/modules/localecfg/main.py:144 #: src/modules/networkcfg/main.py:48 msgid "Configuration Error" -msgstr "" +msgstr "Памылка канфігурацыі" #: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:188 #: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:172 #: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79 #: src/modules/fstab/main.py:313 msgid "No partitions are defined for
{!s}
to use." -msgstr "" +msgstr "Раздзелы для
{!s}
не вызначаныя." #: src/modules/services-systemd/main.py:35 msgid "Configure systemd services" -msgstr "" +msgstr "Наладзіць службы systemd" #: src/modules/services-systemd/main.py:68 #: src/modules/services-openrc/main.py:102 msgid "Cannot modify service" -msgstr "" +msgstr "Немагчыма наладзіць службу" #: src/modules/services-systemd/main.py:69 msgid "" "systemctl {arg!s} call in chroot returned error code {num!s}." -msgstr "" +msgstr "systemctl {arg!s} у chroot вярнуў код памылкі {num!s}." #: src/modules/services-systemd/main.py:72 #: src/modules/services-systemd/main.py:76 msgid "Cannot enable systemd service {name!s}." -msgstr "" +msgstr "Немагчыма ўключыць службу systemd {name!s}." #: src/modules/services-systemd/main.py:74 msgid "Cannot enable systemd target {name!s}." -msgstr "" +msgstr "Немагчыма ўключыць мэту systemd {name!s}." #: src/modules/services-systemd/main.py:78 msgid "Cannot disable systemd target {name!s}." -msgstr "" +msgstr "Немагчыма выключыць мэту systemd {name!s}." #: src/modules/services-systemd/main.py:80 msgid "Cannot mask systemd unit {name!s}." -msgstr "" +msgstr "Немагчыма замаскаваць юніт systemd {name!s}. " #: src/modules/services-systemd/main.py:82 msgid "" "Unknown systemd commands {command!s} and " "{suffix!s} for unit {name!s}." msgstr "" +"Невядомыя systemd загады {command!s} і {suffix!s} " +"для юніта {name!s}." #: src/modules/umount/main.py:40 msgid "Unmount file systems." -msgstr "" +msgstr "Адмантаваць файлавыя сістэмы." #: src/modules/unpackfs/main.py:41 msgid "Filling up filesystems." -msgstr "" +msgstr "Запаўненне файлавых сістэм." #: src/modules/unpackfs/main.py:159 msgid "rsync failed with error code {}." -msgstr "" +msgstr "памылка rsync з кодам {}." #: src/modules/unpackfs/main.py:220 src/modules/unpackfs/main.py:238 msgid "Failed to unpack image \"{}\"" -msgstr "" +msgstr "Не атрымалася распакаваць вобраз \"{}\"" #: src/modules/unpackfs/main.py:221 msgid "" "Failed to find unsquashfs, make sure you have the squashfs-tools package " "installed" msgstr "" +"Не атрымалася знайсці unsquashfs, праверце ці ўсталяваны ў вас пакунак " +"squashfs-tools" #: src/modules/unpackfs/main.py:320 msgid "No mount point for root partition" -msgstr "" +msgstr "Для каранёвага раздзела няма пункта мантавання" #: src/modules/unpackfs/main.py:321 msgid "globalstorage does not contain a \"rootMountPoint\" key, doing nothing" -msgstr "" +msgstr "globalstorage не змяшчае ключа \"rootMountPoint\", нічога не выконваецца" #: src/modules/unpackfs/main.py:326 msgid "Bad mount point for root partition" -msgstr "" +msgstr "Хібны пункт мантавання для каранёвага раздзела" #: src/modules/unpackfs/main.py:327 msgid "rootMountPoint is \"{}\", which does not exist, doing nothing" -msgstr "" +msgstr "rootMountPoint \"{}\" не існуе, нічога не выконваецца" #: src/modules/unpackfs/main.py:340 src/modules/unpackfs/main.py:347 #: src/modules/unpackfs/main.py:352 msgid "Bad unsquash configuration" -msgstr "" +msgstr "Хібная канфігурацыя unsquash" #: src/modules/unpackfs/main.py:341 msgid "The filesystem for \"{}\" ({}) is not supported" -msgstr "" +msgstr "Файлавая сістэма для \"{}\" ({}) не падтрымліваецца" #: src/modules/unpackfs/main.py:348 msgid "The source filesystem \"{}\" does not exist" -msgstr "" +msgstr "Зыходная файлавая сістэма \"{}\" не існуе" #: src/modules/unpackfs/main.py:353 msgid "The destination \"{}\" in the target system is not a directory" -msgstr "" +msgstr "Пункт прызначэння \"{}\" у мэтавай сістэме не з’яўляецца каталогам" #: src/modules/displaymanager/main.py:381 msgid "Cannot write KDM configuration file" -msgstr "" +msgstr "Немагчыма запісаць файл канфігурацыі KDM" #: src/modules/displaymanager/main.py:382 msgid "KDM config file {!s} does not exist" -msgstr "" +msgstr "Файл канфігурацыі KDM {!s} не існуе" #: src/modules/displaymanager/main.py:443 msgid "Cannot write LXDM configuration file" -msgstr "" +msgstr "Немагчыма запісаць файл канфігурацыі LXDM" #: src/modules/displaymanager/main.py:444 msgid "LXDM config file {!s} does not exist" -msgstr "" +msgstr "Файл канфігурацыі LXDM {!s} не існуе" #: src/modules/displaymanager/main.py:527 msgid "Cannot write LightDM configuration file" -msgstr "" +msgstr "Немагчыма запісаць файл канфігурацыі LightDM" #: src/modules/displaymanager/main.py:528 msgid "LightDM config file {!s} does not exist" -msgstr "" +msgstr "Файл канфігурацыі LightDM {!s} не існуе" #: src/modules/displaymanager/main.py:602 msgid "Cannot configure LightDM" -msgstr "" +msgstr "Немагчыма наладзіць LightDM" #: src/modules/displaymanager/main.py:603 msgid "No LightDM greeter installed." -msgstr "" +msgstr "LightDM greeter не ўсталяваны." #: src/modules/displaymanager/main.py:634 msgid "Cannot write SLIM configuration file" -msgstr "" +msgstr "Немагчыма запісаць файл канфігурацыі SLIM" #: src/modules/displaymanager/main.py:635 msgid "SLIM config file {!s} does not exist" -msgstr "" +msgstr "Файл канфігурацыі SLIM {!s} не існуе" #: src/modules/displaymanager/main.py:750 msgid "No display managers selected for the displaymanager module." -msgstr "" +msgstr "У модулі дысплейных кіраўнікоў нічога не абрана." #: src/modules/displaymanager/main.py:751 msgid "" "The displaymanagers list is empty or undefined in bothglobalstorage and " "displaymanager.conf." msgstr "" +"Спіс дысплейных кіраўнікоў пусты альбо не вызначаны ў bothglobalstorage і " +"displaymanager.conf." #: src/modules/displaymanager/main.py:831 msgid "Display manager configuration was incomplete" -msgstr "" +msgstr "Наладка дысплейнага кіраўніка не завершаная." #: src/modules/initcpiocfg/main.py:36 msgid "Configuring mkinitcpio." -msgstr "" +msgstr "Наладка mkinitcpio." #: src/modules/initcpiocfg/main.py:192 #: src/modules/luksopenswaphookcfg/main.py:100 @@ -200,142 +210,145 @@ msgstr "" #: src/modules/openrcdmcryptcfg/main.py:83 src/modules/fstab/main.py:317 #: src/modules/localecfg/main.py:145 src/modules/networkcfg/main.py:49 msgid "No root mount point is given for
{!s}
to use." -msgstr "" +msgstr "Каранёвы пункт мантавання для
{!s}
не пададзены." #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." -msgstr "" +msgstr "Наладка зашыфраванага swap." #: src/modules/rawfs/main.py:35 msgid "Installing data." -msgstr "" +msgstr "Усталёўка даных." #: src/modules/services-openrc/main.py:38 msgid "Configure OpenRC services" -msgstr "" +msgstr "Наладзіць службы OpenRC" #: src/modules/services-openrc/main.py:66 msgid "Cannot add service {name!s} to run-level {level!s}." -msgstr "" +msgstr "Не атрымалася дадаць службу {name!s} на ўзровень запуску {level!s}." #: src/modules/services-openrc/main.py:68 msgid "Cannot remove service {name!s} from run-level {level!s}." -msgstr "" +msgstr "Не атрымалася выдаліць службу {name!s} з узроўня запуску {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 "" +"Невядомае дзеянне {arg!s} для службы {name!s} на ўзроўні " +"запуску {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} пад chroot вярнуўся з кодам памылкі {num!s}." #: src/modules/services-openrc/main.py:110 msgid "Target runlevel does not exist" -msgstr "" +msgstr "Мэтавы ўзровень запуску не існуе" #: src/modules/services-openrc/main.py:111 msgid "" "The path for runlevel {level!s} is {path!s}, which does not " "exist." -msgstr "" +msgstr "Шлях {path!s} да ўзроўня запуску {level!s} не існуе." #: src/modules/services-openrc/main.py:119 msgid "Target service does not exist" -msgstr "" +msgstr "Мэтавая служба не існуе" #: src/modules/services-openrc/main.py:120 msgid "" "The path for service {name!s} is {path!s}, which does not " "exist." -msgstr "" +msgstr "Шлях {path!s} да службы {level!s} не існуе." #: src/modules/plymouthcfg/main.py:36 msgid "Configure Plymouth theme" -msgstr "" +msgstr "Наладзіць тэму Plymouth" #: src/modules/machineid/main.py:36 msgid "Generate machine-id." -msgstr "" +msgstr "Стварыць machine-id." #: src/modules/packages/main.py:62 #, python-format msgid "Processing packages (%(count)d / %(total)d)" -msgstr "" +msgstr "Апрацоўка пакункаў (%(count)d / %(total)d)" #: src/modules/packages/main.py:64 src/modules/packages/main.py:74 msgid "Install packages." -msgstr "" +msgstr "Усталяваць пакункі." #: src/modules/packages/main.py:67 #, python-format msgid "Installing one package." msgid_plural "Installing %(num)d packages." -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "Усталёўка аднаго пакунка." +msgstr[1] "Усталёўка %(num)d пакункаў." +msgstr[2] "Усталёўка %(num)d пакункаў." +msgstr[3] "Усталёўка%(num)d пакункаў." #: src/modules/packages/main.py:70 #, python-format msgid "Removing one package." msgid_plural "Removing %(num)d packages." -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "Выдаленне аднаго пакунка." +msgstr[1] "Выдаленне %(num)d пакункаў." +msgstr[2] "Выдаленне %(num)d пакункаў." +msgstr[3] "Выдаленне %(num)d пакункаў." #: src/modules/bootloader/main.py:51 msgid "Install bootloader." -msgstr "" +msgstr "Усталяваць загрузчык." #: src/modules/removeuser/main.py:34 msgid "Remove live user from target system" -msgstr "" +msgstr "Выдаліць часовага карыстальніка з мэтавай сістэмы" #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." -msgstr "" +msgstr "Наладка апаратнага гадзінніка." #: src/modules/dracut/main.py:36 msgid "Creating initramfs with dracut." -msgstr "" +msgstr "Стварэнне initramfs з dracut." #: src/modules/dracut/main.py:58 msgid "Failed to run dracut on the target" -msgstr "" +msgstr "Не атрымалася запусціць dracut у пункце прызначэння" #: src/modules/dracut/main.py:59 msgid "The exit code was {}" -msgstr "" +msgstr "Код выхаду {}" #: src/modules/initramfscfg/main.py:41 msgid "Configuring initramfs." -msgstr "" +msgstr "Наладка initramfs." #: src/modules/openrcdmcryptcfg/main.py:34 msgid "Configuring OpenRC dmcrypt service." -msgstr "" +msgstr "Наладка OpenRC dmcrypt." #: src/modules/fstab/main.py:38 msgid "Writing fstab." -msgstr "" +msgstr "Запіс fstab." #: src/modules/dummypython/main.py:44 msgid "Dummy python job." -msgstr "" +msgstr "Задача Dummy python." #: src/modules/dummypython/main.py:97 msgid "Dummy python step {}" -msgstr "" +msgstr "Крок Dummy python {}" #: src/modules/localecfg/main.py:39 msgid "Configuring locales." -msgstr "" +msgstr "Наладка лакаляў." #: src/modules/networkcfg/main.py:37 msgid "Saving network configuration." -msgstr "" +msgstr "Захаванне сеткавай канфігурацыі." diff --git a/lang/python/es/LC_MESSAGES/python.mo b/lang/python/es/LC_MESSAGES/python.mo index 5f74bc29cc845780a7c2148b5a96f5b5463d32b5..5dac1ae94ccc53b74623c5890c2aaeed08740a40 100644 GIT binary patch delta 232 zcmXZWu?qnK7zOZm<&JYE!->IBhSRYSMM`8cFfyqtM+%oiGRbVQSg;w5xBDY37Q2LFudiP3JE>Q7|J=+3U?~D|051thQppb#s7{NtM=SI|OY}}P8VUeqnxRoTq%pds zU3#Wz`lTtV$v~JkXr6XtRFPxY@!)x*-r$F}s2&6ix}sj;^7lc#2NcCU3T267Rd}9?8wp7Cao4Ce0UNMVbY+yPnC2@c$ zoZ%2RSi~0=Fy=^ctY8_tj#?@amK;J)7!E!$z=SLLIL5HB`+LLifscFH8~upgnaroT JUi)nM<`3tB8fE|h diff --git a/lang/python/es/LC_MESSAGES/python.po b/lang/python/es/LC_MESSAGES/python.po index 583b3adf0..928549662 100644 --- a/lang/python/es/LC_MESSAGES/python.po +++ b/lang/python/es/LC_MESSAGES/python.po @@ -7,7 +7,7 @@ # strel, 2018 # Francisco Sánchez López de Lerma , 2018 # Guido Grasso , 2018 -# Fito JB, 2019 +# Adolfo Jayme-Barrientos, 2019 # #, fuzzy msgid "" @@ -16,7 +16,7 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2019-07-06 01:16+0200\n" "PO-Revision-Date: 2017-08-09 10:34+0000\n" -"Last-Translator: Fito JB, 2019\n" +"Last-Translator: Adolfo Jayme-Barrientos, 2019\n" "Language-Team: Spanish (https://www.transifex.com/calamares/teams/20061/es/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" diff --git a/lang/python/pt_PT/LC_MESSAGES/python.mo b/lang/python/pt_PT/LC_MESSAGES/python.mo index 60d342d6e242279944db636a824f390eb2f137f6..9ac0dcef1b3c827d0b68611855a030211d1bf8a5 100644 GIT binary patch delta 2173 zcmY+^TWB0r7{Kw9OWVZU6LW1EkFBP$#%-G>+9pvO(=-@}(WDXydFZ%1yO}nbNoOZX zbCG>fP$+^7wmyUsloBh{qKi-;#FkZpLO~HJ;sr{nJ_Pi^r=So1zmtvC180A8W@paj zJKve*&Ra)Qzf|VGttkD}M(T-Nr7S#`&kv=1yHW#Kk#!t*(_X~}{2CA8U97|U9ZI!h zTh;{1|I4@^zrku$1xg)ODy3?;*h6~=AHpQ=#dosp>sUqmE|%d2)?;De=74)pCen@4 z&nWK1MXbRKct3uKwV1&N@JDQAeDxO>72IgKZ}Y)U9Hu>lveI`^I{Xr)gWD(_ZlFx8 zv}p7F-B?b$9VG&NC=*&hS=dFCg=J9QU&mdHuT-&8UC@LN;uv<|5)vZyF+PgxC>_?8 zD0Kk4P&%H(UHBHt1g~Nfu4V84iruvHOO+bO9+U}O#MEP4q`4Tv+c<~^iSr|v!k6$e zp2S?1Cwmt~9#!*r3|~iCz)jRxNI1{uD76nqY2T>aw4QM7qkRS?qRUmpUqXG28_ih6 zwED3PpTPx`0Y1ayn9Jz0;%D)Bbnys&j-9xHPhvY8FKr(s2d?nL9Ml&m1K-N}XASX} ztS=*OvNx?Ldwv2X$>z|6Hru|6vPEB^46u&OO*NDHjIFxxMSKAt##NN(Z)V$npyXOL zoy$0TQ(VZ6fvn?rkhY8MxPl${Js!p)Qe6f*h7lY?*}6AyKmLHS*M%&z509hd&N-Cl zuc18m8%n>aT9z+KHHb3PGblL`X4^NgllC2qV-w+E4D}ke;R=r7cPP0NA@k(@C3Nuv zJcad~IgPKPoSI9>7N^vwT*yrRM%mjotyB)?Qf2R@JWYL^${42f@+OI-J2W(HyTiRY zHWl^frvsg|{aGh!M^vxp#+}5B@3;wVyXH?jrjv8lbR>MUps%Udx2-__bX+I!t*LlY z&pE+_j`>z}CJ4VRNZ0u@ZnmjCR|gZe4lF-m2kH63-*XzD^R(}Ifu8ba+(1uz4!=%P zC!AT^4F`%c9V6DP^zYiioadj`(d>j6)pH|i#172x6P6#FvwT}eC%x$DNLXC_Q@MTC z33xtc>p3f_7hg%=DPGGd8TB3WMm!lThu=d0It+GlN| zWcmNz)h_?rNhX*cu35|tPuA5}nDAsS>$vB;cGQV^;YW2p_xI?;3~T0H>t0OE@N}Sk zJI3bqa2aP~q<`O@%%l?z-Ftc~SP?Z8UazVNFV&C8OPd3G+GP!z0cWOk%<=6YllC1i vtZX<{7tN$&PC}-rlUC+R%wkfGM0UO*FSj}=BihNRZ_nB?q=|62)VT5w;4fmj delta 1474 zcmYM!TSyd97{Kw*)x6~`%}eU$R+i=^Gqt=G716~~OU=Y2-0qsWAtvF2`x4nhR5T_% zNJ)Z_p%hE_Py{B?LxhEqV4#Q*h7UbNloiqcn;q$}Grx0YXXc#qo$t)V_MSrbRHWZ+ zp={$w1MbTJ4`0McW=I5{}up0(YQxcocOYtr&wha5?s4EI!2y9LHrS zLEir(v4Z|3g-Qa~+fg6rwr&_g?RXUR!3m7OFQ_y8g*x!8VDG>yQ3rkrbpX9+$0t~X zdjQ=!vaeJem`;4VeMAo65!$m%S1n@tX=tEE>N!^6B(B5ENRd5Q zg*&kawS#Hgjmd;jCv*-E;!P~TnJD64NF{-IZN+NTb{Fbejv?=m&!`I?QjZD zV-%^r3EQz22eA|b36DNkjm>x&8}S<^;W5IcOVfec&j{+0xPMS#$%Py;i;Xj5G80jg zk_nq-i)A5_$mXndW*QX-hel0jriFYn3p>u-QMxNMI>qMI|EE;l|MYKe4?iT~&7w=9 zvo7G!50lPJN2}XUi-t}!TqB{g@#WB>xuOZFMYrx^(OpCU%_R=AE@oho?Dw`bN%+nP zA2qY+zFjPAbMp(g8QB~?Tvl+?KWdLsrMgA7@tA_ diff --git a/lang/python/pt_PT/LC_MESSAGES/python.po b/lang/python/pt_PT/LC_MESSAGES/python.po index dcefb6c66..b5ba4bfc4 100644 --- a/lang/python/pt_PT/LC_MESSAGES/python.po +++ b/lang/python/pt_PT/LC_MESSAGES/python.po @@ -93,7 +93,7 @@ msgstr "" #: src/modules/umount/main.py:40 msgid "Unmount file systems." -msgstr "Desmontar sistemas de ficheiro." +msgstr "Desmontar sistemas de ficheiros." #: src/modules/unpackfs/main.py:41 msgid "Filling up filesystems." @@ -146,7 +146,7 @@ msgstr "O sistema de ficheiros fonte \"{}\" não existe" #: src/modules/unpackfs/main.py:353 msgid "The destination \"{}\" in the target system is not a directory" -msgstr "O destino \"{}\" no sistema alvo não é uma diretoria" +msgstr "O destino \"{}\" no sistema de destino não é um diretório" #: src/modules/displaymanager/main.py:381 msgid "Cannot write KDM configuration file" @@ -215,11 +215,11 @@ msgstr "A configurar o mkintcpio." #: src/modules/openrcdmcryptcfg/main.py:83 src/modules/fstab/main.py:317 #: src/modules/localecfg/main.py:145 src/modules/networkcfg/main.py:49 msgid "No root mount point is given for
{!s}
to use." -msgstr "" +msgstr "Nenhum ponto de montagem root é fornecido para
{!s}
usar." #: src/modules/luksopenswaphookcfg/main.py:35 msgid "Configuring encrypted swap." -msgstr "" +msgstr "Configurando a swap criptografada." #: src/modules/rawfs/main.py:35 msgid "Installing data." @@ -318,19 +318,19 @@ msgstr "Remover utilizador ativo do sistema de destino" #: src/modules/hwclock/main.py:35 msgid "Setting hardware clock." -msgstr "" +msgstr "A definir o relógio do hardware." #: src/modules/dracut/main.py:36 msgid "Creating initramfs with dracut." -msgstr "" +msgstr "Criando o initramfs com o dracut." #: src/modules/dracut/main.py:58 msgid "Failed to run dracut on the target" -msgstr "" +msgstr "Falha ao executar o dracut no destino" #: src/modules/dracut/main.py:59 msgid "The exit code was {}" -msgstr "" +msgstr "O código de saída foi {}" #: src/modules/initramfscfg/main.py:41 msgid "Configuring initramfs." @@ -338,11 +338,11 @@ msgstr "A configurar o initramfs." #: src/modules/openrcdmcryptcfg/main.py:34 msgid "Configuring OpenRC dmcrypt service." -msgstr "" +msgstr "A configurar o serviço OpenRC dmcrypt." #: src/modules/fstab/main.py:38 msgid "Writing fstab." -msgstr "" +msgstr "A escrever o fstab." #: src/modules/dummypython/main.py:44 msgid "Dummy python job." @@ -354,8 +354,8 @@ msgstr "Passo Dummy python {}" #: src/modules/localecfg/main.py:39 msgid "Configuring locales." -msgstr "A configurar o local." +msgstr "A configurar a localização." #: src/modules/networkcfg/main.py:37 msgid "Saving network configuration." -msgstr "" +msgstr "A guardar a configuração de rede." From c9ab0524e226a99e78589f8a0ac9a9100305e36a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 30 Aug 2019 13:38:00 +0200 Subject: [PATCH 301/302] Changes: post-release housekeeping --- CHANGES | 9 +++++++++ CMakeLists.txt | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 3921b21e2..ad985b1e4 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,15 @@ changelog -- this log starts with version 3.2.0. The release notes on the website will have to do for older versions. +# 3.2.14 (unreleased) # + +This release contains contributions from (alphabetically by first name): + +## Core ## + +## Modules ## + + # 3.2.13 (2019-08-30) # This release contains contributions from (alphabetically by first name): diff --git a/CMakeLists.txt b/CMakeLists.txt index f48dda135..46acedaf9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,10 +40,10 @@ cmake_minimum_required( VERSION 3.3 FATAL_ERROR ) project( CALAMARES - VERSION 3.2.13 + VERSION 3.2.14 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 c7cbba3951f269cfe20c2915b51ea6928f5b6a1c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 30 Aug 2019 22:54:28 +0200 Subject: [PATCH 302/302] [welcome] Fix typo in tooltip --- src/modules/welcome/WelcomePage.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/welcome/WelcomePage.ui b/src/modules/welcome/WelcomePage.ui index 160daa595..590029558 100644 --- a/src/modules/welcome/WelcomePage.ui +++ b/src/modules/welcome/WelcomePage.ui @@ -176,7 +176,7 @@ - Open relead notes website + Open release notes website &Release notes