Compare commits

...

52 Commits

Author SHA1 Message Date
demmm
cbeeb06e59 Merge pull request #1960 from AIIX/feature/port/partition_qml_module/v1
Initial upload of WIP partitionq module
2022-05-26 21:11:55 +02:00
Aditya Mehra
dc7f91797c fix spdx headers for files 2022-05-26 17:54:42 +09:30
Aditya Mehra
abaf7630ad Add flat partition list module for qml, fix review stuff 2022-05-26 17:47:21 +09:30
Adriaan de Groot
0a4e6804c6 [partition] Move encryption state-calculation to state()
Previously, state() just returned a stored state, which changed
via updateState(). However, when updateState() started taking
visibility-of-the-widget into account, it became possible to
de-sync the *apparent* state of the encryption widget, from the
stored one:
- make an encryption widget, which is not visible
- show it.

Now the stored-state takes visibility into account that is
different (hidden, so we end up with a state of Unconfirmed)
from the apparent value (shown and unchecked).

Move the calculation to state() instead, so whenever queried,
it checks the current checks-and-visibility values. Restore
the previously-reverted bit for accepting LUKS partitions.

SEE #1935
SEE #1953
2022-05-20 18:10:24 +02:00
Adriaan de Groot
900700b9bc [partition] Partial revert reuse-luks merge
- a hidden checkbox should not be handled the same as a checkbox
  that is checked; if there is a setting that can be checked or
  unchecked, it can only be checked when visible.

FIXES #1953
2022-05-20 13:49:32 +02:00
Adriaan de Groot
12b62980cb Changes: pre-release housekeeping 2022-05-20 12:14:05 +02:00
Adriaan de Groot
e7f6ead038 [partition] When changing encryption-widget visibility, re-check next 2022-05-20 12:02:25 +02:00
Adriaan de Groot
51e3ac0ded [partition] Polish up debugging when checking for next-enabled
- Improve the messages a bit
- Remove useless variable (it is checking that the switch(choice)
  statement covers all the cases; let's leave that to the compiler)
2022-05-20 11:56:08 +02:00
Aditya Mehra
a84783d5e2 Initial upload of WIP partitionq module 2022-05-19 17:48:32 +09:30
Adriaan de Groot
17814410e9 [users] always-forbidden-names should be set in the Config constructor 2022-05-18 14:40:35 +02:00
Adriaan de Groot
cebafcf869 [users] Make test more expressive 2022-05-18 14:37:02 +02:00
Adriaan de Groot
7d5a4eafa2 [partition] Support KPMCore3 API (no testPassphrase in FS::luks) 2022-05-18 14:06:00 +02:00
Adriaan de Groot
fc8e5fb5c7 CI: forbid clang-format-14 2022-05-18 12:55:15 +02:00
Adriaan de Groot
f352740aba Git: update blame-ignore 2022-05-18 12:45:32 +02:00
Adriaan de Groot
874a0c1f38 CI: apply coding style globally again 2022-05-18 12:44:55 +02:00
Adriaan de Groot
8fea6f71ab [partition] Apply coding style 2022-05-18 12:26:19 +02:00
Adriaan de Groot
56071c4016 CI: acceptable clang-format versions 2022-05-18 12:22:51 +02:00
Adriaan de Groot
9e664d7165 Changes: pre-release housekeeping 2022-05-18 12:05:45 +02:00
Calamares CI
cf5f0e1caa i18n: [calamares] Automatic merge of Transifex translations 2022-05-18 11:52:43 +02:00
Adriaan de Groot
62f3055e5a [netinstall] Implement a special "blank" item
- If the name of an item is empty, treat it as a
  "separator line", do not paint it like a regular
  item. The branches of the tree just pass it by.
2022-05-18 00:25:04 +02:00
Adriaan de Groot
542aa5c083 SPDX: tag the ignore-revs file, too 2022-05-17 23:29:37 +02:00
Adriaan de Groot
9e2728bcb7 [netinstall] Polish up SPDX headers 2022-05-17 14:40:36 +02:00
Adriaan de Groot
6bf710bed3 [netinstall] Introduce a custom class for the Tree Widget 2022-05-17 14:38:44 +02:00
Adriaan de Groot
67ad12c2d0 Docs: suggest IRC for non-account chat 2022-05-17 11:01:06 +02:00
Adriaan de Groot
4a4d872bb0 Docs: offer alternative Matrix webchat link 2022-05-17 10:51:36 +02:00
Adriaan de Groot
9d6bb2ee2a Merge pull request #1952 from abalfoort/#1935
#1935 - Reuse luks partitions
2022-05-17 10:35:51 +02:00
Adriaan de Groot
a63c474d93 Merge pull request #1948 from dalto8/zfsencryption
[partition] Don't offer whole disk encryption when zfs is selected
2022-05-17 10:31:48 +02:00
abalfoort
f67df577db Fix compilation warning 2022-05-16 15:08:11 +02:00
abalfoort
25a6a5ee53 Fix crypttab 2022-05-16 15:06:59 +02:00
abalfoort
cd4b8d4179 Reuse luks partitions 2022-05-16 15:06:33 +02:00
dalto
31c8123677 [partition] Remove no longer needed setChecked() in the encryption widget 2022-05-14 10:38:27 -05:00
Adriaan de Groot
d318778f53 Merge pull request #1949 from dalto8/removeemits
Remove unneeded emits
2022-05-14 17:24:48 +02:00
dalto
152f99fb07 Remove useless emits 2022-05-13 17:24:07 -05:00
dalto
42841a217c [partition] Don't offer whole disk encryption when zfs is selected 2022-05-13 16:24:15 -05:00
demmm
7937cd625d [localeq]Map.qml needed fixes
esri has several bugs, not showing for all locations, zooming on Americas broken
use osm as default, set preferred, so esri can be fallback
remove Label section for mouse movement, showing coordinates not really useful,
issue with mouse grabbing is back with it
2022-05-13 13:17:19 +02:00
Adriaan de Groot
bc98b9892c Changes: document new settings in the users module. 2022-05-09 15:01:49 +02:00
Adriaan de Groot
d0db56e964 [users] Simplify code: use contains() instead of a for-loop 2022-05-09 14:58:46 +02:00
Adriaan de Groot
ef9bf2650c [users] Allow a configurable list of forbidden names
- forbidden login names
- forbidden host names
2022-05-09 14:51:13 +02:00
Adriaan de Groot
7473462125 [users] Introduce forbidden_names settings 2022-05-09 14:51:13 +02:00
Adriaan de Groot
40c5ef1c35 [users] Add new structured setting to example file 2022-05-09 14:33:39 +02:00
Adriaan de Groot
fe04ae3ac1 [users] Introduce new structure for users-settings 2022-05-09 14:33:39 +02:00
Adriaan de Groot
1bf5206bd7 [users] Apply code-style to test-code 2022-05-09 14:33:39 +02:00
Adriaan de Groot
14129fedb6 Changes: post-release housekeeping and credits 2022-05-09 13:23:45 +02:00
Adriaan de Groot
3bc3b352d8 [displaymanager] Add LF after last line of greetd configuration
FIXES #1937
2022-05-06 11:47:44 +02:00
Adriaan de Groot
091eb9683b [libcalamares] Give Occitan a native name 2022-05-05 15:23:54 +02:00
Adriaan de Groot
4be25e2f70 [libcalamares] Special-case the regions through the lookup-table as well 2022-05-05 15:20:29 +02:00
Adriaan de Groot
2de7736291 [libcalamares] Replace locale special-cases by a table
Replace the function with a table-driven approach,
since that is somewhat easier to extend to more
languages.
2022-05-05 14:42:12 +02:00
Adriaan de Groot
e005b1af32 Merge pull request #1941 from edupals/special_locale_region
[libcalamares] Improving special-case language detection
2022-05-05 11:22:32 +02:00
Lt-Henry
a8857e51f4 Improving special-case language detection 2022-05-05 11:12:29 +02:00
abalfoort
6ef243ba37 Merge branch 'calamares:calamares' into calamares 2022-04-26 14:56:06 +02:00
abalfoort
bbb0efc15e Merge branch 'calamares:calamares' into calamares 2022-04-23 16:14:15 +02:00
abalfoort
34ea3112a5 Merge branch 'calamares' of https://github.com/abalfoort/calamares into calamares 2022-04-23 14:44:06 +02:00
99 changed files with 3404 additions and 620 deletions

View File

@@ -1 +1,5 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
#
18fef8dfe5d926ec0bc979562553adf4db8db2e9
874a0c1f38b0da4e5bc83083b13a63b1c7eed935

View File

@@ -8,6 +8,41 @@ 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.58.1 (2022-05-20)
This is a hot-fix release for a regression in the *partition* module where
it was impossible to proceed unless *Encrypt system* was checked.
# 3.2.58 (2022-05-18) #
This release contains contributions from (alphabetically by first name):
- Anke Boersma
- Arjen Balfoort
- Enrique Medina Gremaldos
- Evan James
## Core ##
- Internal improvements to translations-setup means that Catalan (in the
Valencian dialect), Occitan (Lenga d'Oc) and Serbian (in Latin script)
are all better supported. Thanks Enrique.
## Modules ##
- *netinstall* Now displays entries with an empty name slightly differently.
An empty name is not generally useful, but in combination with
*immutable:true* and *selected:false* can be used to introduce separators
or descriptive comments into the list of packages.
- *partition* does not offer full-disk encryption when using ZFS. ZFS and the
way Calamares sets up FDE don't mix well. (Thanks Evan)
- *partition* Various bugs related to LUKS have been fixed. (Thanks Arjen)
- *users* module now has a structured *user* key with settings specific
to the user (shell, in particular). This maintains backwards compatibility
with the *userShell* key.
- *users* module now has lists of forbidden login- and host-names, to
avoid settings that will mess up the install (e.g. using a login-name
that is one of the system's reserved names). #1944
# 3.2.57 (2022-05-04) #
This release contains contributions from (alphabetically by first name):

View File

@@ -41,7 +41,7 @@
# TODO:3.3: Require CMake 3.12
cmake_minimum_required( VERSION 3.3 FATAL_ERROR )
project( CALAMARES
VERSION 3.2.57
VERSION 3.2.58.1
LANGUAGES C CXX
)

View File

@@ -65,5 +65,5 @@ that chat window open because it can easily take a few hours for
someone to notice a message.
Matrix is persistent, and we'll see your message eventually.
* [![Join us on Matrix](https://img.shields.io/badge/Matrix-%23calamares:kde.org-blue)](https://webchat.kde.org/#/room/%23calamares:kde.org)
* [![Chat on IRC](https://img.shields.io/badge/IRC-Libera.Chat%20%23calamares-green)](https://kiwiirc.com/client/irc.libera.chat/#calamares)
* [![Join us on Matrix](https://img.shields.io/badge/Matrix-%23calamares:kde.org-blue)](https://webchat.kde.org/#/room/%23calamares:kde.org) (needs a Matrix account)
* [![Chat on IRC](https://img.shields.io/badge/IRC-Libera.Chat%20%23calamares-green)](https://kiwiirc.com/client/irc.libera.chat/#calamares) (IRC supports guest accounts)

View File

@@ -24,7 +24,7 @@ test -f "$TOPDIR/.clang-format" || { echo "! No .clang-format support files in $
AS=$( which astyle )
# Allow specifying CF_VERSIONS outside already
CF_VERSIONS="$CF_VERSIONS clang-format13 clang-format-13 clang-format12 clang-format-12 clang-format"
CF_VERSIONS="$CF_VERSIONS clang-format13 clang-format-13 clang-format-13.0.1 clang-format12 clang-format-12 clang-format"
for _cf in $CF_VERSIONS
do
# Not an error if this particular clang-format isn't found
@@ -42,6 +42,9 @@ test -x "$CF" || { echo "! $CF is not executable."; exit 1 ; }
# Version 7 and earlier doesn't understand all the options we would like
# Version 12 handles lambdas nicely, so use that.
# Version 13 is also ok.
# Version 14 behaves differently with short-functions-in-class,
# spreading functions out that 13 keeps on one line. To avoid
# ping-pong commits, forbid 14.
format_version=`"$CF" --version | tr -dc '[^.0-9]' | cut -d . -f 1`
case "$format_version" in
@@ -49,7 +52,7 @@ case "$format_version" in
:
;;
* )
echo "! Clang-format version '$format_version' unsupported, version 12 required."
echo "! Clang-format version '$format_version' unsupported, versions 12 or 13 are ok."
exit 1
;;
esac

View File

@@ -37,17 +37,17 @@
<message>
<location filename="../src/modules/partition/core/BootLoaderModel.cpp" line="92"/>
<source>Boot Partition</source>
<translation type="unfinished"/>
<translation>Particion daviada</translation>
</message>
<message>
<location filename="../src/modules/partition/core/BootLoaderModel.cpp" line="99"/>
<source>System Partition</source>
<translation type="unfinished"/>
<translation>Particion sistèma</translation>
</message>
<message>
<location filename="../src/modules/partition/core/BootLoaderModel.cpp" line="129"/>
<source>Do not install a boot loader</source>
<translation type="unfinished"/>
<translation>Installar pas lo gestionari d'aviada</translation>
</message>
<message>
<location filename="../src/modules/partition/core/BootLoaderModel.cpp" line="147"/>
@@ -83,12 +83,12 @@
<message>
<location filename="../src/calamares/DebugWindow.ui" line="48"/>
<source>Modules</source>
<translation type="unfinished"/>
<translation>Moduls</translation>
</message>
<message>
<location filename="../src/calamares/DebugWindow.ui" line="61"/>
<source>Type:</source>
<translation type="unfinished"/>
<translation>Tipe:</translation>
</message>
<message>
<location filename="../src/calamares/DebugWindow.ui" line="68"/>
@@ -124,7 +124,7 @@
<message>
<location filename="../src/calamares/DebugWindow.ui" line="118"/>
<source>Reload Stylesheet</source>
<translation type="unfinished"/>
<translation>Recargar fuèlh destil</translation>
</message>
<message>
<location filename="../src/calamares/DebugWindow.ui" line="128"/>
@@ -139,7 +139,7 @@
<message>
<location filename="../src/calamares/DebugWindow.cpp" line="221"/>
<source>Debug information</source>
<translation type="unfinished"/>
<translation>Informacions de desbugatge</translation>
</message>
</context>
<context>
@@ -194,12 +194,12 @@
<message>
<location filename="../src/libcalamares/ProcessJob.cpp" line="42"/>
<source> Run command '%1'.</source>
<translation type="unfinished"/>
<translation>Executar la comanda « %1».</translation>
</message>
<message>
<location filename="../src/libcalamares/ProcessJob.cpp" line="49"/>
<source>Running command %1 %2</source>
<translation type="unfinished"/>
<translation>Execucion de la comanda %1 %2</translation>
</message>
</context>
<context>
@@ -207,7 +207,7 @@
<message>
<location filename="../src/libcalamares/PythonJob.cpp" line="233"/>
<source>Running %1 operation.</source>
<translation type="unfinished"/>
<translation>Execucion de loperacion %1</translation>
</message>
<message>
<location filename="../src/libcalamares/PythonJob.cpp" line="262"/>
@@ -250,7 +250,7 @@
<message>
<location filename="../src/libcalamaresui/viewpages/QmlViewStep.cpp" line="268"/>
<source>Loading failed.</source>
<translation type="unfinished"/>
<translation>Fracàs del cargament.</translation>
</message>
</context>
<context>
@@ -336,7 +336,7 @@ Link copied to clipboard</source>
<message>
<location filename="../src/libcalamaresui/ViewManager.cpp" line="189"/>
<source>Calamares Initialization Failed</source>
<translation type="unfinished"/>
<translation>Lançament de Calamares fracassat</translation>
</message>
<message>
<location filename="../src/libcalamaresui/ViewManager.cpp" line="190"/>
@@ -396,22 +396,22 @@ Link copied to clipboard</source>
<message>
<location filename="../src/libcalamaresui/ViewManager.cpp" line="378"/>
<source>Setup is complete. Close the setup program.</source>
<translation type="unfinished"/>
<translation>Configuracion acabada. Tampatz lo programa de configuracion.</translation>
</message>
<message>
<location filename="../src/libcalamaresui/ViewManager.cpp" line="379"/>
<source>The installation is complete. Close the installer.</source>
<translation type="unfinished"/>
<translation>Linstallacion es acabada. Tampatz linstallador.</translation>
</message>
<message>
<location filename="../src/libcalamaresui/ViewManager.cpp" line="381"/>
<source>Cancel setup without changing the system.</source>
<translation type="unfinished"/>
<translation>Anullar la configuracion sens cambiar lo sistèma.</translation>
</message>
<message>
<location filename="../src/libcalamaresui/ViewManager.cpp" line="382"/>
<source>Cancel installation without changing the system.</source>
<translation type="unfinished"/>
<translation>Anullar linstallacion sens cambiar lo sistèma.</translation>
</message>
<message>
<location filename="../src/libcalamaresui/ViewManager.cpp" line="392"/>
@@ -436,12 +436,12 @@ Link copied to clipboard</source>
<message>
<location filename="../src/libcalamaresui/ViewManager.cpp" line="495"/>
<source>Cancel setup?</source>
<translation type="unfinished"/>
<translation>Anullar la configuracion?</translation>
</message>
<message>
<location filename="../src/libcalamaresui/ViewManager.cpp" line="495"/>
<source>Cancel installation?</source>
<translation type="unfinished"/>
<translation>Anullar linstallacion?</translation>
</message>
<message>
<location filename="../src/libcalamaresui/ViewManager.cpp" line="496"/>
@@ -489,7 +489,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/calamares/CalamaresWindow.cpp" line="371"/>
<source>%1 Installer</source>
<translation type="unfinished"/>
<translation>Installador de %1</translation>
</message>
</context>
<context>
@@ -536,12 +536,12 @@ The installer will quit and all changes will be lost.</source>
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1062"/>
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1159"/>
<source>Current:</source>
<translation type="unfinished"/>
<translation>Actual:</translation>
</message>
<message>
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="139"/>
<source>After:</source>
<translation type="unfinished"/>
<translation>Aprèp:</translation>
</message>
<message>
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1723"/>
@@ -566,12 +566,12 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1091"/>
<source>Boot loader location:</source>
<translation type="unfinished"/>
<translation>Emplaçament del gestionari d'aviada:</translation>
</message>
<message>
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1150"/>
<source>&lt;strong&gt;Select a partition to install on&lt;/strong&gt;</source>
<translation type="unfinished"/>
<translation>&lt;strong&gt;Seleccionar una particion ont installar&lt;/strong&gt;</translation>
</message>
<message>
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1209"/>
@@ -586,7 +586,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1225"/>
<source>EFI system partition:</source>
<translation type="unfinished"/>
<translation>Particion sistèma EFI:</translation>
</message>
<message>
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1385"/>
@@ -803,7 +803,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/netinstall/Config.cpp" line="77"/>
<source>Package selection</source>
<translation type="unfinished"/>
<translation>Seleccion dels paquets</translation>
</message>
<message>
<location filename="../src/modules/netinstall/Config.cpp" line="59"/>
@@ -838,72 +838,72 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/welcome/Config.cpp" line="250"/>
<source>&lt;h1&gt;Welcome to the Calamares setup program for %1&lt;/h1&gt;</source>
<translation type="unfinished"/>
<translation>&lt;h1&gt;La benvenguda al programa dinstallacion de Calamares per %1&lt;/h1&gt;</translation>
</message>
<message>
<location filename="../src/modules/welcome/Config.cpp" line="251"/>
<source>&lt;h1&gt;Welcome to %1 setup&lt;/h1&gt;</source>
<translation type="unfinished"/>
<translation>&lt;h1&gt;La benvenguda a la configuracion de %1&lt;/h1&gt;</translation>
</message>
<message>
<location filename="../src/modules/welcome/Config.cpp" line="255"/>
<source>&lt;h1&gt;Welcome to the Calamares installer for %1&lt;/h1&gt;</source>
<translation type="unfinished"/>
<translation>&lt;h1&gt;La benvenguda a linstallador de Calamares per %1&lt;/h1&gt;</translation>
</message>
<message>
<location filename="../src/modules/welcome/Config.cpp" line="256"/>
<source>&lt;h1&gt;Welcome to the %1 installer&lt;/h1&gt;</source>
<translation type="unfinished"/>
<translation>&lt;h1&gt;La benvenguda a linstallador de %1&lt;/h1&gt;</translation>
</message>
<message>
<location filename="../src/modules/users/Config.cpp" line="221"/>
<source>Your username is too long.</source>
<translation type="unfinished"/>
<translation>Vòstre nom dutilizaire es tròp long.</translation>
</message>
<message>
<location filename="../src/modules/users/Config.cpp" line="227"/>
<source>'%1' is not allowed as username.</source>
<translation type="unfinished"/>
<translation>« %1» es pas permés coma nom dutilizaire.</translation>
</message>
<message>
<location filename="../src/modules/users/Config.cpp" line="234"/>
<source>Your username must start with a lowercase letter or underscore.</source>
<translation type="unfinished"/>
<translation>Vòstre nom dutilizaire deu començar per una minuscula o un jonhent bas.</translation>
</message>
<message>
<location filename="../src/modules/users/Config.cpp" line="238"/>
<source>Only lowercase letters, numbers, underscore and hyphen are allowed.</source>
<translation type="unfinished"/>
<translation>Son solament permeses las letras minusculas, nombres, jonhents basses e los tirets.</translation>
</message>
<message>
<location filename="../src/modules/users/Config.cpp" line="288"/>
<source>Your hostname is too short.</source>
<translation type="unfinished"/>
<translation>Vòstre nom dòste es tròp cort.</translation>
</message>
<message>
<location filename="../src/modules/users/Config.cpp" line="292"/>
<source>Your hostname is too long.</source>
<translation type="unfinished"/>
<translation>Vòstre nom dòste es tròp long.</translation>
</message>
<message>
<location filename="../src/modules/users/Config.cpp" line="298"/>
<source>'%1' is not allowed as hostname.</source>
<translation type="unfinished"/>
<translation>« %1» es pas permés coma nom dòste.</translation>
</message>
<message>
<location filename="../src/modules/users/Config.cpp" line="304"/>
<source>Only letters, numbers, underscore and hyphen are allowed.</source>
<translation type="unfinished"/>
<translation>Son solament permeses las letras, nombres, jonhents basses e los tirets.</translation>
</message>
<message>
<location filename="../src/modules/users/Config.cpp" line="573"/>
<source>Your passwords do not match!</source>
<translation type="unfinished"/>
<translation>Los senhals correspondon pas!</translation>
</message>
<message>
<location filename="../src/modules/users/Config.cpp" line="587"/>
<source>OK!</source>
<translation type="unfinished"/>
<translation>Dacòrd!</translation>
</message>
<message>
<location filename="../src/modules/finished/Config.cpp" line="145"/>
@@ -928,27 +928,27 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/finished/Config.cpp" line="152"/>
<source>Setup Complete</source>
<translation type="unfinished"/>
<translation>Configuracion acabada</translation>
</message>
<message>
<location filename="../src/modules/finished/Config.cpp" line="153"/>
<source>Installation Complete</source>
<translation type="unfinished"/>
<translation>Installacion acabada</translation>
</message>
<message>
<location filename="../src/modules/finished/Config.cpp" line="154"/>
<source>The setup of %1 is complete.</source>
<translation type="unfinished"/>
<translation>La configuracion de %1 es acabada.</translation>
</message>
<message>
<location filename="../src/modules/finished/Config.cpp" line="155"/>
<source>The installation of %1 is complete.</source>
<translation type="unfinished"/>
<translation>Linstallacion de %1 es acabada.</translation>
</message>
<message>
<location filename="../src/modules/packagechooser/Config.cpp" line="111"/>
<source>Package Selection</source>
<translation type="unfinished"/>
<translation>Seleccion dels paquets</translation>
</message>
<message>
<location filename="../src/modules/packagechooser/Config.cpp" line="113"/>
@@ -999,7 +999,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/partition/gui/CreatePartitionDialog.ui" line="42"/>
<source>Si&amp;ze:</source>
<translation type="unfinished"/>
<translation>Ta&amp;lha:</translation>
</message>
<message>
<location filename="../src/modules/partition/gui/CreatePartitionDialog.ui" line="52"/>
@@ -1009,7 +1009,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/partition/gui/CreatePartitionDialog.ui" line="59"/>
<source>Partition &amp;Type:</source>
<translation type="unfinished"/>
<translation>&amp;Tipe de particion:</translation>
</message>
<message>
<location filename="../src/modules/partition/gui/CreatePartitionDialog.ui" line="71"/>
@@ -1019,12 +1019,12 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/partition/gui/CreatePartitionDialog.ui" line="81"/>
<source>E&amp;xtended</source>
<translation type="unfinished"/>
<translation>E&amp;spandida</translation>
</message>
<message>
<location filename="../src/modules/partition/gui/CreatePartitionDialog.ui" line="123"/>
<source>Fi&amp;le System:</source>
<translation type="unfinished"/>
<translation>Sistèma de fic&amp;hièr:</translation>
</message>
<message>
<location filename="../src/modules/partition/gui/CreatePartitionDialog.ui" line="155"/>
@@ -1034,7 +1034,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/partition/gui/CreatePartitionDialog.ui" line="165"/>
<source>&amp;Mount Point:</source>
<translation type="unfinished"/>
<translation>Punt de &amp;montatge:</translation>
</message>
<message>
<location filename="../src/modules/partition/gui/CreatePartitionDialog.ui" line="191"/>
@@ -1182,17 +1182,17 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/users/CreateUserJob.cpp" line="35"/>
<source>Create user %1</source>
<translation type="unfinished"/>
<translation>Crear lutilizaire %1</translation>
</message>
<message>
<location filename="../src/modules/users/CreateUserJob.cpp" line="42"/>
<source>Create user &lt;strong&gt;%1&lt;/strong&gt;.</source>
<translation type="unfinished"/>
<translation>Crear utilizaire &lt;strong&gt;%1&lt;/strong&gt;.</translation>
</message>
<message>
<location filename="../src/modules/users/CreateUserJob.cpp" line="125"/>
<source>Preserving home directory</source>
<translation type="unfinished"/>
<translation>Servar lo repertòri home</translation>
</message>
<message>
<location filename="../src/modules/users/CreateUserJob.cpp" line="49"/>
@@ -1266,7 +1266,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/partition/jobs/DeletePartitionJob.cpp" line="73"/>
<source>Delete partition %1.</source>
<translation type="unfinished"/>
<translation>Suprimir la particion %1.</translation>
</message>
<message>
<location filename="../src/modules/partition/jobs/DeletePartitionJob.cpp" line="80"/>
@@ -1276,7 +1276,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/partition/jobs/DeletePartitionJob.cpp" line="87"/>
<source>Deleting partition %1.</source>
<translation type="unfinished"/>
<translation>Supression de la particion %1.</translation>
</message>
<message>
<location filename="../src/modules/partition/jobs/DeletePartitionJob.cpp" line="102"/>
@@ -1388,12 +1388,12 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/partition/gui/EditExistingPartitionDialog.ui" line="103"/>
<source>&amp;Mount Point:</source>
<translation type="unfinished"/>
<translation>Punt de &amp;montatge:</translation>
</message>
<message>
<location filename="../src/modules/partition/gui/EditExistingPartitionDialog.ui" line="129"/>
<source>Si&amp;ze:</source>
<translation type="unfinished"/>
<translation>Ta&amp;lha:</translation>
</message>
<message>
<location filename="../src/modules/partition/gui/EditExistingPartitionDialog.ui" line="139"/>
@@ -1403,7 +1403,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/partition/gui/EditExistingPartitionDialog.ui" line="146"/>
<source>Fi&amp;le System:</source>
<translation type="unfinished"/>
<translation>Sistèma de fic&amp;hièr:</translation>
</message>
<message>
<location filename="../src/modules/partition/gui/EditExistingPartitionDialog.ui" line="159"/>
@@ -1460,7 +1460,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/libcalamaresui/widgets/ErrorDialog.ui" line="40"/>
<source>Details:</source>
<translation type="unfinished"/>
<translation>Detalhs:</translation>
</message>
<message>
<location filename="../src/libcalamaresui/widgets/ErrorDialog.ui" line="56"/>
@@ -1633,22 +1633,22 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/welcome/checker/GeneralRequirements.cpp" line="177"/>
<source>is plugged in to a power source</source>
<translation type="unfinished"/>
<translation>es brancat a una alimentacion electrica</translation>
</message>
<message>
<location filename="../src/modules/welcome/checker/GeneralRequirements.cpp" line="178"/>
<source>The system is not plugged in to a power source.</source>
<translation type="unfinished"/>
<translation>Lo sistèma es pas brancat a una alimentacion electrica.</translation>
</message>
<message>
<location filename="../src/modules/welcome/checker/GeneralRequirements.cpp" line="185"/>
<source>is connected to the Internet</source>
<translation type="unfinished"/>
<translation>es connectat a lInternet</translation>
</message>
<message>
<location filename="../src/modules/welcome/checker/GeneralRequirements.cpp" line="186"/>
<source>The system is not connected to the Internet.</source>
<translation type="unfinished"/>
<translation>Lo sistèma es pas connectat a lInternet.</translation>
</message>
<message>
<location filename="../src/modules/welcome/checker/GeneralRequirements.cpp" line="193"/>
@@ -1736,7 +1736,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/interactiveterminal/InteractiveTerminalPage.cpp" line="46"/>
<source>Konsole not installed</source>
<translation type="unfinished"/>
<translation>Konsole pas installada</translation>
</message>
<message>
<location filename="../src/modules/interactiveterminal/InteractiveTerminalPage.cpp" line="47"/>
@@ -1778,7 +1778,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/locale/LCLocaleDialog.cpp" line="23"/>
<source>System locale setting</source>
<translation type="unfinished"/>
<translation>Paramètres de regionalizacion del sistèma</translation>
</message>
<message>
<location filename="../src/modules/locale/LCLocaleDialog.cpp" line="30"/>
@@ -1829,12 +1829,12 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/license/LicensePage.ui" line="26"/>
<source>&lt;h1&gt;License Agreement&lt;/h1&gt;</source>
<translation type="unfinished"/>
<translation>&lt;h1&gt;Acòrd de licéncia&lt;/h1&gt;</translation>
</message>
<message>
<location filename="../src/modules/license/LicensePage.cpp" line="135"/>
<source>I accept the terms and conditions above.</source>
<translation type="unfinished"/>
<translation>Accèpti los tèrmes e las condicion aquí dessús.</translation>
</message>
<message>
<location filename="../src/modules/license/LicensePage.cpp" line="137"/>
@@ -1875,7 +1875,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/license/LicenseWidget.cpp" line="88"/>
<source>URL: %1</source>
<translation type="unfinished"/>
<translation>URL: %1</translation>
</message>
<message>
<location filename="../src/modules/license/LicenseWidget.cpp" line="109"/>
@@ -1912,22 +1912,22 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/license/LicenseWidget.cpp" line="163"/>
<source>File: %1</source>
<translation type="unfinished"/>
<translation>Fichièr: %1</translation>
</message>
<message>
<location filename="../src/modules/license/LicenseWidget.cpp" line="186"/>
<source>Hide license text</source>
<translation type="unfinished"/>
<translation>Amagar lo tèxte de licéncia</translation>
</message>
<message>
<location filename="../src/modules/license/LicenseWidget.cpp" line="186"/>
<source>Show the license text</source>
<translation type="unfinished"/>
<translation>Mostrar lo tèxte de licéncia</translation>
</message>
<message>
<location filename="../src/modules/license/LicenseWidget.cpp" line="190"/>
<source>Open license agreement in browser.</source>
<translation type="unfinished"/>
<translation>Dobrir lacòrd de licéncia dins lo navegador.</translation>
</message>
</context>
<context>
@@ -1935,18 +1935,18 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/locale/LocalePage.cpp" line="130"/>
<source>Region:</source>
<translation type="unfinished"/>
<translation>Region:</translation>
</message>
<message>
<location filename="../src/modules/locale/LocalePage.cpp" line="131"/>
<source>Zone:</source>
<translation type="unfinished"/>
<translation>Zòna;</translation>
</message>
<message>
<location filename="../src/modules/locale/LocalePage.cpp" line="132"/>
<location filename="../src/modules/locale/LocalePage.cpp" line="133"/>
<source>&amp;Change...</source>
<translation type="unfinished"/>
<translation>&amp;Cambiar...</translation>
</message>
</context>
<context>
@@ -2032,7 +2032,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/localeq/Map.qml" line="243"/>
<source>Timezone: %1</source>
<translation type="unfinished"/>
<translation>Fus orari: %1</translation>
</message>
<message>
<location filename="../src/modules/localeq/Map.qml" line="264"/>
@@ -2047,7 +2047,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="49"/>
<source>Package selection</source>
<translation type="unfinished"/>
<translation>Seleccion dels paquets</translation>
</message>
<message>
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="50"/>
@@ -2067,17 +2067,17 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="53"/>
<source>Browser package</source>
<translation type="unfinished"/>
<translation>Percórrer lo paquet</translation>
</message>
<message>
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="54"/>
<source>Web browser</source>
<translation type="unfinished"/>
<translation>Navegador web</translation>
</message>
<message>
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="55"/>
<source>Kernel</source>
<translation type="unfinished"/>
<translation>Nuclèu</translation>
</message>
<message>
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="56"/>
@@ -2087,7 +2087,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="57"/>
<source>Login</source>
<translation type="unfinished"/>
<translation>Connexion</translation>
</message>
<message>
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="58"/>
@@ -2127,7 +2127,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="65"/>
<source>Theming</source>
<translation type="unfinished"/>
<translation>Personalizacion</translation>
</message>
<message>
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="66"/>
@@ -2171,7 +2171,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/oemid/OEMViewStep.cpp" line="122"/>
<source>OEM Configuration</source>
<translation type="unfinished"/>
<translation>Configuracion OEM</translation>
</message>
<message>
<location filename="../src/modules/oemid/OEMViewStep.cpp" line="128"/>
@@ -2191,7 +2191,7 @@ The installer will quit and all changes will be lost.</source>
<location filename="../src/modules/localeq/Offline.qml" line="173"/>
<location filename="../src/modules/localeq/Offline.qml" line="217"/>
<source>Timezone: %1</source>
<translation type="unfinished"/>
<translation>Fus orari: %1</translation>
</message>
<message>
<location filename="../src/modules/localeq/Offline.qml" line="115"/>
@@ -2214,17 +2214,17 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/users/CheckPWQuality.cpp" line="51"/>
<source>Password is too short</source>
<translation type="unfinished"/>
<translation>Lo senhal es tròp cort</translation>
</message>
<message>
<location filename="../src/modules/users/CheckPWQuality.cpp" line="67"/>
<source>Password is too long</source>
<translation type="unfinished"/>
<translation>Lo senhal es tròp long</translation>
</message>
<message>
<location filename="../src/modules/users/CheckPWQuality.cpp" line="188"/>
<source>Password is too weak</source>
<translation type="unfinished"/>
<translation>Lo senhal es tròp feble</translation>
</message>
<message>
<location filename="../src/modules/users/CheckPWQuality.cpp" line="196"/>
@@ -2302,7 +2302,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/users/CheckPWQuality.cpp" line="249"/>
<source>The password is too short</source>
<translation type="unfinished"/>
<translation>Lo senhal es tròp cort</translation>
</message>
<message>
<location filename="../src/modules/users/CheckPWQuality.cpp" line="258"/>
@@ -2421,7 +2421,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/users/CheckPWQuality.cpp" line="305"/>
<source>Unknown setting - %1</source>
<translation type="unfinished"/>
<translation>Paramètre desconegut - %1</translation>
</message>
<message>
<location filename="../src/modules/users/CheckPWQuality.cpp" line="307"/>
@@ -2436,7 +2436,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/users/CheckPWQuality.cpp" line="313"/>
<source>Bad integer value</source>
<translation type="unfinished"/>
<translation>Marrida valor dentièr</translation>
</message>
<message>
<location filename="../src/modules/users/CheckPWQuality.cpp" line="317"/>
@@ -2476,7 +2476,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/users/CheckPWQuality.cpp" line="333"/>
<source>Unknown error</source>
<translation type="unfinished"/>
<translation>Error desconeguda</translation>
</message>
<message>
<location filename="../src/modules/users/Config.cpp" line="818"/>
@@ -2509,7 +2509,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/packagechooser/PackageChooserPage.cpp" line="25"/>
<source>Package Selection</source>
<translation type="unfinished"/>
<translation>Seleccion dels paquets</translation>
</message>
<message>
<location filename="../src/modules/packagechooser/PackageChooserPage.cpp" line="26"/>
@@ -2522,7 +2522,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/packagechooserq/PackageChooserQmlViewStep.cpp" line="32"/>
<source>Packages</source>
<translation type="unfinished"/>
<translation>Paquets</translation>
</message>
</context>
<context>
@@ -2530,7 +2530,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/packagechooser/PackageChooserViewStep.cpp" line="51"/>
<source>Packages</source>
<translation type="unfinished"/>
<translation>Paquets</translation>
</message>
</context>
<context>
@@ -2556,7 +2556,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/keyboard/KeyboardPage.ui" line="74"/>
<source>Keyboard Model:</source>
<translation type="unfinished"/>
<translation>Modèl de clavièr:</translation>
</message>
<message>
<location filename="../src/modules/keyboard/KeyboardPage.ui" line="135"/>
@@ -2574,27 +2574,27 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/users/page_usersetup.ui" line="40"/>
<source>What is your name?</source>
<translation type="unfinished"/>
<translation>Cossí vos dison?</translation>
</message>
<message>
<location filename="../src/modules/users/page_usersetup.ui" line="55"/>
<source>Your Full Name</source>
<translation type="unfinished"/>
<translation>Vòstre nom complèt</translation>
</message>
<message>
<location filename="../src/modules/users/page_usersetup.ui" line="124"/>
<source>What name do you want to use to log in?</source>
<translation type="unfinished"/>
<translation>Qual nom volètz utilizar per vos connectar?</translation>
</message>
<message>
<location filename="../src/modules/users/page_usersetup.ui" line="148"/>
<source>login</source>
<translation type="unfinished"/>
<translation>identificant</translation>
</message>
<message>
<location filename="../src/modules/users/page_usersetup.ui" line="223"/>
<source>What is the name of this computer?</source>
<translation type="unfinished"/>
<translation>Cossí sapèla aqueste ordenador?</translation>
</message>
<message>
<location filename="../src/modules/users/page_usersetup.ui" line="247"/>
@@ -2604,7 +2604,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/users/page_usersetup.ui" line="250"/>
<source>Computer Name</source>
<translation type="unfinished"/>
<translation>Nom de lordenador</translation>
</message>
<message>
<location filename="../src/modules/users/page_usersetup.ui" line="325"/>
@@ -2671,17 +2671,17 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/partition/gui/PartitionLabelsView.cpp" line="193"/>
<source>Home</source>
<translation type="unfinished"/>
<translation>Home</translation>
</message>
<message>
<location filename="../src/modules/partition/gui/PartitionLabelsView.cpp" line="197"/>
<source>Boot</source>
<translation type="unfinished"/>
<translation>Boot</translation>
</message>
<message>
<location filename="../src/modules/partition/gui/PartitionLabelsView.cpp" line="202"/>
<source>EFI system</source>
<translation type="unfinished"/>
<translation>Sistèma EFI</translation>
</message>
<message>
<location filename="../src/modules/partition/gui/PartitionLabelsView.cpp" line="206"/>
@@ -2696,13 +2696,13 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/partition/gui/PartitionLabelsView.cpp" line="214"/>
<source>New partition</source>
<translation type="unfinished"/>
<translation>Particion novèla</translation>
</message>
<message>
<location filename="../src/modules/partition/gui/PartitionLabelsView.cpp" line="238"/>
<source>%1 %2</source>
<extracomment>size[number] filesystem[name]</extracomment>
<translation type="unfinished"/>
<translation>%1 %2</translation>
</message>
</context>
<context>
@@ -2711,13 +2711,13 @@ The installer will quit and all changes will be lost.</source>
<location filename="../src/modules/partition/core/PartitionModel.cpp" line="157"/>
<location filename="../src/modules/partition/core/PartitionModel.cpp" line="201"/>
<source>Free Space</source>
<translation type="unfinished"/>
<translation>Espaci disponible</translation>
</message>
<message>
<location filename="../src/modules/partition/core/PartitionModel.cpp" line="161"/>
<location filename="../src/modules/partition/core/PartitionModel.cpp" line="205"/>
<source>New partition</source>
<translation type="unfinished"/>
<translation>Particion novèla</translation>
</message>
<message>
<location filename="../src/modules/partition/core/PartitionModel.cpp" line="298"/>
@@ -2737,7 +2737,7 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/partition/core/PartitionModel.cpp" line="304"/>
<source>Mount Point</source>
<translation type="unfinished"/>
<translation>Punt de montatge</translation>
</message>
<message>
<location filename="../src/modules/partition/core/PartitionModel.cpp" line="306"/>
@@ -2853,12 +2853,12 @@ The installer will quit and all changes will be lost.</source>
<message>
<location filename="../src/modules/partition/PartitionViewStep.cpp" line="300"/>
<source>Current:</source>
<translation type="unfinished"/>
<translation>Actual:</translation>
</message>
<message>
<location filename="../src/modules/partition/PartitionViewStep.cpp" line="318"/>
<source>After:</source>
<translation type="unfinished"/>
<translation>Aprèp:</translation>
</message>
<message>
<location filename="../src/modules/partition/PartitionViewStep.cpp" line="529"/>
@@ -3241,7 +3241,7 @@ Output:
<message>
<location filename="../src/modules/partition/gui/ReplaceWidget.cpp" line="277"/>
<source>EFI system partition:</source>
<translation type="unfinished"/>
<translation>Particion sistèma EFI:</translation>
</message>
</context>
<context>
@@ -3425,7 +3425,7 @@ Output:
<location filename="../src/modules/users/SetHostNameJob.cpp" line="124"/>
<location filename="../src/modules/users/SetHostNameJob.cpp" line="131"/>
<source>Internal Error</source>
<translation type="unfinished"/>
<translation>Error intèrna</translation>
</message>
<message>
<location filename="../src/modules/users/SetHostNameJob.cpp" line="142"/>
@@ -4018,22 +4018,22 @@ Output:
<message>
<location filename="../src/modules/welcome/WelcomePage.cpp" line="216"/>
<source>&lt;h1&gt;Welcome to the Calamares setup program for %1.&lt;/h1&gt;</source>
<translation type="unfinished"/>
<translation>&lt;h1&gt;La benvenguda al programa dinstallacion de Calamares per %1.&lt;/h1&gt;</translation>
</message>
<message>
<location filename="../src/modules/welcome/WelcomePage.cpp" line="217"/>
<source>&lt;h1&gt;Welcome to %1 setup.&lt;/h1&gt;</source>
<translation type="unfinished"/>
<translation>&lt;h1&gt;La benvenguda a la configuracion de %1.&lt;/h1&gt;</translation>
</message>
<message>
<location filename="../src/modules/welcome/WelcomePage.cpp" line="222"/>
<source>&lt;h1&gt;Welcome to the Calamares installer for %1.&lt;/h1&gt;</source>
<translation type="unfinished"/>
<translation>&lt;h1&gt;La benvenguda a linstallador de Calamares per %1.&lt;/h1&gt;</translation>
</message>
<message>
<location filename="../src/modules/welcome/WelcomePage.cpp" line="223"/>
<source>&lt;h1&gt;Welcome to the %1 installer.&lt;/h1&gt;</source>
<translation type="unfinished"/>
<translation>&lt;h1&gt;La benvenguda a linstallador de %1.&lt;/h1&gt;</translation>
</message>
<message>
<location filename="../src/modules/welcome/WelcomePage.cpp" line="228"/>
@@ -4164,12 +4164,12 @@ Output:
<message>
<location filename="../src/modules/finishedq/finishedq.qml" line="65"/>
<source>Close Installer</source>
<translation type="unfinished"/>
<translation>Tampar linstallador</translation>
</message>
<message>
<location filename="../src/modules/finishedq/finishedq.qml" line="71"/>
<source>Restart System</source>
<translation type="unfinished"/>
<translation>Reaviar lo sistèma</translation>
</message>
<message>
<location filename="../src/modules/finishedq/finishedq.qml" line="89"/>
@@ -4208,7 +4208,8 @@ Output:
<location filename="../src/modules/localeq/i18n.qml" line="50"/>
<source>&lt;h1&gt;Languages&lt;/h1&gt; &lt;/br&gt;
The system locale setting affects the language and character set for some command line user interface elements. The current setting is &lt;strong&gt;%1&lt;/strong&gt;.</source>
<translation type="unfinished"/>
<translation>&lt;h1&gt;Lengas&lt;/h1&gt; &lt;/br&gt;
Los paramètres de lingüistics del sistèma afèctan la lenga, lo jòc de caractèrs per dunes elements dinterfàcias de linha de comanda. Lo parametratge actual es &lt;strong&gt;%1&lt;/strong&gt;.</translation>
</message>
<message>
<location filename="../src/modules/localeq/i18n.qml" line="123"/>
@@ -4232,7 +4233,7 @@ Output:
<message>
<location filename="../src/modules/keyboardq/keyboardq.qml" line="86"/>
<source>Keyboard Model:</source>
<translation type="unfinished"/>
<translation>Modèl de clavièr:</translation>
</message>
<message>
<location filename="../src/modules/keyboardq/keyboardq.qml" line="254"/>
@@ -4349,17 +4350,17 @@ Output:
<message>
<location filename="../src/modules/usersq/usersq.qml" line="56"/>
<source>What is your name?</source>
<translation type="unfinished"/>
<translation>Cossí vos dison?</translation>
</message>
<message>
<location filename="../src/modules/usersq/usersq.qml" line="63"/>
<source>Your Full Name</source>
<translation type="unfinished"/>
<translation>Vòstre nom complèt</translation>
</message>
<message>
<location filename="../src/modules/usersq/usersq.qml" line="80"/>
<source>What name do you want to use to log in?</source>
<translation type="unfinished"/>
<translation>Qual nom volètz utilizar per vos connectar?</translation>
</message>
<message>
<location filename="../src/modules/usersq/usersq.qml" line="87"/>
@@ -4374,7 +4375,7 @@ Output:
<message>
<location filename="../src/modules/usersq/usersq.qml" line="128"/>
<source>Only lowercase letters, numbers, underscore and hyphen are allowed.</source>
<translation type="unfinished"/>
<translation>Son solament permeses las letras, nombres, jonhents basses e los tirets.</translation>
</message>
<message>
<location filename="../src/modules/usersq/usersq.qml" line="136"/>
@@ -4384,12 +4385,12 @@ Output:
<message>
<location filename="../src/modules/usersq/usersq.qml" line="145"/>
<source>What is the name of this computer?</source>
<translation type="unfinished"/>
<translation>Cossí sapèla aqueste ordenador?</translation>
</message>
<message>
<location filename="../src/modules/usersq/usersq.qml" line="151"/>
<source>Computer Name</source>
<translation type="unfinished"/>
<translation>Nom de lordenador</translation>
</message>
<message>
<location filename="../src/modules/usersq/usersq.qml" line="178"/>

View File

@@ -240,7 +240,7 @@
<message>
<location filename="../src/libcalamaresui/viewpages/QmlViewStep.cpp" line="67"/>
<source>Loading ...</source>
<translation type="unfinished"/>
<translation>Ładowanie...</translation>
</message>
<message>
<location filename="../src/libcalamaresui/viewpages/QmlViewStep.cpp" line="88"/>
@@ -360,7 +360,7 @@ Link copied to clipboard</source>
<message>
<location filename="../src/libcalamaresui/ViewManager.cpp" line="310"/>
<source>Continue with installation?</source>
<translation type="unfinished"/>
<translation>Kontynuować instalację?</translation>
</message>
<message>
<location filename="../src/libcalamaresui/ViewManager.cpp" line="312"/>
@@ -502,7 +502,7 @@ Instalator zostanie zamknięty i wszystkie zmiany zostaną utracone.</translatio
<message>
<location filename="../src/modules/partition/jobs/ChangeFilesystemLabelJob.cpp" line="32"/>
<source>Set filesystem label on %1.</source>
<translation type="unfinished"/>
<translation>Ustaw etykietę systemu plików na %1.</translation>
</message>
<message>
<location filename="../src/modules/partition/jobs/ChangeFilesystemLabelJob.cpp" line="39"/>
@@ -683,7 +683,7 @@ Instalator zostanie zamknięty i wszystkie zmiany zostaną utracone.</translatio
<message>
<location filename="../src/modules/partition/jobs/ClearMountsJob.cpp" line="272"/>
<source>Successfully unmounted %1.</source>
<translation type="unfinished"/>
<translation>Pomyślnie odmontowano %1.</translation>
</message>
<message>
<location filename="../src/modules/partition/jobs/ClearMountsJob.cpp" line="279"/>
@@ -868,7 +868,7 @@ Instalator zostanie zamknięty i wszystkie zmiany zostaną utracone.</translatio
<message>
<location filename="../src/modules/users/Config.cpp" line="227"/>
<source>'%1' is not allowed as username.</source>
<translation type="unfinished"/>
<translation>'%1' nie może zostać użyte jako nazwa użytkownika.</translation>
</message>
<message>
<location filename="../src/modules/users/Config.cpp" line="234"/>
@@ -908,7 +908,7 @@ Instalator zostanie zamknięty i wszystkie zmiany zostaną utracone.</translatio
<message>
<location filename="../src/modules/users/Config.cpp" line="587"/>
<source>OK!</source>
<translation type="unfinished"/>
<translation>OK!</translation>
</message>
<message>
<location filename="../src/modules/finished/Config.cpp" line="145"/>
@@ -953,7 +953,7 @@ Instalator zostanie zamknięty i wszystkie zmiany zostaną utracone.</translatio
<message>
<location filename="../src/modules/packagechooser/Config.cpp" line="111"/>
<source>Package Selection</source>
<translation type="unfinished"/>
<translation>Wybór Pakietów</translation>
</message>
<message>
<location filename="../src/modules/packagechooser/Config.cpp" line="113"/>
@@ -1049,7 +1049,7 @@ Instalator zostanie zamknięty i wszystkie zmiany zostaną utracone.</translatio
<message>
<location filename="../src/modules/partition/gui/CreatePartitionDialog.ui" line="224"/>
<source>Label for the filesystem</source>
<translation type="unfinished"/>
<translation>Etykieta dla systemu plików</translation>
</message>
<message>
<location filename="../src/modules/partition/gui/CreatePartitionDialog.ui" line="234"/>
@@ -1084,7 +1084,7 @@ Instalator zostanie zamknięty i wszystkie zmiany zostaną utracone.</translatio
<message>
<location filename="../src/modules/partition/gui/PartitionDialogHelpers.cpp" line="96"/>
<source>Mountpoint must start with a &lt;tt&gt;/&lt;/tt&gt;.</source>
<translation type="unfinished"/>
<translation>Punkt montowania musi się zaczynać od &lt;tt&gt;/&lt;/tt&gt;.</translation>
</message>
</context>
<context>
@@ -1418,7 +1418,7 @@ Instalator zostanie zamknięty i wszystkie zmiany zostaną utracone.</translatio
<message>
<location filename="../src/modules/partition/gui/EditExistingPartitionDialog.ui" line="179"/>
<source>Label for the filesystem</source>
<translation type="unfinished"/>
<translation>Etykieta dla systemu plików</translation>
</message>
<message>
<location filename="../src/modules/partition/gui/EditExistingPartitionDialog.ui" line="189"/>
@@ -2037,7 +2037,7 @@ Instalator zostanie zamknięty i wszystkie zmiany zostaną utracone.</translatio
<message>
<location filename="../src/modules/localeq/Map.qml" line="243"/>
<source>Timezone: %1</source>
<translation type="unfinished"/>
<translation>Strefa czasowa: %1</translation>
</message>
<message>
<location filename="../src/modules/localeq/Map.qml" line="264"/>
@@ -2196,7 +2196,7 @@ Instalator zostanie zamknięty i wszystkie zmiany zostaną utracone.</translatio
<location filename="../src/modules/localeq/Offline.qml" line="173"/>
<location filename="../src/modules/localeq/Offline.qml" line="217"/>
<source>Timezone: %1</source>
<translation type="unfinished"/>
<translation>Strefa czasowa: %1</translation>
</message>
<message>
<location filename="../src/modules/localeq/Offline.qml" line="115"/>
@@ -2289,11 +2289,11 @@ Instalator zostanie zamknięty i wszystkie zmiany zostaną utracone.</translatio
<message numerus="yes">
<location filename="../src/modules/users/CheckPWQuality.cpp" line="232"/>
<source>The password contains fewer than %n lowercase letters</source>
<translation type="unfinished">
<numerusform/>
<numerusform/>
<numerusform/>
<numerusform/>
<translation>
<numerusform>Hasło składa się z mniej niż %1 małej litery</numerusform>
<numerusform>Hasło składa się z mniej niż %1 małych liter</numerusform>
<numerusform>Hasło składa się z mniej niż %1 małych liter</numerusform>
<numerusform>Hasło składa się z mniej niż %1 małych liter</numerusform>
</translation>
</message>
<message>
@@ -2504,7 +2504,7 @@ Instalator zostanie zamknięty i wszystkie zmiany zostaną utracone.</translatio
<message>
<location filename="../src/modules/users/Config.cpp" line="818"/>
<source>Password is empty</source>
<translation type="unfinished"/>
<translation>Hasło jest puste</translation>
</message>
</context>
<context>
@@ -2532,7 +2532,7 @@ Instalator zostanie zamknięty i wszystkie zmiany zostaną utracone.</translatio
<message>
<location filename="../src/modules/packagechooser/PackageChooserPage.cpp" line="25"/>
<source>Package Selection</source>
<translation type="unfinished"/>
<translation>Wybór Pakietów</translation>
</message>
<message>
<location filename="../src/modules/packagechooser/PackageChooserPage.cpp" line="26"/>
@@ -2545,7 +2545,7 @@ Instalator zostanie zamknięty i wszystkie zmiany zostaną utracone.</translatio
<message>
<location filename="../src/modules/packagechooserq/PackageChooserQmlViewStep.cpp" line="32"/>
<source>Packages</source>
<translation type="unfinished"/>
<translation>Pakiety</translation>
</message>
</context>
<context>
@@ -2553,7 +2553,7 @@ Instalator zostanie zamknięty i wszystkie zmiany zostaną utracone.</translatio
<message>
<location filename="../src/modules/packagechooser/PackageChooserViewStep.cpp" line="51"/>
<source>Packages</source>
<translation type="unfinished"/>
<translation>Pakiety</translation>
</message>
</context>
<context>
@@ -2602,7 +2602,7 @@ Instalator zostanie zamknięty i wszystkie zmiany zostaną utracone.</translatio
<message>
<location filename="../src/modules/users/page_usersetup.ui" line="55"/>
<source>Your Full Name</source>
<translation type="unfinished"/>
<translation>Twoja Pełne Imię</translation>
</message>
<message>
<location filename="../src/modules/users/page_usersetup.ui" line="124"/>
@@ -2612,7 +2612,7 @@ Instalator zostanie zamknięty i wszystkie zmiany zostaną utracone.</translatio
<message>
<location filename="../src/modules/users/page_usersetup.ui" line="148"/>
<source>login</source>
<translation type="unfinished"/>
<translation>login</translation>
</message>
<message>
<location filename="../src/modules/users/page_usersetup.ui" line="223"/>
@@ -2627,7 +2627,7 @@ Instalator zostanie zamknięty i wszystkie zmiany zostaną utracone.</translatio
<message>
<location filename="../src/modules/users/page_usersetup.ui" line="250"/>
<source>Computer Name</source>
<translation type="unfinished"/>
<translation>Nazwa Komputera</translation>
</message>
<message>
<location filename="../src/modules/users/page_usersetup.ui" line="325"/>
@@ -2644,13 +2644,13 @@ Instalator zostanie zamknięty i wszystkie zmiany zostaną utracone.</translatio
<location filename="../src/modules/users/page_usersetup.ui" line="355"/>
<location filename="../src/modules/users/page_usersetup.ui" line="525"/>
<source>Password</source>
<translation type="unfinished"/>
<translation>Hasło</translation>
</message>
<message>
<location filename="../src/modules/users/page_usersetup.ui" line="380"/>
<location filename="../src/modules/users/page_usersetup.ui" line="550"/>
<source>Repeat Password</source>
<translation type="unfinished"/>
<translation>Powtórz Hasło</translation>
</message>
<message>
<location filename="../src/modules/users/page_usersetup.ui" line="455"/>
@@ -2755,7 +2755,7 @@ Instalator zostanie zamknięty i wszystkie zmiany zostaną utracone.</translatio
<message>
<location filename="../src/modules/partition/core/PartitionModel.cpp" line="302"/>
<source>File System Label</source>
<translation type="unfinished"/>
<translation>Etykieta Systemu Plików</translation>
</message>
<message>
<location filename="../src/modules/partition/core/PartitionModel.cpp" line="304"/>
@@ -2901,7 +2901,7 @@ Instalator zostanie zamknięty i wszystkie zmiany zostaną utracone.</translatio
<message>
<location filename="../src/modules/partition/PartitionViewStep.cpp" line="549"/>
<source>The filesystem must be mounted on &lt;strong&gt;%1&lt;/strong&gt;.</source>
<translation type="unfinished"/>
<translation>System plików musi zostać zamontowany w &lt;strong&gt;%1&lt;/strong&gt;.</translation>
</message>
<message>
<location filename="../src/modules/partition/PartitionViewStep.cpp" line="555"/>
@@ -3120,7 +3120,7 @@ Wyjście:
<location filename="../src/modules/machineid/Workers.cpp" line="76"/>
<location filename="../src/modules/machineid/Workers.cpp" line="93"/>
<source>File not found</source>
<translation type="unfinished"/>
<translation>Plik nie został znaleziony</translation>
</message>
<message>
<location filename="../src/modules/machineid/Workers.cpp" line="65"/>
@@ -3130,7 +3130,7 @@ Wyjście:
<message>
<location filename="../src/modules/machineid/MachineIdJob.cpp" line="83"/>
<source>Directory not found</source>
<translation type="unfinished"/>
<translation>Katalog nie został znaleziony</translation>
</message>
<message>
<location filename="../src/modules/machineid/MachineIdJob.cpp" line="84"/>
@@ -3922,7 +3922,7 @@ i nie uruchomi się</translation>
<location filename="../src/calamares/VariantModel.cpp" line="232"/>
<source>Key</source>
<comment>Column header for key/value</comment>
<translation type="unfinished"/>
<translation>Klucz</translation>
</message>
<message>
<location filename="../src/calamares/VariantModel.cpp" line="236"/>
@@ -4164,7 +4164,7 @@ i nie uruchomi się</translation>
<message>
<location filename="../src/modules/welcomeq/about.qml" line="96"/>
<source>Back</source>
<translation type="unfinished"/>
<translation>Wstecz</translation>
</message>
</context>
<context>
@@ -4180,7 +4180,7 @@ i nie uruchomi się</translation>
<message>
<location filename="../src/modules/finishedq/finishedq.qml" line="36"/>
<source>Installation Completed</source>
<translation type="unfinished"/>
<translation>Instalacja została zakończona</translation>
</message>
<message>
<location filename="../src/modules/finishedq/finishedq.qml" line="43"/>
@@ -4191,12 +4191,12 @@ i nie uruchomi się</translation>
<message>
<location filename="../src/modules/finishedq/finishedq.qml" line="65"/>
<source>Close Installer</source>
<translation type="unfinished"/>
<translation>Zamknij instalator</translation>
</message>
<message>
<location filename="../src/modules/finishedq/finishedq.qml" line="71"/>
<source>Restart System</source>
<translation type="unfinished"/>
<translation>Uruchom ponownie system</translation>
</message>
<message>
<location filename="../src/modules/finishedq/finishedq.qml" line="89"/>
@@ -4210,7 +4210,7 @@ i nie uruchomi się</translation>
<message>
<location filename="../src/modules/finishedq/finishedq@mobile.qml" line="36"/>
<source>Installation Completed</source>
<translation type="unfinished"/>
<translation>Instalacja została zakończona</translation>
</message>
<message>
<location filename="../src/modules/finishedq/finishedq@mobile.qml" line="43"/>
@@ -4246,7 +4246,7 @@ i nie uruchomi się</translation>
<message>
<location filename="../src/modules/localeq/i18n.qml" line="189"/>
<source>Back</source>
<translation type="unfinished"/>
<translation>Wstecz</translation>
</message>
</context>
<context>
@@ -4363,7 +4363,7 @@ i nie uruchomi się</translation>
<message>
<location filename="../src/modules/welcomeq/release_notes.qml" line="76"/>
<source>Back</source>
<translation type="unfinished"/>
<translation>Wstecz</translation>
</message>
</context>
<context>
@@ -4381,7 +4381,7 @@ i nie uruchomi się</translation>
<message>
<location filename="../src/modules/usersq/usersq.qml" line="63"/>
<source>Your Full Name</source>
<translation type="unfinished"/>
<translation>Twoja Pełne Imię</translation>
</message>
<message>
<location filename="../src/modules/usersq/usersq.qml" line="80"/>
@@ -4416,7 +4416,7 @@ i nie uruchomi się</translation>
<message>
<location filename="../src/modules/usersq/usersq.qml" line="151"/>
<source>Computer Name</source>
<translation type="unfinished"/>
<translation>Nazwa Komputera</translation>
</message>
<message>
<location filename="../src/modules/usersq/usersq.qml" line="178"/>
@@ -4436,12 +4436,12 @@ i nie uruchomi się</translation>
<message>
<location filename="../src/modules/usersq/usersq.qml" line="217"/>
<source>Password</source>
<translation type="unfinished"/>
<translation>Hasło</translation>
</message>
<message>
<location filename="../src/modules/usersq/usersq.qml" line="234"/>
<source>Repeat Password</source>
<translation type="unfinished"/>
<translation>Powtórz Hasło</translation>
</message>
<message>
<location filename="../src/modules/usersq/usersq.qml" line="261"/>

View File

@@ -67,8 +67,7 @@ CalamaresApplication::init()
{
Logger::setupLogfile();
cDebug() << "Calamares version:" << CALAMARES_VERSION;
cDebug() << Logger::SubEntry
<< "languages:" << QString( CALAMARES_TRANSLATION_LANGUAGES ).replace( ";", ", " );
cDebug() << Logger::SubEntry << "languages:" << QString( CALAMARES_TRANSLATION_LANGUAGES ).replace( ";", ", " );
if ( !Calamares::Settings::instance() )
{

View File

@@ -134,10 +134,9 @@ getWidgetSidebar( Calamares::DebugWindowManager* debug,
{
QPushButton* debugWindowBtn = new QPushButton;
debugWindowBtn->setObjectName( "debugButton" );
CALAMARES_RETRANSLATE_FOR(
debugWindowBtn,
debugWindowBtn->setText( QCoreApplication::translate( CalamaresWindow::staticMetaObject.className(),
"Show debug information" ) ); );
CALAMARES_RETRANSLATE_FOR( debugWindowBtn,
debugWindowBtn->setText( QCoreApplication::translate(
CalamaresWindow::staticMetaObject.className(), "Show debug information" ) ); );
sideLayout->addWidget( debugWindowBtn );
debugWindowBtn->setFlat( true );
debugWindowBtn->setCheckable( true );
@@ -173,7 +172,7 @@ getWidgetNavigation( Calamares::DebugWindowManager*,
QObject::connect( viewManager, &Calamares::ViewManager::backEnabledChanged, back, &QPushButton::setEnabled );
QObject::connect( viewManager, &Calamares::ViewManager::backLabelChanged, back, &QPushButton::setText );
QObject::connect(
viewManager, &Calamares::ViewManager::backIconChanged, [=]( QString n ) { setButtonIcon( back, n ); } );
viewManager, &Calamares::ViewManager::backIconChanged, [ = ]( QString n ) { setButtonIcon( back, n ); } );
QObject::connect(
viewManager, &Calamares::ViewManager::backAndNextVisibleChanged, back, &QPushButton::setVisible );
bottomLayout->addWidget( back );
@@ -189,7 +188,7 @@ getWidgetNavigation( Calamares::DebugWindowManager*,
QObject::connect( viewManager, &Calamares::ViewManager::nextEnabledChanged, next, &QPushButton::setEnabled );
QObject::connect( viewManager, &Calamares::ViewManager::nextLabelChanged, next, &QPushButton::setText );
QObject::connect(
viewManager, &Calamares::ViewManager::nextIconChanged, [=]( QString n ) { setButtonIcon( next, n ); } );
viewManager, &Calamares::ViewManager::nextIconChanged, [ = ]( QString n ) { setButtonIcon( next, n ); } );
QObject::connect(
viewManager, &Calamares::ViewManager::backAndNextVisibleChanged, next, &QPushButton::setVisible );
bottomLayout->addWidget( next );
@@ -205,7 +204,7 @@ getWidgetNavigation( Calamares::DebugWindowManager*,
QObject::connect( viewManager, &Calamares::ViewManager::quitEnabledChanged, quit, &QPushButton::setEnabled );
QObject::connect( viewManager, &Calamares::ViewManager::quitLabelChanged, quit, &QPushButton::setText );
QObject::connect(
viewManager, &Calamares::ViewManager::quitIconChanged, [=]( QString n ) { setButtonIcon( quit, n ); } );
viewManager, &Calamares::ViewManager::quitIconChanged, [ = ]( QString n ) { setButtonIcon( quit, n ); } );
QObject::connect( viewManager, &Calamares::ViewManager::quitTooltipChanged, quit, &QPushButton::setToolTip );
QObject::connect( viewManager, &Calamares::ViewManager::quitVisibleChanged, quit, &QPushButton::setVisible );
bottomLayout->addWidget( quit );

View File

@@ -85,17 +85,22 @@ DebugWindow::DebugWindow()
m_ui->globalStorageView->expandAll();
// Do above when the GS changes, too
connect( gs, &GlobalStorage::changed, this, [=] {
m_globals = JobQueue::instance()->globalStorage()->data();
m_globals_model->reload();
m_ui->globalStorageView->expandAll();
} );
connect( gs,
&GlobalStorage::changed,
this,
[ = ]
{
m_globals = JobQueue::instance()->globalStorage()->data();
m_globals_model->reload();
m_ui->globalStorageView->expandAll();
} );
// JobQueue page
m_ui->jobQueueText->setReadOnly( true );
connect( JobQueue::instance(), &JobQueue::queueChanged, this, [this]( const QStringList& jobs ) {
m_ui->jobQueueText->setText( jobs.join( '\n' ) );
} );
connect( JobQueue::instance(),
&JobQueue::queueChanged,
this,
[ this ]( const QStringList& jobs ) { m_ui->jobQueueText->setText( jobs.join( '\n' ) ); } );
// Modules page
QStringList modulesKeys;
@@ -116,67 +121,74 @@ DebugWindow::DebugWindow()
m_ui->modulesVerticalLayout->insertWidget( 1, pythonConsoleButton );
pythonConsoleButton->hide();
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 )
return;
for ( ViewStep* step : ViewManager::instance()->viewSteps() )
QObject::connect(
pythonConsoleButton,
&QPushButton::clicked,
this,
[ this, moduleConfigModel ]
{
if ( step->moduleInstanceKey() == module->instanceKey() )
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 )
return;
for ( ViewStep* step : ViewManager::instance()->viewSteps() )
{
PythonQtViewStep* pqvs = qobject_cast< PythonQtViewStep* >( step );
if ( pqvs )
if ( step->moduleInstanceKey() == module->instanceKey() )
{
QWidget* consoleWindow = new QWidget;
PythonQtViewStep* pqvs = qobject_cast< PythonQtViewStep* >( step );
if ( pqvs )
{
QWidget* consoleWindow = new QWidget;
QWidget* console = pqvs->createScriptingConsole();
console->setParent( consoleWindow );
QWidget* console = pqvs->createScriptingConsole();
console->setParent( consoleWindow );
QVBoxLayout* layout = new QVBoxLayout;
consoleWindow->setLayout( layout );
layout->addWidget( console );
QVBoxLayout* layout = new QVBoxLayout;
consoleWindow->setLayout( layout );
layout->addWidget( console );
QHBoxLayout* bottomLayout = new QHBoxLayout;
layout->addLayout( bottomLayout );
QHBoxLayout* bottomLayout = new QHBoxLayout;
layout->addLayout( bottomLayout );
QLabel* bottomLabel = new QLabel( consoleWindow );
bottomLayout->addWidget( bottomLabel );
QString line = QString( "Module: <font color=\"#008000\"><code>%1</code></font><br/>"
"Python class: <font color=\"#008000\"><code>%2</code></font>" )
.arg( module->instanceKey() )
.arg( console->property( "classname" ).toString() );
bottomLabel->setText( line );
QLabel* bottomLabel = new QLabel( consoleWindow );
bottomLayout->addWidget( bottomLabel );
QString line = QString( "Module: <font color=\"#008000\"><code>%1</code></font><br/>"
"Python class: <font color=\"#008000\"><code>%2</code></font>" )
.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(); } );
bottomLayout->addWidget( closeButton );
bottomLabel->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );
QPushButton* closeButton = new QPushButton( consoleWindow );
closeButton->setText( "&Close" );
QObject::connect(
closeButton, &QPushButton::clicked, [ consoleWindow ] { consoleWindow->close(); } );
bottomLayout->addWidget( closeButton );
bottomLabel->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );
consoleWindow->setParent( this );
consoleWindow->setWindowFlags( Qt::Window );
consoleWindow->setWindowTitle( "Calamares Python console" );
consoleWindow->setAttribute( Qt::WA_DeleteOnClose, true );
consoleWindow->showNormal();
break;
consoleWindow->setParent( this );
consoleWindow->setWindowFlags( Qt::Window );
consoleWindow->setWindowTitle( "Calamares Python console" );
consoleWindow->setAttribute( Qt::WA_DeleteOnClose, true );
consoleWindow->showNormal();
break;
}
}
}
}
} );
} );
#endif
connect( m_ui->modulesListView->selectionModel(),
&QItemSelectionModel::selectionChanged,
this,
[this
[ this
#ifdef WITH_PYTHONQT
,
pythonConsoleButton
,
pythonConsoleButton
#endif
] {
]
{
QString moduleName = m_ui->modulesListView->currentIndex().data().toString();
Module* module
= ModuleManager::instance()->moduleInstance( ModuleSystem::InstanceKey::fromString( moduleName ) );
@@ -196,27 +208,33 @@ DebugWindow::DebugWindow()
// 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 );
}
} );
// Send Log button only if it would be useful
m_ui->sendLogButton->setVisible( CalamaresUtils::Paste::isEnabled() );
connect( m_ui->sendLogButton, &QPushButton::clicked, [this]() { CalamaresUtils::Paste::doLogUploadUI( this ); } );
connect( m_ui->sendLogButton, &QPushButton::clicked, [ this ]() { CalamaresUtils::Paste::doLogUploadUI( this ); } );
CALAMARES_RETRANSLATE( m_ui->retranslateUi( this ); setWindowTitle( tr( "Debug information" ) ); );
}
@@ -260,11 +278,15 @@ DebugWindowManager::show( bool visible )
{
m_debugWindow = new Calamares::DebugWindow();
m_debugWindow->show();
connect( m_debugWindow.data(), &Calamares::DebugWindow::closed, this, [=]() {
m_debugWindow->deleteLater();
m_visible = false;
emit visibleChanged( false );
} );
connect( m_debugWindow.data(),
&Calamares::DebugWindow::closed,
this,
[ = ]()
{
m_debugWindow->deleteLater();
m_visible = false;
emit visibleChanged( false );
} );
m_visible = true;
emit visibleChanged( true );
}

View File

@@ -51,6 +51,6 @@ ProgressTreeView::setModel( QAbstractItemModel* model )
Calamares::ViewManager::instance(),
&Calamares::ViewManager::currentStepChanged,
this,
[this]() { viewport()->update(); },
[ this ]() { viewport()->update(); },
Qt::UniqueConnection );
}

View File

@@ -89,9 +89,10 @@ public:
= m_queuedJobs->isEmpty() ? 0.0 : ( m_queuedJobs->last().cumulative + m_queuedJobs->last().weight );
qreal totalJobWeight
= std::accumulate( jobs.cbegin(), jobs.cend(), qreal( 0.0 ), []( qreal total, const job_ptr& j ) {
return total + j->getJobWeight();
} );
= std::accumulate( jobs.cbegin(),
jobs.cend(),
qreal( 0.0 ),
[]( qreal total, const job_ptr& j ) { return total + j->getJobWeight(); } );
if ( totalJobWeight < 1 )
{
totalJobWeight = 1.0;

View File

@@ -211,14 +211,14 @@ _process_output( Calamares::Utils::RunLocation location,
bp::extract< bp::list > x( callback );
if ( x.check() )
{
QObject::connect( &r, &decltype( r )::output, [cb = callback.attr( "append" )]( const QString& s ) {
cb( s.toStdString() );
} );
QObject::connect( &r,
&decltype( r )::output,
[ cb = callback.attr( "append" ) ]( const QString& s ) { cb( s.toStdString() ); } );
}
else
{
QObject::connect(
&r, &decltype( r )::output, [&callback]( const QString& s ) { callback( s.toStdString() ); } );
&r, &decltype( r )::output, [ &callback ]( const QString& s ) { callback( s.toStdString() ); } );
}
r.enableOutputProcessing();
}

View File

@@ -290,7 +290,7 @@ Settings::reconcileInstancesAndSequence()
// Since moduleFinder captures targetKey by reference, we can
// update targetKey to change what the finder lambda looks for.
Calamares::ModuleSystem::InstanceKey targetKey;
auto moduleFinder = [&targetKey]( const InstanceDescription& d ) { return d.isValid() && d.key() == targetKey; };
auto moduleFinder = [ &targetKey ]( const InstanceDescription& d ) { return d.isValid() && d.key() == targetKey; };
// Check the sequence against the existing instances (which so far are only custom)
for ( const auto& step : m_modulesSequence )

View File

@@ -425,9 +425,8 @@ sequence:
// Make a lambda where we can adjust what it looks for from the outside,
// by capturing a reference.
QString moduleKey = QString( "welcome" );
auto moduleFinder = [&moduleKey]( const Calamares::InstanceDescription& d ) {
return d.isValid() && d.key().module() == moduleKey;
};
auto moduleFinder = [ &moduleKey ]( const Calamares::InstanceDescription& d )
{ return d.isValid() && d.key().module() == moduleKey; };
const auto it0 = std::find_if( s.moduleInstances().constBegin(), s.moduleInstances().constEnd(), moduleFinder );
QVERIFY( it0 != s.moduleInstances().constEnd() );

View File

@@ -150,7 +150,7 @@ 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
@@ -171,7 +171,7 @@ 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 GeoIP

View File

@@ -43,9 +43,9 @@ lookup( TwoChar c )
}
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 );
} );
= 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;
@@ -86,7 +86,7 @@ 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; } );
[ c = country ]( const CountryData& d ) { return d.c == c; } );
if ( p == country_data_table + country_data_size )
{
return QLocale::Language::AnyLanguage;

View File

@@ -224,16 +224,19 @@ public:
loadTZData( m_regions, m_altZones, in );
}
std::sort( m_regions.begin(), m_regions.end(), []( const RegionData* lhs, const RegionData* rhs ) {
return lhs->key() < rhs->key();
} );
std::sort( m_zones.begin(), m_zones.end(), []( const TimeZoneData* lhs, const TimeZoneData* rhs ) {
if ( lhs->region() == rhs->region() )
{
return lhs->zone() < rhs->zone();
}
return lhs->region() < rhs->region();
} );
std::sort( m_regions.begin(),
m_regions.end(),
[]( const RegionData* lhs, const RegionData* rhs ) { return lhs->key() < rhs->key(); } );
std::sort( m_zones.begin(),
m_zones.end(),
[]( const TimeZoneData* lhs, const TimeZoneData* rhs )
{
if ( lhs->region() == rhs->region() )
{
return lhs->zone() < rhs->zone();
}
return lhs->region() < rhs->region();
} );
for ( auto* z : m_zones )
{
@@ -399,7 +402,8 @@ ZonesModel::find( double latitude, double longitude ) const
* either N/S or E/W equal to any other; this obviously
* falls apart at the poles.
*/
auto distance = [&]( const TimeZoneData* zone ) -> double {
auto distance = [ & ]( const TimeZoneData* zone ) -> double
{
// Latitude doesn't wrap around: there is nothing north of 90
double latitudeDifference = abs( zone->latitude() - latitude );
@@ -445,7 +449,8 @@ ZonesModel::Iterator::operator bool() const
return 0 <= m_index && m_index < m_p->m_zones.count();
}
const TimeZoneData* ZonesModel::Iterator::operator*() const
const TimeZoneData*
ZonesModel::Iterator::operator*() const
{
if ( *this )
{

View File

@@ -13,45 +13,88 @@
#include <memory>
struct TranslationSpecialCase
{
const char* id; // The Calamares ID for the translation
const char** regions;
QLocale::Language language;
QLocale::Script script;
QLocale::Country country;
const char* name; // Native name, if different from Qt
constexpr bool customLocale() const { return language != QLocale::Language::AnyLanguage; }
};
/** @brief Handle special cases of Calamares language names
*
* If a given @p localeName (e.g. en_US, or sr@latin) has special handling,
* returns a pair of pointers:
* - a pointer to a QLocale; this is the locale to use, or may be @c nullptr
* to indicate that the Qt locale derived from @p localeName is accepatable.
* - a pointer to a QString; this is the native language name to use, or may
* be @c nullptr to indicate that the Qt value is acceptable.
* If a given @p id (e.g. en_US, or sr@latin) has special handling,
* put an entry in this table. The QLocale constants are used when a
* particular @p id needs specific configuration, **if** @p language
* is not @c AnyLanguage. The @p name is used as a human-readable
* native name if the Qt name is not suitable.
*
* Returns a pair of nullptrs for non-special cases.
* Another form of lookup maps a @p language + a region-identifier
* to a @p id, running around Qt's neglect of `@region` variants.
*
* Examples:
* - `sr@latin` needs specific Qt Locale settnigs, but the name is OK
* - Chinese needs a specific name, but the Locale is OK
*/
static std::pair< QLocale*, QString* >
specialCase( const CalamaresUtils::Locale::Translation::Id& locale )
{
const QString localeName = locale.name;
if ( localeName == "sr@latin" )
{
static QLocale loc( QLocale::Language::Serbian, QLocale::Script::LatinScript, QLocale::Country::Serbia );
return { &loc, nullptr };
}
if ( localeName == "ca@valencia" )
{
static QString name = QStringLiteral( "Català (València)" );
return { nullptr, &name };
}
if ( localeName == "zh_CN" )
{
// Simplified Chinese, but drop the (China) from the name
static QString name = QStringLiteral( "简体中文" );
return { nullptr, &name };
}
if ( localeName == "zh_TW" )
{
// Traditional Chinese, but drop (Taiwan) from the name
static QString name = QStringLiteral( "繁體中文" );
return { nullptr, &name };
}
static const char* serbian_latin_regions[] = { "latin", "latn", nullptr };
static const char* catalan_regions[] = { "valencia", nullptr };
static constexpr const TranslationSpecialCase special_cases[] = {
{ "sr@latin",
serbian_latin_regions,
QLocale::Language::Serbian,
QLocale::Script::LatinScript,
QLocale::Country::Serbia,
nullptr },
// Valencian is a regional variant of Catalan
{ "ca@valencia",
catalan_regions,
QLocale::Language::Catalan,
QLocale::Script::AnyScript,
QLocale::Country::AnyCountry,
"Català (València)" },
// Simplified Chinese, but drop the (China) from the name
{ "zh_CN",
nullptr,
QLocale::Language::AnyLanguage,
QLocale::Script::AnyScript,
QLocale::Country::AnyCountry,
"简体中文" },
// Traditional Chinese, but drop (Taiwan) from the name
{ "zh_TW",
nullptr,
QLocale::Language::AnyLanguage,
QLocale::Script::AnyScript,
QLocale::Country::AnyCountry,
"繁體中文" },
{ "oc",
nullptr,
QLocale::Language::AnyLanguage,
QLocale::Script::AnyScript,
QLocale::Country::AnyCountry,
"Lenga d'òc" },
};
return { nullptr, nullptr };
static inline bool
lookup_region( const QByteArray& region, const char** regions_list )
{
if ( regions_list )
{
while ( *regions_list )
{
if ( region == *regions_list )
{
return true;
}
regions_list++;
}
}
return false;
}
static QString
@@ -59,25 +102,24 @@ specialCaseSystemLanguage()
{
const QByteArray lang_p = qgetenv( "LANG" );
if ( lang_p.isEmpty() )
return {};
QString lang = QString::fromLatin1( lang_p );
if ( lang.isEmpty() )
return {};
const QString serbian_latin = QStringLiteral( "sr@latin" );
const QString serbian_latin_variant = QStringLiteral( "sr@latn" );
if ( ( lang == serbian_latin ) || ( lang == serbian_latin_variant ) )
{
return serbian_latin;
// This will figure out the system language some other way
return {};
}
const QString valencian = QStringLiteral( "ca@valencia" );
if ( lang == valencian )
auto lang_parts = lang_p.split( '@' );
if ( lang_parts.size() != 2 )
{
return valencian;
return {};
}
return {};
QLocale locale( QString::fromLatin1( lang_p ) );
auto it
= std::find_if( std::cbegin( special_cases ),
std::cend( special_cases ),
[ language = locale.language(), region = lang_parts[ 1 ] ]( const TranslationSpecialCase& s )
{ return ( s.language == language ) && lookup_region( region, s.regions ); } );
return ( it != std::cend( special_cases ) ) ? QString::fromLatin1( it->id ) : QString();
}
namespace CalamaresUtils
@@ -95,11 +137,14 @@ Translation::Translation( const Id& localeId, LabelFormat format, QObject* paren
, m_locale( getLocale( localeId ) )
, m_localeId( localeId.name.isEmpty() ? m_locale.name() : localeId.name )
{
auto [ _, name ] = specialCase( localeId );
auto it = std::find_if( std::cbegin( special_cases ),
std::cend( special_cases ),
[ &localeId ]( const TranslationSpecialCase& s ) { return localeId.name == s.id; } );
const char* name = ( it != std::cend( special_cases ) ) ? it->name : nullptr;
QString longFormat = QObject::tr( "%1 (%2)" );
QString languageName = name ? *name : m_locale.nativeLanguageName();
QString languageName = name ? QString::fromUtf8( name ) : m_locale.nativeLanguageName();
QString englishName = m_locale.languageToString( m_locale.language() );
if ( languageName.isEmpty() )
@@ -125,8 +170,14 @@ Translation::getLocale( const Id& localeId )
return QLocale();
}
auto [ locale, _ ] = specialCase( localeId );
return locale ? *locale : QLocale( localeName );
auto it = std::find_if( std::cbegin( special_cases ),
std::cend( special_cases ),
[ &localeId ]( const TranslationSpecialCase& s ) { return localeId.name == s.id; } );
if ( it != std::cend( special_cases ) && it->customLocale() )
{
return QLocale( it->language, it->script, it->country );
}
return QLocale( localeName );
}
} // namespace Locale

View File

@@ -47,7 +47,7 @@ Presets::Presets( const QVariantMap& configurationMap, const QStringList& recogn
{
reserve( recognizedKeys.size() );
loadPresets(
*this, configurationMap, [&recognizedKeys]( const QString& s ) { return recognizedKeys.contains( s ); } );
*this, configurationMap, [ &recognizedKeys ]( const QString& s ) { return recognizedKeys.contains( s ); } );
}
bool

View File

@@ -63,9 +63,9 @@ RequirementsChecker::finished()
static QMutex finishedMutex;
QMutexLocker lock( &finishedMutex );
if ( m_progressTimer && std::all_of( m_watchers.cbegin(), m_watchers.cend(), []( const Watcher* w ) {
return w && w->isFinished();
} ) )
if ( m_progressTimer
&& std::all_of(
m_watchers.cbegin(), m_watchers.cend(), []( const Watcher* w ) { return w && w->isFinished(); } ) )
{
cDebug() << "All requirements have been checked.";
if ( m_progressTimer )
@@ -100,14 +100,17 @@ RequirementsChecker::reportProgress()
m_progressTimeouts++;
QStringList remainingNames;
auto remaining = std::count_if( m_watchers.cbegin(), m_watchers.cend(), [&]( const Watcher* w ) {
if ( w && !w->isFinished() )
{
remainingNames << w->objectName();
return true;
}
return false;
} );
auto remaining = std::count_if( m_watchers.cbegin(),
m_watchers.cend(),
[ & ]( const Watcher* w )
{
if ( w && !w->isFinished() )
{
remainingNames << w->objectName();
return true;
}
return false;
} );
if ( remaining > 0 )
{
cDebug() << "Remaining modules:" << remaining << Logger::DebugList( remainingNames );

View File

@@ -19,10 +19,10 @@ void
RequirementsModel::addRequirementsList( const Calamares::RequirementsList& requirements )
{
QMutexLocker l( &m_addLock );
emit beginResetModel();
beginResetModel();
m_requirements.append( requirements );
changeRequirementsList();
emit endResetModel();
endResetModel();
}
void

View File

@@ -140,7 +140,7 @@ PackagesTests::testAdd()
{
// This is the "original" instance, so it's missing extraEditor
auto op = action[ "install" ].toList();
QCOMPARE( op.length(), packages.length()-1 ); // changed from original length
QCOMPARE( op.length(), packages.length() - 1 ); // changed from original length
QVERIFY( !op.contains( extraEditor ) );
}
}

View File

@@ -102,9 +102,7 @@ KPMManager::KPMManager()
{
}
KPMManager::~KPMManager()
{
}
KPMManager::~KPMManager() {}
KPMManager::operator bool() const
{

View File

@@ -29,7 +29,8 @@ PartitionIterator::PartitionIterator( PartitionTable* table )
{
}
Partition* PartitionIterator::operator*() const
Partition*
PartitionIterator::operator*() const
{
return m_current;
}

View File

@@ -108,5 +108,5 @@ struct cScopedAssignment
};
template < typename T >
cScopedAssignment( T p )->cScopedAssignment< decltype( *p ) >;
cScopedAssignment( T p ) -> cScopedAssignment< decltype( *p ) >;
#endif

View File

@@ -116,7 +116,7 @@ private:
* immediately after setting up the connection. This allows
* setup and translation code to be mixed together.
*/
#define CALAMARES_RETRANSLATE( body ) CalamaresUtils::Retranslator::attach( this, [=] { body } )
#define CALAMARES_RETRANSLATE( body ) CalamaresUtils::Retranslator::attach( this, [ = ] { body } )
/** @brief Call code for the given object (widget) when language changes
*
* This is identical to CALAMARES_RETRANSLATE, except the @p body is called
@@ -126,7 +126,7 @@ private:
* immediately after setting up the connection. This allows
* setup and translation code to be mixed together.
*/
#define CALAMARES_RETRANSLATE_FOR( object, body ) CalamaresUtils::Retranslator::attach( object, [=] { body } )
#define CALAMARES_RETRANSLATE_FOR( object, body ) CalamaresUtils::Retranslator::attach( object, [ = ] { body } )
/** @brief Call a slot in this object when language changes
*
* Given a slot (in method-function-pointer notation), call that slot when the

View File

@@ -151,16 +151,19 @@ Calamares::Utils::Runner::run()
if ( m_output )
{
connect( &process, &QProcess::readyReadStandardOutput, [this, &process]() {
do
{
QString s = process.readLine();
if ( !s.isEmpty() )
{
Q_EMIT this->output( s );
}
} while ( process.canReadLine() );
} );
connect( &process,
&QProcess::readyReadStandardOutput,
[ this, &process ]()
{
do
{
QString s = process.readLine();
if ( !s.isEmpty() )
{
Q_EMIT this->output( s );
}
} while ( process.canReadLine() );
} );
}
cDebug() << Logger::SubEntry << "Running" << Logger::RedactedCommand( m_command );

View File

@@ -993,7 +993,7 @@ LibCalamaresTests::testRunnerOutput()
Calamares::Utils::Runner r( { "cat" } );
r.enableOutputProcessing().setInput( QStringLiteral( "hello\nworld\n\n!\n" ) );
QObject::connect( &r, &decltype( r )::output, [&collectedOutput]( QString s ) { collectedOutput << s; } );
QObject::connect( &r, &decltype( r )::output, [ &collectedOutput ]( QString s ) { collectedOutput << s; } );
{
auto result = r.run();

View File

@@ -97,12 +97,12 @@ PythonQtViewModule::loadSelf()
cala.addVariable( "configuration", m_configurationMap );
// Basic stdout/stderr handling
QObject::connect( PythonQt::self(), &PythonQt::pythonStdOut, []( const QString& message ) {
cDebug() << "PythonQt OUT>" << message;
} );
QObject::connect( PythonQt::self(), &PythonQt::pythonStdErr, []( const QString& message ) {
cDebug() << "PythonQt ERR>" << message;
} );
QObject::connect( PythonQt::self(),
&PythonQt::pythonStdOut,
[]( const QString& message ) { cDebug() << "PythonQt OUT>" << message; } );
QObject::connect( PythonQt::self(),
&PythonQt::pythonStdErr,
[]( const QString& message ) { cDebug() << "PythonQt ERR>" << message; } );
}
QDir workingDir( m_workingPath );

View File

@@ -135,14 +135,14 @@ addExpansions( QmlSearch method, QStringList& candidates, const QStringList& nam
std::transform( names.constBegin(),
names.constEnd(),
std::back_inserter( candidates ),
[&]( const QString& s ) { return s.isEmpty() ? QString() : bPath.arg( brandDir, s ); } );
[ & ]( const QString& s ) { return s.isEmpty() ? QString() : bPath.arg( brandDir, s ); } );
}
if ( ( method == QmlSearch::Both ) || ( method == QmlSearch::QrcOnly ) )
{
std::transform( names.constBegin(),
names.constEnd(),
std::back_inserter( candidates ),
[&]( const QString& s ) { return s.isEmpty() ? QString() : qrPath.arg( s ); } );
[ & ]( const QString& s ) { return s.isEmpty() ? QString() : qrPath.arg( s ); } );
}
}
@@ -222,22 +222,30 @@ registerQmlModels()
// Because branding and viewmanager have a parent (CalamaresApplication
// and CalamaresWindow), they will not be deleted by QmlEngine.
// https://doc.qt.io/qt-5/qtqml-cppintegration-data.html#data-ownership
qmlRegisterSingletonType< Calamares::Branding >(
"io.calamares.ui", 1, 0, "Branding", []( QQmlEngine*, QJSEngine* ) -> QObject* {
return Calamares::Branding::instance();
} );
qmlRegisterSingletonType< Calamares::ViewManager >(
"io.calamares.ui", 1, 0, "ViewManager", []( QQmlEngine*, QJSEngine* ) -> QObject* {
return Calamares::ViewManager::instance();
} );
qmlRegisterSingletonType< Calamares::Branding >( "io.calamares.ui",
1,
0,
"Branding",
[]( QQmlEngine*, QJSEngine* ) -> QObject*
{ return Calamares::Branding::instance(); } );
qmlRegisterSingletonType< Calamares::ViewManager >( "io.calamares.ui",
1,
0,
"ViewManager",
[]( QQmlEngine*, QJSEngine* ) -> QObject*
{ return Calamares::ViewManager::instance(); } );
qmlRegisterSingletonType< Calamares::GlobalStorage >(
"io.calamares.core", 1, 0, "Global", []( QQmlEngine*, QJSEngine* ) -> QObject* {
return Calamares::JobQueue::instance()->globalStorage();
} );
"io.calamares.core",
1,
0,
"Global",
[]( QQmlEngine*, QJSEngine* ) -> QObject* { return Calamares::JobQueue::instance()->globalStorage(); } );
qmlRegisterSingletonType< CalamaresUtils::Network::Manager >(
"io.calamares.core", 1, 0, "Network", []( QQmlEngine*, QJSEngine* ) -> QObject* {
return &CalamaresUtils::Network::Manager::instance();
} );
"io.calamares.core",
1,
0,
"Network",
[]( QQmlEngine*, QJSEngine* ) -> QObject* { return &CalamaresUtils::Network::Manager::instance(); } );
}
}

View File

@@ -896,6 +896,7 @@ class DMgreetd(DisplayManager):
def desktop_environment_setup(self, default_desktop_environment):
with open(self.environments_path(), 'w') as envs_file:
envs_file.write(default_desktop_environment.desktop_file)
envs_file.write("\n")
def greeter_setup(self):
pass

View File

@@ -31,16 +31,19 @@ FinishedPage::FinishedPage( Config* config, QWidget* parent )
ui->mainText->setWordWrap( true );
ui->mainText->setOpenExternalLinks( true );
connect( config, &Config::restartModeChanged, [this]( Config::RestartMode mode ) {
using Mode = Config::RestartMode;
connect( config,
&Config::restartModeChanged,
[ this ]( Config::RestartMode mode )
{
using Mode = Config::RestartMode;
ui->restartCheckBox->setVisible( mode != Mode::Never );
ui->restartCheckBox->setEnabled( mode != Mode::Always );
} );
ui->restartCheckBox->setVisible( mode != Mode::Never );
ui->restartCheckBox->setEnabled( mode != Mode::Always );
} );
connect( config, &Config::restartNowWantedChanged, ui->restartCheckBox, &QCheckBox::setChecked );
connect( ui->restartCheckBox, &QCheckBox::stateChanged, [config]( int state ) {
config->setRestartNowWanted( state != 0 );
} );
connect( ui->restartCheckBox,
&QCheckBox::stateChanged,
[ config ]( int state ) { config->setRestartNowWanted( state != 0 ); } );
CALAMARES_RETRANSLATE_SLOT( &FinishedPage::retranslate );
}

View File

@@ -162,13 +162,18 @@ class FstabGenerator(object):
crypttab_options = self.crypttab_options
# Set crypttab password for partition to none and remove crypttab options
# if crypto_keyfile.bin was not generated
if not os.path.exists(os.path.join(self.root_mount_point, "crypto_keyfile.bin")):
password = "none"
crypttab_options = ""
# on root partition when /boot is unencrypted
if partition["mountPoint"] == "/":
elif partition["mountPoint"] == "/":
if any([p["mountPoint"] == "/boot"
and "luksMapperName" not in p
for p in self.partitions]):
password = "none"
crypttab_options = ""
return dict(
name=mapper_name,

View File

@@ -156,18 +156,24 @@ Config::Config( QObject* parent )
m_setxkbmapTimer.setSingleShot( true );
// Connect signals and slots
connect( m_keyboardModelsModel, &KeyboardModelsModel::currentIndexChanged, [&]( int index ) {
// Set Xorg keyboard model
m_selectedModel = m_keyboardModelsModel->key( index );
QProcess::execute( "setxkbmap", xkbmap_model_args( m_selectedModel ) );
emit prettyStatusChanged();
} );
connect( m_keyboardModelsModel,
&KeyboardModelsModel::currentIndexChanged,
[ & ]( int index )
{
// Set Xorg keyboard model
m_selectedModel = m_keyboardModelsModel->key( index );
QProcess::execute( "setxkbmap", xkbmap_model_args( m_selectedModel ) );
emit prettyStatusChanged();
} );
connect( m_keyboardLayoutsModel, &KeyboardLayoutModel::currentIndexChanged, [&]( int index ) {
m_selectedLayout = m_keyboardLayoutsModel->item( index ).first;
updateVariants( QPersistentModelIndex( m_keyboardLayoutsModel->index( index ) ) );
emit prettyStatusChanged();
} );
connect( m_keyboardLayoutsModel,
&KeyboardLayoutModel::currentIndexChanged,
[ & ]( int index )
{
m_selectedLayout = m_keyboardLayoutsModel->item( index ).first;
updateVariants( QPersistentModelIndex( m_keyboardLayoutsModel->index( index ) ) );
emit prettyStatusChanged();
} );
connect( m_keyboardVariantsModel, &KeyboardVariantsModel::currentIndexChanged, this, &Config::xkbChanged );

View File

@@ -27,7 +27,8 @@ retranslateKeyboardModels()
{
s_kbtranslator = new QTranslator;
}
(void)CalamaresUtils::loadTranslator( CalamaresUtils::translatorLocaleName(), QStringLiteral( "kb_" ), s_kbtranslator );
(void)CalamaresUtils::loadTranslator(
CalamaresUtils::translatorLocaleName(), QStringLiteral( "kb_" ), s_kbtranslator );
}
@@ -220,9 +221,8 @@ KeyboardLayoutModel::init()
std::stable_sort( m_layouts.begin(),
m_layouts.end(),
[]( const QPair< QString, KeyboardGlobal::KeyboardInfo >& a,
const QPair< QString, KeyboardGlobal::KeyboardInfo >& b ) {
return a.second.description < b.second.description;
} );
const QPair< QString, KeyboardGlobal::KeyboardInfo >& b )
{ return a.second.description < b.second.description; } );
}
QHash< int, QByteArray >

View File

@@ -69,8 +69,9 @@ KeyboardPage::KeyboardPage( Config* config, QWidget* parent )
cDebug() << "Variants now total=" << model->rowCount() << "selected=" << model->currentIndex();
}
connect(
ui->buttonRestore, &QPushButton::clicked, [config = config] { config->keyboardModels()->setCurrentIndex(); } );
connect( ui->buttonRestore,
&QPushButton::clicked,
[ config = config ] { config->keyboardModels()->setCurrentIndex(); } );
connect( ui->physicalModelSelector,
QOverload< int >::of( &QComboBox::currentIndexChanged ),
@@ -83,21 +84,29 @@ KeyboardPage::KeyboardPage( Config* config, QWidget* parent )
connect( ui->layoutSelector->selectionModel(),
&QItemSelectionModel::currentChanged,
[this]( const QModelIndex& current ) { m_config->keyboardLayouts()->setCurrentIndex( current.row() ); } );
connect( config->keyboardLayouts(), &KeyboardLayoutModel::currentIndexChanged, [this]( int index ) {
ui->layoutSelector->setCurrentIndex( m_config->keyboardLayouts()->index( index ) );
m_keyboardPreview->setLayout( m_config->keyboardLayouts()->key( index ) );
m_keyboardPreview->setVariant(
m_config->keyboardVariants()->key( m_config->keyboardVariants()->currentIndex() ) );
} );
[ this ]( const QModelIndex& current )
{ m_config->keyboardLayouts()->setCurrentIndex( current.row() ); } );
connect( config->keyboardLayouts(),
&KeyboardLayoutModel::currentIndexChanged,
[ this ]( int index )
{
ui->layoutSelector->setCurrentIndex( m_config->keyboardLayouts()->index( index ) );
m_keyboardPreview->setLayout( m_config->keyboardLayouts()->key( index ) );
m_keyboardPreview->setVariant(
m_config->keyboardVariants()->key( m_config->keyboardVariants()->currentIndex() ) );
} );
connect( ui->variantSelector->selectionModel(),
&QItemSelectionModel::currentChanged,
[this]( const QModelIndex& current ) { m_config->keyboardVariants()->setCurrentIndex( current.row() ); } );
connect( config->keyboardVariants(), &KeyboardVariantsModel::currentIndexChanged, [this]( int index ) {
ui->variantSelector->setCurrentIndex( m_config->keyboardVariants()->index( index ) );
m_keyboardPreview->setVariant( m_config->keyboardVariants()->key( index ) );
} );
[ this ]( const QModelIndex& current )
{ m_config->keyboardVariants()->setCurrentIndex( current.row() ); } );
connect( config->keyboardVariants(),
&KeyboardVariantsModel::currentIndexChanged,
[ this ]( int index )
{
ui->variantSelector->setCurrentIndex( m_config->keyboardVariants()->index( index ) );
m_keyboardPreview->setVariant( m_config->keyboardVariants()->key( index ) );
} );
CALAMARES_RETRANSLATE_SLOT( &KeyboardPage::retranslate );
}

View File

@@ -118,15 +118,15 @@ loadLocales( const QString& localeGenPath )
// Assuming we have a list of supported locales, we usually only want UTF-8 ones
// because it's not 1995.
auto notUtf8 = []( const QString& s ) {
return !s.contains( "UTF-8", Qt::CaseInsensitive ) && !s.contains( "utf8", Qt::CaseInsensitive );
};
auto notUtf8 = []( const QString& s )
{ return !s.contains( "UTF-8", Qt::CaseInsensitive ) && !s.contains( "utf8", Qt::CaseInsensitive ); };
auto it = std::remove_if( localeGenLines.begin(), localeGenLines.end(), notUtf8 );
localeGenLines.erase( it, localeGenLines.end() );
// We strip " UTF-8" from "en_US.UTF-8 UTF-8" because it's redundant redundant.
// Also simplify whitespace.
auto unredundant = []( QString& s ) {
auto unredundant = []( QString& s )
{
if ( s.endsWith( " UTF-8" ) )
{
s.chop( 6 );
@@ -183,30 +183,36 @@ Config::Config( QObject* parent )
// we don't need to call an update-GS method, or introduce an intermediate
// update-thing-and-GS method. And everywhere where we **do** change
// language or location, we already emit the signal.
connect( this, &Config::currentLanguageCodeChanged, [&]() {
auto* gs = Calamares::JobQueue::instance()->globalStorage();
gs->insert( "locale", m_selectedLocaleConfiguration.toBcp47() );
} );
connect( this,
&Config::currentLanguageCodeChanged,
[ & ]()
{
auto* gs = Calamares::JobQueue::instance()->globalStorage();
gs->insert( "locale", m_selectedLocaleConfiguration.toBcp47() );
} );
connect( this, &Config::currentLCCodeChanged, [&]() {
updateGSLocale( Calamares::JobQueue::instance()->globalStorage(), localeConfiguration() );
} );
connect( this,
&Config::currentLCCodeChanged,
[ & ]() { updateGSLocale( Calamares::JobQueue::instance()->globalStorage(), localeConfiguration() ); } );
connect( this, &Config::currentLocationChanged, [&]() {
const bool locationChanged
= updateGSLocation( Calamares::JobQueue::instance()->globalStorage(), currentLocation() );
connect( this,
&Config::currentLocationChanged,
[ & ]()
{
const bool locationChanged
= updateGSLocation( Calamares::JobQueue::instance()->globalStorage(), currentLocation() );
if ( locationChanged && m_adjustLiveTimezone )
{
QProcess::execute( "timedatectl", // depends on systemd
{ "set-timezone", currentTimezoneCode() } );
}
if ( locationChanged && m_adjustLiveTimezone )
{
QProcess::execute( "timedatectl", // depends on systemd
{ "set-timezone", currentTimezoneCode() } );
}
emit currentTimezoneCodeChanged( currentTimezoneCode() );
emit currentTimezoneNameChanged( currentTimezoneName() );
} );
emit currentTimezoneCodeChanged( currentTimezoneCode() );
emit currentTimezoneNameChanged( currentTimezoneName() );
} );
auto prettyStatusNotify = [&]() { emit prettyStatusChanged( prettyStatus() ); };
auto prettyStatusNotify = [ & ]() { emit prettyStatusChanged( prettyStatus() ); };
connect( this, &Config::currentLanguageStatusChanged, prettyStatusNotify );
connect( this, &Config::currentLCStatusChanged, prettyStatusNotify );
connect( this, &Config::currentLocationStatusChanged, prettyStatusNotify );

View File

@@ -60,16 +60,19 @@ LCLocaleDialog::LCLocaleDialog( const QString& guessedLCLocale, const QStringLis
connect( dbb->button( QDialogButtonBox::Cancel ), &QPushButton::clicked, this, &QDialog::reject );
connect( m_localesWidget, &QListWidget::itemDoubleClicked, this, &QDialog::accept );
connect( m_localesWidget, &QListWidget::itemSelectionChanged, [this, dbb]() {
if ( m_localesWidget->selectedItems().isEmpty() )
{
dbb->button( QDialogButtonBox::Ok )->setEnabled( false );
}
else
{
dbb->button( QDialogButtonBox::Ok )->setEnabled( true );
}
} );
connect( m_localesWidget,
&QListWidget::itemSelectionChanged,
[ this, dbb ]()
{
if ( m_localesWidget->selectedItems().isEmpty() )
{
dbb->button( QDialogButtonBox::Ok )->setEnabled( false );
}
else
{
dbb->button( QDialogButtonBox::Ok )->setEnabled( true );
}
} );
if ( selected > -1 )
{

View File

@@ -140,9 +140,9 @@ TimeZoneWidget::paintEvent( QPaintEvent* )
// .. the lambda manages deprecations: the old one works in Qt 5.9 and Qt 5.10,
// while the new one avoids deprecation messages in Qt 5.13 and later.
#if QT_VERSION >= QT_VERSION_CHECK( 5, 11, 0 )
auto textwidth = [&]( const QString& s ) { return fontMetrics.horizontalAdvance( s ); };
auto textwidth = [ & ]( const QString& s ) { return fontMetrics.horizontalAdvance( s ); };
#else
auto textwidth = [&]( const QString& s ) { return fontMetrics.width( s ); };
auto textwidth = [ & ]( const QString& s ) { return fontMetrics.width( s ); };
#endif
const int textWidth = textwidth( m_currentLocation ? m_currentLocation->tr() : QString() );
const int textHeight = fontMetrics.height();
@@ -185,7 +185,8 @@ TimeZoneWidget::mousePressEvent( QMouseEvent* event )
int mX = event->pos().x();
int mY = event->pos().y();
auto distance = [&]( const CalamaresUtils::Locale::TimeZoneData* zone ) {
auto distance = [ & ]( const CalamaresUtils::Locale::TimeZoneData* zone )
{
QPoint locPos = TimeZoneImageList::getLocationPosition( zone->longitude(), zone->latitude() );
return double( abs( mX - locPos.x() ) + abs( mY - locPos.y() ) );
};

View File

@@ -1,6 +1,6 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2020 Anke Boersma <demm@kaosx.us>
* SPDX-FileCopyrightText: 2020 - 2022 Anke Boersma <demm@kaosx.us>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
@@ -112,7 +112,7 @@ Column {
Plugin {
id: mapPlugin
name: "esri" // "esri", "here", "itemsoverlay", "mapbox", "mapboxgl", "osm"
preferred: ["osm", "esri"] // "esri", "here", "itemsoverlay", "mapbox", "mapboxgl", "osm"
}
Map {
@@ -121,7 +121,7 @@ Column {
plugin: mapPlugin
activeMapType: supportedMapTypes[0]
//might be desirable to set zoom level configurable?
zoomLevel: 5
zoomLevel: 7
bearing: 0
tilt: 0
copyrightsVisible : true
@@ -167,12 +167,6 @@ Column {
anchors.fill: map
hoverEnabled: true
property var coordinate: map.toCoordinate(Qt.point(mouseX, mouseY))
Label {
x: parent.mouseX - width -5
y: parent.mouseY - height - 5
text: "%1, %2".arg(
parent.coordinate.latitude).arg(parent.coordinate.longitude)
}
onClicked: {
marker.coordinate = coordinate

View File

@@ -8,6 +8,7 @@ calamares_add_plugin( netinstall
EXPORT_MACRO PLUGINDLLEXPORT_PRO
SOURCES
Config.cpp
groupstreeview.cpp
LoaderQueue.cpp
NetInstallViewStep.cpp
NetInstallPage.cpp

View File

@@ -35,10 +35,13 @@ NetInstallPage::NetInstallPage( Config* c, QWidget* parent )
ui->groupswidget->header()->setSectionResizeMode( QHeaderView::ResizeToContents );
ui->groupswidget->setModel( c->model() );
connect( c, &Config::statusChanged, ui->netinst_status, &QLabel::setText );
connect( c, &Config::titleLabelChanged, [ui = this->ui]( const QString title ) {
ui->label->setVisible( !title.isEmpty() );
ui->label->setText( title );
} );
connect( c,
&Config::titleLabelChanged,
[ ui = this->ui ]( const QString title )
{
ui->label->setVisible( !title.isEmpty() );
ui->label->setText( title );
} );
connect( c, &Config::statusReady, this, &NetInstallPage::expandGroups );
}

View File

@@ -1,4 +1,5 @@
/*
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2016 Luca Giambonini <almack@chakraos.org>
* SPDX-FileCopyrightText: 2016 Lisa Vitolo <shainer@chakraos.org>
* SPDX-FileCopyrightText: 2017 Kyle Robbertze <krobbertze@gmail.com>

View File

@@ -1,4 +1,5 @@
/*
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2016 Luca Giambonini <almack@chakraos.org>
* SPDX-FileCopyrightText: 2016 Lisa Vitolo <shainer@chakraos.org>
* SPDX-FileCopyrightText: 2017 Kyle Robbertze <krobbertze@gmail.com>

View File

@@ -349,11 +349,11 @@ PackageModel::setupModelData( const QVariantList& groupList, PackageTreeItem* pa
void
PackageModel::setupModelData( const QVariantList& l )
{
Q_EMIT beginResetModel();
beginResetModel();
delete m_rootItem;
m_rootItem = new PackageTreeItem();
setupModelData( l, m_rootItem );
Q_EMIT endResetModel();
endResetModel();
}
void
@@ -361,7 +361,7 @@ PackageModel::appendModelData( const QVariantList& groupList )
{
if ( m_rootItem )
{
Q_EMIT beginResetModel();
beginResetModel();
const QStringList sources = collectSources( groupList );
@@ -386,6 +386,6 @@ PackageModel::appendModelData( const QVariantList& groupList )
// Add the new data to the model
setupModelData( groupList, m_rootItem );
Q_EMIT endResetModel();
endResetModel();
}
}

View File

@@ -1,4 +1,3 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2017 Kyle Robbertze <kyle@aims.ac.za>

View File

@@ -0,0 +1,31 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2022 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*/
#include "groupstreeview.h"
#include "utils/Logger.h"
#include <QPainter>
void
GroupsTreeView::drawBranches( QPainter* painter, const QRect& rect, const QModelIndex& index ) const
{
QTreeView::drawBranches( painter, rect, index );
// Empty names are handled specially: don't draw them as items,
// so the "branch" seems to just pass them by.
const QString s = index.data().toString();
if ( s.isEmpty() )
{
QStyleOptionViewItem opt = viewOptions();
opt.state = QStyle::State_Sibling;
opt.rect = QRect( !isRightToLeft() ? rect.left() : rect.right() + 1, rect.top(), indentation(), rect.height() );
painter->eraseRect( opt.rect );
style()->drawPrimitive( QStyle::PE_IndicatorBranch, &opt, painter, this );
}
}

View File

@@ -0,0 +1,18 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2022 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*/
#include <QTreeView>
class GroupsTreeView : public QTreeView
{
public:
using QTreeView::QTreeView;
protected:
virtual void drawBranches( QPainter* painter, const QRect& rect, const QModelIndex& index ) const override;
};

View File

@@ -36,13 +36,13 @@ SPDX-License-Identifier: GPL-3.0-or-later
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QTreeView" name="groupswidget">
<widget class="GroupsTreeView" name="groupswidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>981</width>
<height>407</height>
<height>410</height>
</rect>
</property>
<property name="font">
@@ -63,6 +63,13 @@ SPDX-License-Identifier: GPL-3.0-or-later
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>GroupsTreeView</class>
<extends>QTreeView</extends>
<header>groupstreeview.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@@ -56,9 +56,9 @@ PackageChooserViewStep::widget()
if ( !m_widget )
{
m_widget = new PackageChooserPage( m_config->mode(), nullptr );
connect( m_widget, &PackageChooserPage::selectionChanged, [=]() {
emit nextStatusChanged( this->isNextEnabled() );
} );
connect( m_widget,
&PackageChooserPage::selectionChanged,
[ = ]() { emit nextStatusChanged( this->isNextEnabled() ); } );
hookupModel();
}
return m_widget;

View File

@@ -251,7 +251,9 @@ fillGSConfigurationEFI( Calamares::GlobalStorage* gs, const QVariantMap& configu
gs->insert( "efiSystemPartitionSize", sizeString );
gs->insert( "efiSystemPartitionSize_i", part_size.toBytes() );
if ( part_size.toBytes() != PartUtils::efiFilesystemMinimumSize() )
// Assign long long int to long unsigned int to prevent compilation warning
size_t unsigned_part_size = part_size.toBytes();
if ( unsigned_part_size != PartUtils::efiFilesystemMinimumSize() )
{
cWarning() << "EFI partition size" << sizeString << "has been adjusted to"
<< PartUtils::efiFilesystemMinimumSize() << "bytes";

View File

@@ -20,8 +20,10 @@
#include <kpmcore/backend/corebackendmanager.h>
#include <kpmcore/core/device.h>
#include <kpmcore/core/partition.h>
#include <kpmcore/fs/filesystem.h>
#include <kpmcore/fs/filesystemfactory.h>
#include <kpmcore/fs/luks.h>
#include <kpmcore/util/externalcommand.h>
using CalamaresUtils::Partition::PartitionIterator;
@@ -127,6 +129,120 @@ clonePartition( Device* device, Partition* partition )
partition->activeFlags() );
}
#ifndef WITH_KPMCORE4API
// This function was added in KPMCore 4, implementation copied from src/fs/luks.cpp
/*
SPDX-FileCopyrightText: 2010 Volker Lanz <vl@fidra.de>
SPDX-FileCopyrightText: 2012-2019 Andrius Štikonas <andrius@stikonas.eu>
SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac <teo@kde.org>
SPDX-FileCopyrightText: 2016 Chantara Tith <tith.chantara@gmail.com>
SPDX-FileCopyrightText: 2017 Christian Morlok <christianmorlok@gmail.com>
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
SPDX-FileCopyrightText: 2020 Arnaud Ferraris <arnaud.ferraris@collabora.com>
SPDX-FileCopyrightText: 2020 Gaël PORTAY <gael.portay@collabora.com>
SPDX-License-Identifier: GPL-3.0-or-later
*/
static bool
testPassphrase( FS::luks* fs, const QString& deviceNode, const QString& passphrase )
{
ExternalCommand cmd( QStringLiteral( "cryptsetup" ),
{ QStringLiteral( "open" ),
QStringLiteral( "--tries" ),
QStringLiteral( "1" ),
QStringLiteral( "--test-passphrase" ),
deviceNode } );
if ( cmd.write( passphrase.toLocal8Bit() + '\n' ) && cmd.start( -1 ) && cmd.exitCode() == 0 )
{
return true;
}
return false;
}
#else
static bool
testPassphrase( FS::luks* fs, const QString& deviceNode, const QString& passphrase )
{
return fs->testPassphrase( deviceNode, passphrase );
}
#endif
// Adapted from luks cryptOpen which always opens a dialog to ask for a passphrase
int
updateLuksDevice( Partition* partition, const QString& passphrase )
{
const QString deviceNode = partition->partitionPath();
cDebug() << "Update Luks device: " << deviceNode;
if ( passphrase.isEmpty() )
{
cWarning() << Logger::SubEntry << "#1: Passphrase is empty";
return 1;
}
if ( partition->fileSystem().type() != FileSystem::Luks )
{
cWarning() << Logger::SubEntry << "#2: Not a luks encrypted device";
return 2;
}
// Cast partition fs to luks fs
FS::luks* luksFs = dynamic_cast< FS::luks* >( &partition->fileSystem() );
// Test the given passphrase
if ( !testPassphrase( luksFs, deviceNode, passphrase ) )
{
cWarning() << Logger::SubEntry << "#3: Passphrase incorrect";
return 3;
}
if ( luksFs->isCryptOpen() )
{
if ( !luksFs->mapperName().isEmpty() )
{
cWarning() << Logger::SubEntry << "#4: Device already decrypted";
return 4;
}
else
{
cDebug() << Logger::SubEntry << "No mapper node found";
luksFs->setCryptOpen( false );
}
}
ExternalCommand openCmd( QStringLiteral( "cryptsetup" ),
{ QStringLiteral( "open" ), deviceNode, luksFs->suggestedMapperName( deviceNode ) } );
if ( !( openCmd.write( passphrase.toLocal8Bit() + '\n' ) && openCmd.start( -1 ) && openCmd.exitCode() == 0 ) )
{
cWarning() << Logger::SubEntry << openCmd.exitCode() << ": cryptsetup command failed";
return openCmd.exitCode();
}
// Save the existing passphrase
luksFs->setPassphrase( passphrase );
luksFs->scan( deviceNode );
if ( luksFs->mapperName().isEmpty() )
{
cWarning() << Logger::SubEntry << "#5: No mapper node found";
return 5;
}
luksFs->loadInnerFileSystem( luksFs->mapperName() );
luksFs->setCryptOpen( luksFs->innerFS() != nullptr );
if ( !luksFs->isCryptOpen() )
{
cWarning() << Logger::SubEntry << "#6: Device could not be decrypted";
return 6;
}
return 0;
}
Calamares::JobResult
execute( Operation& operation, const QString& failureMessage )
{

View File

@@ -74,6 +74,8 @@ Partition* createNewEncryptedPartition( PartitionNode* parent,
Partition* clonePartition( Device* device, Partition* partition );
int updateLuksDevice( Partition* partition, const QString& passphrase );
/** @brief Return a result for an @p operation
*
* Executes the operation, and if successful, returns a success result.

View File

@@ -335,6 +335,8 @@ PartitionCoreModule::doInit()
{
scanForEfiSystemPartitions();
}
emit initCompleted();
}
PartitionCoreModule::~PartitionCoreModule()

View File

@@ -51,6 +51,9 @@ class QStandardItemModel;
class PartitionCoreModule : public QObject
{
Q_OBJECT
Q_PROPERTY( QAbstractListModel* deviceModel READ deviceModel CONSTANT FINAL )
Q_PROPERTY( QStandardItemModel* bootLoaderModel READ bootLoaderModel CONSTANT FINAL )
public:
/**
* This helper class calls refresh() on the module
@@ -239,6 +242,7 @@ Q_SIGNALS:
void isDirtyChanged( bool value );
void reverted();
void deviceReverted( Device* device );
void initCompleted();
private:
void refreshAfterModelChange();

View File

@@ -125,6 +125,8 @@ ChoicePage::ChoicePage( Config* config, QWidget* parent )
m_encryptWidget->hide();
m_reuseHomeCheckBox->hide();
gs->insert( "reuseHome", false );
updateNextEnabled();
}
@@ -457,7 +459,6 @@ ChoicePage::continueApplyDeviceChoice()
Q_EMIT deviceChosen();
}
void
ChoicePage::onActionChanged()
{
@@ -466,6 +467,20 @@ ChoicePage::onActionChanged()
{
applyActionChoice( m_config->installChoice() );
}
// Whole disk encryption isn't implemented for zfs so disable the option for now
if ( m_eraseFsTypesChoiceComboBox != nullptr && m_enableEncryptionWidget )
{
if ( m_eraseFsTypesChoiceComboBox->currentText() == "zfs" )
{
m_encryptWidget->hide();
}
else
{
m_encryptWidget->show();
}
}
updateNextEnabled();
}
void
@@ -1193,6 +1208,8 @@ ChoicePage::updateActionChoicePreview( InstallChoice choice )
m_beforePartitionBarsView->setSelectionMode( previewSelectionMode );
m_beforePartitionLabelsView->setSelectionMode( previewSelectionMode );
updateNextEnabled();
}
@@ -1598,35 +1615,27 @@ ChoicePage::isNextEnabled() const
bool
ChoicePage::calculateNextEnabled() const
{
bool enabled = false;
auto sm_p = m_beforePartitionBarsView ? m_beforePartitionBarsView->selectionModel() : nullptr;
switch ( m_config->installChoice() )
{
case InstallChoice::NoChoice:
cDebug() << "No partitioning choice";
cDebug() << "No partitioning choice has been made yet";
return false;
case InstallChoice::Replace:
case InstallChoice::Alongside:
if ( !( sm_p && sm_p->currentIndex().isValid() ) )
{
cDebug() << "No partition selected";
cDebug() << "No partition selected for alongside or replace";
return false;
}
enabled = true;
break;
case InstallChoice::Erase:
case InstallChoice::Manual:
enabled = true;
// Nothing to check for these
break;
}
if ( !enabled )
{
cDebug() << "No valid choice made";
return false;
}
if ( m_isEfi
&& ( m_config->installChoice() == InstallChoice::Alongside
|| m_config->installChoice() == InstallChoice::Replace ) )
@@ -1643,7 +1652,7 @@ ChoicePage::calculateNextEnabled() const
switch ( m_encryptWidget->state() )
{
case EncryptWidget::Encryption::Unconfirmed:
cDebug() << "No passphrase provided";
cDebug() << "No passphrase provided or passphrase mismatch.";
return false;
case EncryptWidget::Encryption::Disabled:
case EncryptWidget::Encryption::Confirmed:

View File

@@ -17,6 +17,7 @@
#include "ui_EditExistingPartitionDialog.h"
#include "core/ColorUtils.h"
#include "core/KPMHelpers.h"
#include "core/PartUtils.h"
#include "core/PartitionCoreModule.h"
#include "core/PartitionInfo.h"
@@ -28,13 +29,17 @@
#include "Settings.h"
#include "partition/FileSystem.h"
#include "utils/Logger.h"
#include "widgets/TranslationFix.h"
#include <kpmcore/core/device.h>
#include <kpmcore/core/partition.h>
#include <kpmcore/fs/filesystemfactory.h>
#include <kpmcore/fs/luks.h>
#include <QComboBox>
#include <QDir>
#include <QMessageBox>
#include <QProcess>
#include <QPushButton>
using CalamaresUtils::Partition::untranslatedFS;
@@ -52,6 +57,7 @@ EditExistingPartitionDialog::EditExistingPartitionDialog( Device* device,
, m_usedMountPoints( usedMountPoints )
{
m_ui->setupUi( this );
m_ui->encryptWidget->hide();
standardMountPoints( *( m_ui->mountPointComboBox ), PartitionInfo::mountPoint( partition ) );
QColor color = ColorUtils::colorForPartition( m_partition );
@@ -132,10 +138,8 @@ EditExistingPartitionDialog::EditExistingPartitionDialog( Device* device,
setFlagList( *( m_ui->m_listFlags ), m_partition->availableFlags(), PartitionInfo::flags( m_partition ) );
}
EditExistingPartitionDialog::~EditExistingPartitionDialog() {}
PartitionTable::Flags
EditExistingPartitionDialog::newFlags() const
{
@@ -242,8 +246,30 @@ EditExistingPartitionDialog::applyChanges( PartitionCoreModule* core )
{
core->setFilesystemLabel( m_device, m_partition, fsLabel );
}
core->refreshPartition( m_device, m_partition );
}
// Update the existing luks partition
const QString passphrase = m_ui->encryptWidget->passphrase();
if ( !passphrase.isEmpty() )
{
int retCode = KPMHelpers::updateLuksDevice( m_partition, passphrase );
if ( retCode != 0 )
{
QString message = tr( "Passphrase for existing partition" );
QString description = tr( "Partition %1 could not be decrypted "
"with the given passphrase."
"<br/><br/>"
"Edit the partition again and give the correct passphrase"
"or delete and create a new encrypted partition." )
.arg( m_partition->partitionPath() );
QMessageBox mb( QMessageBox::Information, message, description, QMessageBox::Ok, this->parentWidget() );
Calamares::fixButtonLabels( &mb );
mb.exec();
}
}
}
}
@@ -266,7 +292,6 @@ EditExistingPartitionDialog::replacePartResizerWidget()
m_partitionSizeController->setPartResizerWidget( widget, m_ui->formatRadioButton->isChecked() );
}
void
EditExistingPartitionDialog::updateMountPointPicker()
{
@@ -293,13 +318,47 @@ EditExistingPartitionDialog::updateMountPointPicker()
{
setSelectedMountPoint( m_ui->mountPointComboBox, QString() );
}
toggleEncryptWidget();
}
void
EditExistingPartitionDialog::checkMountPointSelection()
{
validateMountPoint( selectedMountPoint( m_ui->mountPointComboBox ),
m_usedMountPoints,
m_ui->mountPointExplanation,
m_ui->buttonBox->button( QDialogButtonBox::Ok ) );
if ( validateMountPoint( selectedMountPoint( m_ui->mountPointComboBox ),
m_usedMountPoints,
m_ui->mountPointExplanation,
m_ui->buttonBox->button( QDialogButtonBox::Ok ) ) )
{
toggleEncryptWidget();
}
}
void
EditExistingPartitionDialog::toggleEncryptWidget()
{
// Show/hide encryptWidget:
// check if partition is a previously luks formatted partition
// and not currently formatted
// and its mount point not a standard mount point except when it's /home
QString mp = selectedMountPoint( m_ui->mountPointComboBox );
if ( !mp.isEmpty() && m_partition->fileSystem().type() == FileSystem::Luks && !m_ui->formatRadioButton->isChecked()
&& ( !standardMountPoints().contains( mp ) || mp == "/home" ) )
{
m_ui->encryptWidget->show();
m_ui->encryptWidget->reset( false );
}
// TODO: When formatting a partition user must be able to encrypt that partition
// Probably need to delete this partition and create a new one
// else if ( m_ui->formatRadioButton->isChecked()
// && !mp.isEmpty())
// {
// m_ui->encryptWidget->show();
// m_ui->encryptWidget->reset();
// }
else
{
m_ui->encryptWidget->reset();
m_ui->encryptWidget->hide();
}
}

View File

@@ -32,6 +32,11 @@ class EditExistingPartitionDialog : public QDialog
{
Q_OBJECT
public:
struct FreeSpace
{
Partition* p;
};
EditExistingPartitionDialog( Device* device,
Partition* partition,
const QStringList& usedMountPoints,
@@ -53,6 +58,7 @@ private:
PartitionTable::Flags newFlags() const;
void replacePartResizerWidget();
void updateMountPointPicker();
void toggleEncryptWidget();
};
#endif /* EDITEXISTINGPARTITIONDIALOG_H */

View File

@@ -10,8 +10,8 @@ SPDX-License-Identifier: GPL-3.0-or-later
<rect>
<x>0</x>
<y>0</y>
<width>450</width>
<height>615</height>
<width>570</width>
<height>689</height>
</rect>
</property>
<property name="sizePolicy">
@@ -97,7 +97,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
</property>
</widget>
</item>
<item row="6" column="0">
<item row="8" column="0">
<widget class="QLabel" name="mountPointLabel">
<property name="text">
<string>&amp;Mount Point:</string>
@@ -107,7 +107,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
</property>
</widget>
</item>
<item row="6" column="1">
<item row="8" column="1">
<widget class="QComboBox" name="mountPointComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
@@ -153,14 +153,14 @@ SPDX-License-Identifier: GPL-3.0-or-later
<item row="5" column="1">
<widget class="QComboBox" name="fileSystemComboBox"/>
</item>
<item row="10" column="0">
<item row="15" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Flags:</string>
</property>
</widget>
</item>
<item row="10" column="1">
<item row="15" column="1">
<widget class="QListWidget" name="m_listFlags">
<property name="alternatingRowColors">
<bool>true</bool>
@@ -173,7 +173,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
</property>
</widget>
</item>
<item row="8" column="1">
<item row="13" column="1">
<widget class="QLineEdit" name="fileSystemLabelEdit">
<property name="toolTip">
<string>Label for the filesystem</string>
@@ -183,20 +183,39 @@ SPDX-License-Identifier: GPL-3.0-or-later
</property>
</widget>
</item>
<item row="8" column="0">
<item row="13" column="0">
<widget class="QLabel" name="fileSystemLabelLabel">
<property name="text">
<string>FS Label:</string>
</property>
</widget>
</item>
<item row="7" column="1">
<item row="10" column="1">
<widget class="QLabel" name="mountPointExplanation">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="EncryptWidget" name="encryptWidget" native="true"/>
</item>
<item row="12" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>13</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
@@ -218,6 +237,12 @@ SPDX-License-Identifier: GPL-3.0-or-later
<header location="global">kpmcore/gui/partresizerwidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>EncryptWidget</class>
<extends>QWidget</extends>
<header>gui/EncryptWidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>sizeSpinBox</tabstop>

View File

@@ -70,19 +70,41 @@ EncryptWidget::EncryptWidget( QWidget* parent )
void
EncryptWidget::reset()
EncryptWidget::reset( bool checkVisible )
{
m_ui->m_passphraseLineEdit->clear();
m_ui->m_confirmLineEdit->clear();
m_ui->m_encryptCheckBox->setChecked( false );
}
m_ui->m_encryptCheckBox->setVisible( checkVisible );
m_ui->m_passphraseLineEdit->setVisible( !checkVisible );
m_ui->m_confirmLineEdit->setVisible( !checkVisible );
}
EncryptWidget::Encryption
EncryptWidget::state() const
{
return m_state;
Encryption newState = Encryption::Unconfirmed;
if ( m_ui->m_encryptCheckBox->isChecked() || !m_ui->m_encryptCheckBox->isVisible() )
{
if ( !m_ui->m_passphraseLineEdit->text().isEmpty()
&& m_ui->m_passphraseLineEdit->text() == m_ui->m_confirmLineEdit->text() )
{
newState = Encryption::Confirmed;
}
else
{
newState = Encryption::Unconfirmed;
}
}
else
{
newState = Encryption::Disabled;
}
return newState;
}
@@ -145,23 +167,7 @@ EncryptWidget::updateState()
}
}
Encryption newState;
if ( m_ui->m_encryptCheckBox->isChecked() )
{
if ( !m_ui->m_passphraseLineEdit->text().isEmpty()
&& m_ui->m_passphraseLineEdit->text() == m_ui->m_confirmLineEdit->text() )
{
newState = Encryption::Confirmed;
}
else
{
newState = Encryption::Unconfirmed;
}
}
else
{
newState = Encryption::Disabled;
}
Encryption newState = state();
if ( newState != m_state )
{

View File

@@ -33,7 +33,7 @@ public:
explicit EncryptWidget( QWidget* parent = nullptr );
void reset();
void reset( bool checkVisible = true );
Encryption state() const;
void setText( const QString& text );

View File

@@ -0,0 +1,109 @@
# === This file is part of Calamares - <https://calamares.io> ===
#
# SPDX-FileCopyrightText: 2020 Adriaan de Groot <groot@kde.org>
# SPDX-FileCopyrightText: 2022 Aditya Mehra <aix.m@outlook.com>
# SPDX-License-Identifier: BSD-2-Clause
#
if( NOT WITH_QML )
calamares_skip_module( "partitionq (QML is not supported in this build)" )
return()
endif()
# When debugging the timezone widget, add this debugging definition
# to have a debugging-friendly timezone widget, debug logging,
# and no intrusive timezone-setting while clicking around.
option( DEBUG_PARTITION_UNSAFE "Allow unsafe partitioning choices." OFF )
option( DEBUG_PARTITION_BAIL_OUT "Unsafe partitioning will error out on exec." ON )
option( DEBUG_PARTITION_SKIP "Don't actually do any partitioning." OFF)
include_directories( ${CMAKE_SOURCE_DIR} ) # for KPMCoreHelper
# This is very chatty, useful mostly if you don't know what KPMCore offers.
option( DEBUG_FILESYSTEMS "Log all available Filesystems from KPMCore." OFF )
set( _partition_defs )
if( DEBUG_PARTITION_UNSAFE )
if( DEBUG_PARTITION_BAIL_OUT )
list( APPEND _partition_defs DEBUG_PARTITION_BAIL_OUT )
endif()
list( APPEND _partition_defs DEBUG_PARTITION_UNSAFE )
endif()
if ( DEBUG_FILESYSTEMS )
list( APPEND _partition_defs DEBUG_FILESYSTEMS )
endif()
if( DEBUG_PARTITION_SKIP )
list( APPEND _partition_defs DEBUG_PARTITION_SKIP )
endif()
find_package(ECM ${ECM_VERSION} REQUIRED NO_MODULE)
include( KPMcoreHelper )
find_package( KF5Config CONFIG )
find_package( KF5I18n CONFIG )
if ( KPMcore_FOUND AND Qt5DBus_FOUND AND KF5CoreAddons_FOUND AND KF5Config_FOUND )
list( APPEND _partition_defs ${KPMcore_API_DEFINITIONS} )
include_directories( ${KPMCORE_INCLUDE_DIR} )
include_directories( ${PROJECT_BINARY_DIR}/src/libcalamaresui )
# Because we're sharing sources with the regular partition module
set( _partition ${CMAKE_CURRENT_SOURCE_DIR}/../partition )
# set( _partitionCore ${CMAKE_CURRENT_SOURCE_DIR}/../partition/core )
# set( _partitionJobs ${CMAKE_CURRENT_SOURCE_DIR}/../partition/jobs )
include_directories( ${_partition} )
calamares_add_plugin( partitionq
TYPE viewmodule
EXPORT_MACRO PLUGINDLLEXPORT_PRO
SOURCES
PartitionQmlViewStep.cpp
ChoicePageQml.cpp
FlatPartitionModel.cpp
${_partition}/Config.cpp
${_partition}/core/PartUtils.cpp
${_partition}/core/DeviceModel.cpp
${_partition}/core/PartitionInfo.cpp
${_partition}/core/PartitionCoreModule.cpp
${_partition}/core/BootLoaderModel.cpp
${_partition}/core/ColorUtils.cpp
${_partition}/core/DeviceList.cpp
${_partition}/core/KPMHelpers.cpp
${_partition}/core/PartitionActions.cpp
${_partition}/core/PartitionLayout.cpp
${_partition}/core/PartitionModel.cpp
${_partition}/jobs/AutoMountManagementJob.cpp
${_partition}/jobs/ChangeFilesystemLabelJob.cpp
${_partition}/jobs/ClearMountsJob.cpp
${_partition}/jobs/ClearTempMountsJob.cpp
${_partition}/jobs/CreatePartitionJob.cpp
${_partition}/jobs/CreatePartitionTableJob.cpp
${_partition}/jobs/CreateVolumeGroupJob.cpp
${_partition}/jobs/DeactivateVolumeGroupJob.cpp
${_partition}/jobs/DeletePartitionJob.cpp
${_partition}/jobs/FillGlobalStorageJob.cpp
${_partition}/jobs/FormatPartitionJob.cpp
${_partition}/jobs/PartitionJob.cpp
${_partition}/jobs/RemoveVolumeGroupJob.cpp
${_partition}/jobs/ResizePartitionJob.cpp
${_partition}/jobs/ResizeVolumeGroupJob.cpp
${_partition}/jobs/SetPartitionFlagsJob.cpp
RESOURCES
partitionq.qrc
LINK_PRIVATE_LIBRARIES
kpmcore
KF5::CoreAddons
COMPILE_DEFINITIONS ${_partition_defs}
SHARED_LIB
)
else()
if ( NOT KPMcore_FOUND )
calamares_skip_module( "partition (missing suitable KPMcore)" )
else()
calamares_skip_module( "partition (missing dependencies for KPMcore)" )
endif()
endif()

View File

@@ -0,0 +1,987 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2014-2017 Teo Mrnjavac <teo@kde.org>
* SPDX-FileCopyrightText: 2017-2019 Adriaan de Groot <groot@kde.org>
* SPDX-FileCopyrightText: 2019 Collabora Ltd
* SPDX-FileCopyrightText: 2022 Aditya Mehra <aix.m@outlook.com>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*/
#include "ChoicePageQml.h"
#include "Config.h"
#include "FlatPartitionModel.h"
#include "core/BootLoaderModel.h"
#include "core/DeviceModel.h"
#include "core/KPMHelpers.h"
#include "core/OsproberEntry.h"
#include "core/PartUtils.h"
#include "core/PartitionActions.h"
#include "core/PartitionCoreModule.h"
#include "core/PartitionInfo.h"
#include "core/PartitionModel.h"
#include "Branding.h"
#include "GlobalStorage.h"
#include "JobQueue.h"
#include "partition/PartitionIterator.h"
#include "partition/PartitionQuery.h"
#include "utils/CalamaresUtilsGui.h"
#include "utils/Logger.h"
#include "utils/Retranslator.h"
#include "utils/Units.h"
#include <kpmcore/core/device.h>
#ifdef WITH_KPMCORE4API
#include <kpmcore/core/softwareraid.h>
#endif
#include <QFutureWatcher>
#include <QtConcurrent/QtConcurrent>
using CalamaresUtils::Partition::findPartitionByPath;
using CalamaresUtils::Partition::isPartitionFreeSpace;
using CalamaresUtils::Partition::PartitionIterator;
using InstallChoice = Config::InstallChoice;
using SwapChoice = Config::SwapChoice;
/**
* @brief ChoicePage::ChoicePage is the default constructor. Called on startup as part of
* the module loading code path.
* @param parent the QObject parent.
*/
ChoicePageQml::ChoicePageQml( Config* config, QObject* parent )
: QObject( parent )
, m_config( config )
, m_nextEnabled( false )
, m_core( nullptr )
, m_isEfi( false )
, m_enableEncryptionWidget( true )
, m_partitionModel( new PartitionModel( this ) )
, m_partitionListModel( nullptr )
{
auto gs = Calamares::JobQueue::instance()->globalStorage();
m_enableEncryptionWidget = gs->value( "enableLuksAutomatedPartitioning" ).toBool();
gs->insert( "reuseHome", false );
}
void
ChoicePageQml::init( PartitionCoreModule* core )
{
m_core = core;
m_isEfi = PartUtils::isEfiSystem();
ChoicePageQml::applyDeviceChoice();
}
void
ChoicePageQml::setDeviceIndex( int index )
{
m_deviceIndex = index;
ChoicePageQml::applyDeviceChoice();
}
/**
* @brief ChoicePage::selectedDevice queries the device picker (which may be a combo or
* a list view) to get a pointer to the currently selected Device.
* @return a Device pointer, valid in the current state of the PCM, or nullptr if
* something goes wrong.
*/
Device*
ChoicePageQml::selectedDevice()
{
Device* currentDevice = nullptr;
currentDevice
= m_core->deviceModel()->deviceForIndex( m_core->deviceModel()->index( m_deviceIndex ) );
return currentDevice;
}
void
ChoicePageQml::setInstallChoice(int choice){
if(choice == InstallChoiceType::EraseChoice){
m_config->setInstallChoice( InstallChoice::Erase );
} else if(choice == InstallChoiceType::ReplaceChoice){
m_config->setInstallChoice( InstallChoice::Replace );
} else if(choice == InstallChoiceType::AlongSideChoice){
m_config->setInstallChoice( InstallChoice::Alongside );
} else if(choice == InstallChoiceType::ManualChoice){
m_config->setInstallChoice( InstallChoice::Manual );
}
Device* currd = selectedDevice();
if ( currd )
{
applyActionChoice( m_config->installChoice() );
}
}
void
ChoicePageQml::setPartitionModelForDevice()
{
Device* currd = selectedDevice();
if ( !currd )
{
return;
}
OsproberEntryList osproberEntriesForCurrentDevice = getOsproberEntriesForDevice( currd );
m_partitionModel->init(currd, osproberEntriesForCurrentDevice);
}
PartitionModel*
ChoicePageQml::partitionModel() const
{
return m_partitionModel;
}
PartitionListModel*
ChoicePageQml::partitionListModel() const
{
return m_partitionListModel;
}
QVariantList
ChoicePageQml::getEraseSwapChoices() const
{
auto choices = m_config->swapChoices();
QVariantList qvChoices;
QVariantMap qvChoice;
// Check which choices are supported by the current device
for ( auto c : choices )
{
if ( c == SwapChoice::NoSwap )
{
qvChoice["label"] = tr( "No swap" );
qvChoice["value"] = c;
qvChoices.append( qvChoice );
}
if ( c == SwapChoice::ReuseSwap )
{
qvChoice["label"] = tr( "Reuse swap" );
qvChoice["value"] = c;
qvChoices.append( qvChoice );
}
if ( c == SwapChoice::SmallSwap )
{
qvChoice["label"] = tr( "Swap (no Hibernate)" );
qvChoice["value"] = c;
qvChoices.append( qvChoice );
}
if ( c == SwapChoice::FullSwap )
{
qvChoice["label"] = tr( "Swap (with Hibernate)" );
qvChoice["value"] = c;
qvChoices.append( qvChoice );
}
if ( c == SwapChoice::SwapFile )
{
qvChoice["label"] = tr( "Swap to file" );
qvChoice["value"] = c;
qvChoices.append( qvChoice );
}
}
// If no choices are supported, only offer the NoSwap and full swap choices
// As done in the partition config
if ( qvChoices.isEmpty() )
{
qvChoice["label"] = tr( "No swap" );
qvChoice["value"] = SwapChoice::NoSwap;
qvChoices.append( qvChoice );
qvChoice["label"] = tr( "Swap (with Hibernate)" );
qvChoice["value"] = SwapChoice::FullSwap;
qvChoices.append( qvChoice );
}
return qvChoices;
}
int
ChoicePageQml::getInitialSwapChoice() const
{
return m_config->initialSwapChoice();
}
void
ChoicePageQml::setSwapChoice(int selectedSwapChoice)
{
if ( selectedSwapChoice == SwapChoice::NoSwap ) {
m_config->setSwapChoice( SwapChoice::NoSwap );
} else if ( selectedSwapChoice == SwapChoice::ReuseSwap ) {
m_config->setSwapChoice( SwapChoice::ReuseSwap );
} else if ( selectedSwapChoice == SwapChoice::SmallSwap ) {
m_config->setSwapChoice( SwapChoice::SmallSwap );
} else if ( selectedSwapChoice == SwapChoice::FullSwap ) {
m_config->setSwapChoice( SwapChoice::FullSwap );
} else if ( selectedSwapChoice == SwapChoice::SwapFile ) {
m_config->setSwapChoice( SwapChoice::SwapFile );
}
onActionChanged();
}
bool
ChoicePageQml::encryptWidgetEnabled() const
{
return m_enableEncryptionWidget;
}
void
ChoicePageQml::setEncryptionSelected(bool enabled)
{
m_encryptionSelected = enabled;
if ( m_config->installChoice() == InstallChoice::Erase )
{
if (m_encryptionSelected)
{
applyActionChoice( m_config->installChoice() );
}
}
updateNextEnabled();
}
void
ChoicePageQml::setEncryptionPhrase(const QString& phrase)
{
m_encryptPassphrase = phrase;
}
/**
* @brief ChoicePage::applyDeviceChoice handler for the selected event of the device
* picker. Calls ChoicePage::selectedDevice() to get the current Device*, then
* updates the preview widget for the on-disk state (calls ChoicePage::
* updateDeviceStatePreview()) and finally sets up the available actions and their
* text by calling ChoicePage::setupActions().
*/
void
ChoicePageQml::applyDeviceChoice()
{
if ( !selectedDevice() )
{
return;
}
if ( m_core->isDirty() )
{
emit scanningDialogShow();
QFuture<void> future =
QtConcurrent::run(
[ = ]
{
QMutexLocker locker( &m_coreMutex );
m_core->revertAllDevices();
} );
// wait for the future to finish
future.waitForFinished();
emit scanningDialogHide();
continueApplyDeviceChoice();
}
else
{
continueApplyDeviceChoice();
}
}
void
ChoicePageQml::continueApplyDeviceChoice()
{
Device* currd = selectedDevice();
// The device should only be nullptr immediately after a PCM reset.
// applyDeviceChoice() will be called again momentarily as soon as we handle the
// PartitionCoreModule::reverted signal.
if ( !currd )
{
return;
}
// Preview setup done. Now we show/hide choices as needed.
setupActions();
cDebug() << "Previous device" << m_lastSelectedDeviceIndex << "new device" << m_deviceIndex;
if ( m_lastSelectedDeviceIndex != m_deviceIndex )
{
m_lastSelectedDeviceIndex = m_deviceIndex;
m_lastSelectedActionIndex = -1;
m_config->setInstallChoice( m_config->initialInstallChoice() );
}
Q_EMIT actionChosen();
Q_EMIT deviceChosen();
}
void ChoicePageQml::setSelectedPartitionForAction(QModelIndex index)
{
// map the index from partition list to partition model
QModelIndex mappedIndex = m_partitionListModel->mapToSource(index);
Partition* partition = m_partitionModel->partitionForIndex(mappedIndex);
}
void
ChoicePageQml::onActionChanged()
{
Device* currd = selectedDevice();
if ( currd )
{
applyActionChoice( m_config->installChoice() );
}
}
void
ChoicePageQml::applyActionChoice( InstallChoice choice )
{
cDebug() << "Prev" << m_lastSelectedActionIndex << "InstallChoice" << choice
<< Config::installChoiceNames().find( choice );
switch ( choice )
{
case InstallChoice::Erase:
{
auto gs = Calamares::JobQueue::instance()->globalStorage();
PartitionActions::Choices::AutoPartitionOptions options { gs->value( "defaultPartitionTableType" ).toString(),
m_config->eraseFsType(),
m_encryptPassphrase,
gs->value( "efiSystemPartition" ).toString(),
CalamaresUtils::GiBtoBytes(
gs->value( "requiredStorageGiB" ).toDouble() ),
m_config->swapChoice() };
if ( m_core->isDirty() )
{
emit scanningDialogShow();
QFuture<void> future = QtConcurrent::run(
[ = ]
{
QMutexLocker locker( &m_coreMutex );
m_core->revertDevice( selectedDevice() );
} );
// wait for the future to finish
future.waitForFinished();
updateNextEnabled();
PartitionActions::doAutopartition( m_core, selectedDevice(), options );
Q_EMIT deviceChosen();
emit scanningDialogHide();
}
else
{
PartitionActions::doAutopartition( m_core, selectedDevice(), options );
Q_EMIT deviceChosen();
}
}
break;
case InstallChoice::Replace:
if ( m_core->isDirty() )
{
emit scanningDialogShow();
QFuture<void> future =
QtConcurrent::run(
[ = ]
{
QMutexLocker locker( &m_coreMutex );
m_core->revertDevice( selectedDevice() );
} );
// wait for the future to finish
future.waitForFinished();
emit scanningDialogHide();
}
break;
case InstallChoice::Alongside:
if ( m_core->isDirty() )
{
emit scanningDialogShow();
QFuture<void> future = QtConcurrent::run(
[ = ]
{
QMutexLocker locker( &m_coreMutex );
m_core->revertDevice( selectedDevice() );
} );
// wait for the future to finish
future.waitForFinished();
updateNextEnabled();
emit scanningDialogHide();
}
break;
case InstallChoice::NoChoice:
case InstallChoice::Manual:
break;
}
updateNextEnabled();
}
void
ChoicePageQml::onLeave()
{
}
bool
ChoicePageQml::eraseButtonEnabled()
{
return m_eraseButtonEnabled;
}
void
ChoicePageQml::setEraseButtonEnabled( bool enabled )
{
m_eraseButtonEnabled = enabled;
emit eraseButtonEnabledChanged();
}
bool
ChoicePageQml::alongSideButtonEnabled()
{
return m_alongSideButtonEnabled;
}
void
ChoicePageQml::setAlongSideButtonEnabled( bool enabled )
{
m_alongSideButtonEnabled = enabled;
emit alongSideButtonEnabledChanged();
}
bool
ChoicePageQml::replaceButtonEnabled()
{
return m_replaceButtonEnabled;
}
void
ChoicePageQml::setReplaceButtonEnabled( bool enabled )
{
m_replaceButtonEnabled = enabled;
emit replaceButtonEnabledChanged();
}
bool
ChoicePageQml::manualButtonEnabled()
{
return m_somethingElseButtonEnabled;
}
void
ChoicePageQml::setManualButtonEnabled( bool enabled )
{
m_somethingElseButtonEnabled = enabled;
emit manualButtonEnabledChanged();
}
QString
ChoicePageQml::messageLabel() const
{
return m_messageLabel;
}
void
ChoicePageQml::setMessageLabel( QString messageLabel )
{
m_messageLabel = messageLabel;
emit messageLabelChanged();
}
QString
ChoicePageQml::eraseButtonLabel() const
{
return m_eraseButtonLabel;
}
void
ChoicePageQml::setEraseButtonLabel( QString eraseButtonLabel )
{
m_eraseButtonLabel = eraseButtonLabel;
emit eraseButtonLabelChanged();
}
QString
ChoicePageQml::alongSideButtonLabel() const
{
return m_alongSideButtonLabel;
}
void
ChoicePageQml::setAlongSideButtonLabel( QString alongSideButtonLabel )
{
m_alongSideButtonLabel = alongSideButtonLabel;
emit alongSideButtonLabelChanged();
}
QString
ChoicePageQml::replaceButtonLabel() const
{
return m_replaceButtonLabel;
}
void
ChoicePageQml::setReplaceButtonLabel( QString replaceButtonLabel )
{
m_replaceButtonLabel = replaceButtonLabel;
emit replaceButtonLabelChanged();
}
QString
ChoicePageQml::somethingElseButtonLabel() const
{
return m_somethingElseButtonLabel;
}
void
ChoicePageQml::setSomethingElseButtonLabel( QString somethingElseButtonLabel )
{
m_somethingElseButtonLabel = somethingElseButtonLabel;
emit somethingElseButtonLabelChanged();
}
void
ChoicePageQml::setupEfiSystemPartitionSelector()
{
Q_ASSERT( m_isEfi );
// Only the already existing ones:
QList< Partition* > efiSystemPartitions = m_core->efiSystemPartitions();
if ( efiSystemPartitions.count() == 0 ) //should never happen
{
emit setEFIMessageLabel( tr( "An EFI system partition cannot be found anywhere "
"on this system. Please go back and use manual "
"partitioning to set up %1." )
.arg( Calamares::Branding::instance()->shortProductName() ) );
updateNextEnabled();
}
else if ( efiSystemPartitions.count() == 1 ) //probably most usual situation
{
emit setEFIMessageLabel( tr( "The EFI system partition at %1 will be used for "
"starting %2." )
.arg( efiSystemPartitions.first()->partitionPath() )
.arg( Calamares::Branding::instance()->shortProductName() ) );
}
else
{
//m_efiComboBox->show();
emit setEFIMessageLabel( tr( "EFI system partition:" ) );
for ( int i = 0; i < efiSystemPartitions.count(); ++i )
{
Partition* efiPartition = efiSystemPartitions.at( i );
//m_efiComboBox->addItem( efiPartition->partitionPath(), i );
// We pick an ESP on the currently selected device, if possible
if ( efiPartition->devicePath() == selectedDevice()->deviceNode() && efiPartition->number() == 1 )
{
qDebug() << "ToDo: set it in qml";
//m_efiComboBox->setCurrentIndex( i );
}
}
}
}
static inline QDebug&
operator<<( QDebug& s, PartitionIterator& it )
{
s << ( ( *it ) ? ( *it )->deviceNode() : QString( "<null device>" ) );
return s;
}
QString
describePartitionTypes( const QStringList& types )
{
if ( types.empty() )
{
return QCoreApplication::translate(
ChoicePageQml::staticMetaObject.className(), "any", "any partition-table type" );
}
if ( types.size() == 1 )
{
return types.first();
}
if ( types.size() == 2 )
{
return QCoreApplication::translate(
ChoicePageQml::staticMetaObject.className(), "%1 or %2", "partition-table types" )
.arg( types.at( 0 ), types.at( 1 ) );
}
// More than two, rather unlikely
return types.join( ", " );
}
QString
ChoicePageQml::getCurrentDevicePartitionType() const
{
return m_currentDevicePartitionTypeName;
}
/**
* @brief ChoicePage::setupActions happens every time a new Device* is selected in the
* device picker. Sets up the text and visibility of the partitioning actions based
* on the currently selected Device*, bootloader and os-prober output.
*/
void
ChoicePageQml::setupActions()
{
Logger::Once o;
m_partitionListModel = new PartitionListModel(m_partitionModel, this);
emit partitionListModelInitialized();
Device* currentDevice = selectedDevice();
OsproberEntryList osproberEntriesForCurrentDevice = getOsproberEntriesForDevice( currentDevice );
cDebug() << o << "Setting up actions for" << currentDevice->deviceNode() << "with"
<< osproberEntriesForCurrentDevice.count() << "entries.";
if ( currentDevice->partitionTable() )
{
m_currentDevicePartitionType = currentDevice->partitionTable()->type();
m_currentDevicePartitionTypeName = currentDevice->partitionTable()->typeName();
}
else
{
m_currentDevicePartitionType = PartitionTable::unknownTableType;
m_currentDevicePartitionTypeName = currentDevice->partitionTable()->typeName();
}
if ( m_config->allowManualPartitioning() )
{
setManualButtonEnabled(true);
}
else
{
setManualButtonEnabled(false);
}
bool atLeastOneCanBeResized = false;
bool atLeastOneCanBeReplaced = false;
bool atLeastOneIsMounted = false; // Suppress 'erase' if so
bool isInactiveRAID = false;
bool matchTableType = false;
#ifdef WITH_KPMCORE4API
if ( currentDevice->type() == Device::Type::SoftwareRAID_Device
&& static_cast< SoftwareRAID* >( currentDevice )->status() == SoftwareRAID::Status::Inactive )
{
cDebug() << Logger::SubEntry << "part of an inactive RAID device";
isInactiveRAID = true;
}
#endif
PartitionTable::TableType tableType = PartitionTable::unknownTableType;
if ( currentDevice->partitionTable() )
{
tableType = currentDevice->partitionTable()->type();
matchTableType = m_config->acceptPartitionTableType( tableType );
}
for ( auto it = PartitionIterator::begin( currentDevice ); it != PartitionIterator::end( currentDevice ); ++it )
{
if ( PartUtils::canBeResized( *it, o ) )
{
cDebug() << Logger::SubEntry << "contains resizable" << it;
atLeastOneCanBeResized = true;
}
if ( PartUtils::canBeReplaced( *it, o ) )
{
cDebug() << Logger::SubEntry << "contains replaceable" << it;
atLeastOneCanBeReplaced = true;
}
if ( ( *it )->isMounted() )
{
atLeastOneIsMounted = true;
}
}
if ( osproberEntriesForCurrentDevice.count() == 0 )
{
CALAMARES_RETRANSLATE(
cDebug() << "Setting texts for 0 osprober entries";
setMessageLabel(tr( "This storage device does not seem to have an operating system on it. "
"What would you like to do?<br/>"
"You will be able to review and confirm your choices "
"before any change is made to the storage device." ));
setEraseButtonLabel(tr( "<strong>Erase disk</strong><br/>"
"This will <font color=\"red\">delete</font> all data "
"currently present on the selected storage device." ));
setAlongSideButtonLabel(tr( "<strong>Install alongside</strong><br/>"
"The installer will shrink a partition to make room for %1." )
.arg( Calamares::Branding::instance()->shortVersionedName() ));
setReplaceButtonLabel(tr( "<strong>Replace a partition</strong><br/>"
"Replaces a partition with %1." )
.arg( Calamares::Branding::instance()->shortVersionedName() ));
);
emit labelsUpdated();
setReplaceButtonEnabled(false);
setAlongSideButtonEnabled(false);
}
else if ( osproberEntriesForCurrentDevice.count() == 1 )
{
QString osName = osproberEntriesForCurrentDevice.first().prettyName;
if ( !osName.isEmpty() )
{
CALAMARES_RETRANSLATE (
cDebug() << "Setting texts for 1 non-empty osprober entry";
setMessageLabel(tr( "This storage device has %1 on it. "
"What would you like to do?<br/>"
"You will be able to review and confirm your choices "
"before any change is made to the storage device." )
.arg( osName ));
setAlongSideButtonLabel(tr( "<strong>Install alongside</strong><br/>"
"The installer will shrink a partition to make room for %1." )
.arg( Calamares::Branding::instance()->shortVersionedName() ));
setEraseButtonLabel(tr( "<strong>Erase disk</strong><br/>"
"This will <font color=\"red\">delete</font> all data "
"currently present on the selected storage device." ));
setReplaceButtonLabel(tr( "<strong>Replace a partition</strong><br/>"
"Replaces a partition with %1." )
.arg( Calamares::Branding::instance()->shortVersionedName() ));
);
emit labelsUpdated();
}
else
{
CALAMARES_RETRANSLATE(
cDebug() << "Setting texts for 1 empty osprober entry";
setMessageLabel(tr( "This storage device already has an operating system on it. "
"What would you like to do?<br/>"
"You will be able to review and confirm your choices "
"before any change is made to the storage device." ));
setAlongSideButtonLabel(tr( "<strong>Install alongside</strong><br/>"
"The installer will shrink a partition to make room for %1." )
.arg( Calamares::Branding::instance()->shortVersionedName() ));
setEraseButtonLabel(tr( "<strong>Erase disk</strong><br/>"
"This will <font color=\"red\">delete</font> all data "
"currently present on the selected storage device." ));
setReplaceButtonLabel(tr( "<strong>Replace a partition</strong><br/>"
"Replaces a partition with %1." )
.arg( Calamares::Branding::instance()->shortVersionedName() ));
);
emit labelsUpdated();
}
}
else
{
// osproberEntriesForCurrentDevice has at least 2 items.
CALAMARES_RETRANSLATE(
cDebug() << "Setting texts for >= 2 osprober entries";
setMessageLabel(tr( "This storage device has multiple operating systems on it. "
"What would you like to do?<br/>"
"You will be able to review and confirm your choices "
"before any change is made to the storage device." ));
setAlongSideButtonLabel(tr( "<strong>Install alongside</strong><br/>"
"The installer will shrink a partition to make room for %1." )
.arg( Calamares::Branding::instance()->shortVersionedName() ));
setEraseButtonLabel(tr( "<strong>Erase disk</strong><br/>"
"This will <font color=\"red\">delete</font> all data "
"currently present on the selected storage device." ));
setReplaceButtonLabel(tr( "<strong>Replace a partition</strong><br/>"
"Replaces a partition with %1." )
.arg( Calamares::Branding::instance()->shortVersionedName() ));
);
emit labelsUpdated();
}
#ifdef DEBUG_PARTITION_UNSAFE
#ifdef DEBUG_PARTITION_BAIL_OUT
// If things can't be broken, allow all the buttons
atLeastOneCanBeReplaced = true;
atLeastOneCanBeResized = true;
atLeastOneIsMounted = false;
isInactiveRAID = false;
#endif
#endif
if ( atLeastOneCanBeReplaced )
{
setReplaceButtonEnabled(true);
}
else
{
cDebug() << "No partitions available for replace-action.";
setReplaceButtonEnabled(false);
}
if ( atLeastOneCanBeResized )
{
setAlongSideButtonEnabled(true);
}
else
{
cDebug() << "No partitions available for resize-action.";
setAlongSideButtonEnabled(false);
}
if ( !atLeastOneIsMounted && !isInactiveRAID )
{
setEraseButtonEnabled(true);
}
else
{
cDebug() << "No partitions ("
<< "any-mounted?" << atLeastOneIsMounted << "is-raid?" << isInactiveRAID << ") for erase-action.";
setEraseButtonEnabled(false);
}
bool isEfi = PartUtils::isEfiSystem();
bool efiSystemPartitionFound = !m_core->efiSystemPartitions().isEmpty();
if ( isEfi && !efiSystemPartitionFound )
{
cWarning() << "System is EFI but there's no EFI system partition, "
"DISABLING alongside and replace features.";
setAlongSideButtonEnabled(false);
setReplaceButtonEnabled(false);
}
if ( tableType != PartitionTable::unknownTableType && !matchTableType )
{
setMessageLabel(tr( "This storage device already has an operating system on it, "
"but the partition table <strong>%1</strong> is different from the "
"needed <strong>%2</strong>.<br/>" )
.arg( PartitionTable::tableTypeToName( tableType ) )
.arg( describePartitionTypes( m_config->partitionTableTypes() ) ) );
cWarning() << "Partition table" << PartitionTable::tableTypeToName( tableType )
<< "does not match the requirement " << m_config->partitionTableTypes().join( ',' )
<< ", ENABLING erase feature and DISABLING alongside, replace and manual features.";
setEraseButtonEnabled(true);
setAlongSideButtonEnabled(false);
setReplaceButtonEnabled(false);
setManualButtonEnabled(false);
cDebug() << "Replace button suppressed because partition table type mismatch.";
}
if ( !m_somethingElseButtonEnabled && !m_alongSideButtonEnabled && !m_replaceButtonEnabled
&& !m_eraseButtonEnabled)
{
if ( atLeastOneIsMounted )
{
setMessageLabel( tr( "This storage device has one of its partitions <strong>mounted</strong>." ) );
}
else
{
setMessageLabel(
tr( "This storage device is a part of an <strong>inactive RAID</strong> device." ) );
}
cWarning() << "No buttons available"
<< "replaced?" << atLeastOneCanBeReplaced << "resized?" << atLeastOneCanBeResized
<< "erased? (not-mounted and not-raid)" << !atLeastOneIsMounted << "and" << !isInactiveRAID;
}
if ( m_somethingElseButtonEnabled )
{
setSomethingElseButtonLabel(tr( "<strong>Manual partitioning</strong><br/>"
"You can create or resize partitions yourself." ));
}
emit labelsUpdated();
// Set Partition Model Here
ChoicePageQml::setPartitionModelForDevice();
}
OsproberEntryList
ChoicePageQml::getOsproberEntriesForDevice( Device* device ) const
{
OsproberEntryList eList;
for ( const OsproberEntry& entry : m_core->osproberEntries() )
{
if ( entry.path.startsWith( device->deviceNode() ) )
{
eList.append( entry );
}
}
return eList;
}
bool
ChoicePageQml::isNextEnabled() const
{
return m_nextEnabled;
}
bool
ChoicePageQml::calculateNextEnabled() const
{
bool enabled = false;
switch ( m_config->installChoice() )
{
case InstallChoice::NoChoice:
cDebug() << "No partitioning choice";
return false;
case InstallChoice::Replace:
case InstallChoice::Alongside:
enabled = true;
break;
case InstallChoice::Erase:
case InstallChoice::Manual:
enabled = true;
}
if ( !enabled )
{
cDebug() << "No valid choice made";
return false;
}
if ( m_isEfi
&& ( m_config->installChoice() == InstallChoice::Alongside
|| m_config->installChoice() == InstallChoice::Replace ) )
{
if ( m_core->efiSystemPartitions().count() == 0 )
{
cDebug() << "No EFI partition for alongside or replace";
return false;
}
}
if ( m_config->installChoice() == InstallChoice::Manual)
{
return true;
}
return true;
}
void
ChoicePageQml::updateNextEnabled()
{
bool enabled = calculateNextEnabled();
if ( enabled != m_nextEnabled )
{
m_nextEnabled = enabled;
Q_EMIT nextStatusChanged( enabled );
}
}
int
ChoicePageQml::lastSelectedDeviceIndex()
{
return m_lastSelectedDeviceIndex;
}
void
ChoicePageQml::setLastSelectedDeviceIndex( int index )
{
m_lastSelectedDeviceIndex = index;
}

View File

@@ -0,0 +1,214 @@
/* === This file is part of Calamares - <https://calamares.io> ===
* SPDX-FileCopyrightText: 2014-2016 Teo Mrnjavac <teo@kde.org>
* SPDX-FileCopyrightText: 2014-2016 Teo Mrnjavac <teo@kde.org>
* SPDX-FileCopyrightText: 2018-2019 Adriaan de Groot <groot@kde.org>
* SPDX-FileCopyrightText: 2019 Collabora Ltd
* SPDX-FileCopyrightText: 2022 Aditya Mehra <aix.m@outlook.com>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*/
#ifndef CHOICEPAGEQML_H
#define CHOICEPAGEQML_H
#include <QMutex>
#include <QPointer>
#include <QSet>
#include "Config.h"
#include "core/OsproberEntry.h"
#include "FlatPartitionModel.h"
namespace Calamares
{
}
class Config;
class PartitionCoreModule;
class PartitionSplitterWidget;
class PartitionModel;
class Device;
using SwapChoiceSet = Config::SwapChoiceSet;
/**
* @brief The ChoicePage class is the first page of the partitioning interface.
* It offers a choice between partitioning operations and initiates all automated
* partitioning modes. For manual partitioning, see PartitionPage.
*/
class ChoicePageQml : public QObject
{
Q_OBJECT
Q_ENUMS(InstallChoiceType)
Q_PROPERTY( bool eraseButtonEnabled READ eraseButtonEnabled WRITE setEraseButtonEnabled NOTIFY eraseButtonEnabledChanged )
Q_PROPERTY( bool alongSideButtonEnabled READ alongSideButtonEnabled WRITE setAlongSideButtonEnabled NOTIFY alongSideButtonEnabledChanged )
Q_PROPERTY( bool replaceButtonEnabled READ replaceButtonEnabled WRITE setReplaceButtonEnabled NOTIFY replaceButtonEnabledChanged )
Q_PROPERTY( bool manualButtonEnabled READ manualButtonEnabled WRITE setManualButtonEnabled NOTIFY manualButtonEnabledChanged )
Q_PROPERTY( QString messageLabel READ messageLabel WRITE setMessageLabel NOTIFY messageLabelChanged )
Q_PROPERTY( QString eraseButtonLabel READ eraseButtonLabel WRITE setEraseButtonLabel NOTIFY eraseButtonLabelChanged )
Q_PROPERTY( QString alongSideButtonLabel READ alongSideButtonLabel WRITE setAlongSideButtonLabel NOTIFY alongSideButtonLabelChanged )
Q_PROPERTY( QString replaceButtonLabel READ replaceButtonLabel WRITE setReplaceButtonLabel NOTIFY replaceButtonLabelChanged )
Q_PROPERTY( QString somethingElseButtonLabel READ somethingElseButtonLabel WRITE setSomethingElseButtonLabel NOTIFY somethingElseButtonLabelChanged )
Q_PROPERTY( QAbstractItemModel* partitionModel READ partitionModel CONSTANT FINAL )
Q_PROPERTY( QAbstractListModel* partitionListModel READ partitionListModel CONSTANT FINAL )
public:
explicit ChoicePageQml( Config* config, QObject* parent = nullptr );
enum InstallChoiceType
{
EraseChoice,
AlongSideChoice,
ReplaceChoice,
ManualChoice
};
Q_ENUMS(InstallChoiceType)
/**
* @brief init runs when the PartitionViewStep and the PartitionCoreModule are
* ready. Sets up the rest of the UI based on os-prober output.
* @param core the PartitionCoreModule pointer.
*/
void init( PartitionCoreModule* core );
/**
* @brief isNextEnabled answers whether the current state of the page is such
* that progressing to the next page should be allowed.
* @return true if next is allowed, otherwise false.
*/
bool isNextEnabled() const;
/**
* @brief onLeave runs when control passes from this page to another one.
*/
void onLeave();
/**
* @brief applyActionChoice reacts to a choice of partitioning mode.
* @param choice the partitioning action choice.
*/
void applyActionChoice( Config::InstallChoice choice );
int lastSelectedDeviceIndex();
void setLastSelectedDeviceIndex( int index );
void onActionChanged();
bool eraseButtonEnabled();
bool alongSideButtonEnabled();
bool replaceButtonEnabled();
bool manualButtonEnabled();
void setEraseButtonEnabled( bool eraseButtonEnabled );
void setAlongSideButtonEnabled( bool alongSideButtonEnabled );
void setReplaceButtonEnabled( bool replaceButtonEnabled );
void setManualButtonEnabled( bool manualButtonEnabled );
QString messageLabel() const;
QString eraseButtonLabel() const;
QString alongSideButtonLabel() const;
QString replaceButtonLabel() const;
QString somethingElseButtonLabel() const;
void setMessageLabel( QString messageLabel );
void setEraseButtonLabel( QString eraseButtonLabel );
void setAlongSideButtonLabel( QString alongSideButtonLabel );
void setReplaceButtonLabel( QString replaceButtonLabel );
void setSomethingElseButtonLabel( QString somethingElseButtonLabel );
PartitionModel* partitionModel() const;
PartitionListModel* partitionListModel() const;
void setPartitionModelForDevice();
public Q_SLOTS:
void setDeviceIndex(int index);
void setupActions();
QString getCurrentDevicePartitionType() const;
void setInstallChoice(int installChoice);
QVariantList getEraseSwapChoices() const;
int getInitialSwapChoice() const;
void setSwapChoice(int selectedSwapChoice);
bool encryptWidgetEnabled() const;
void setEncryptionSelected(bool enabled);
void setEncryptionPhrase(const QString& phrase);
void setSelectedPartitionForAction(QModelIndex index);
Q_SIGNALS:
void partitionListModelInitialized();
void labelsUpdated();
void setEFIMessageLabel( const QString& message );
void scanningDialogShow();
void scanningDialogHide();
void eraseButtonEnabledChanged();
void alongSideButtonEnabledChanged();
void replaceButtonEnabledChanged();
void manualButtonEnabledChanged();
void messageLabelChanged();
void eraseButtonLabelChanged();
void alongSideButtonLabelChanged();
void replaceButtonLabelChanged();
void somethingElseButtonLabelChanged();
signals:
void nextStatusChanged( bool );
void actionChosen();
void deviceChosen();
private:
bool calculateNextEnabled() const;
void updateNextEnabled();
Device* selectedDevice();
void applyDeviceChoice(); // Start scanning new device
void continueApplyDeviceChoice(); // .. called after scan
OsproberEntryList getOsproberEntriesForDevice( Device* device ) const;
void setupEfiSystemPartitionSelector();
Config* m_config;
bool m_nextEnabled;
PartitionCoreModule* m_core;
PartitionModel* m_partitionModel;
PartitionListModel* m_partitionListModel;
QMutex m_previewsMutex;
bool m_isEfi;
int m_lastSelectedDeviceIndex = -1;
int m_lastSelectedActionIndex = -1;
bool m_enableEncryptionWidget;
bool m_encryptionSelected;
bool m_alongSideButtonEnabled;
bool m_eraseButtonEnabled;
bool m_replaceButtonEnabled;
bool m_somethingElseButtonEnabled;
int m_selectedDeviceIndex = -1;
int m_deviceIndex = -1;
QString m_messageLabel;
QString m_eraseButtonLabel;
QString m_alongSideButtonLabel;
QString m_replaceButtonLabel;
QString m_somethingElseButtonLabel;
QPointer< PartitionSplitterWidget > m_afterPartitionSplitterWidget;
QString m_currentDevicePartitionType;
QString m_currentDevicePartitionTypeName;
QString m_encryptPassphrase;
QMutex m_coreMutex;
};
#endif // CHOICEPAGEQML_H

View File

@@ -0,0 +1,310 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2022 Aditya Mehra <aix.m@outlook.com>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*/
import io.calamares.core 1.0
import io.calamares.ui 1.0
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Controls 1.4 as QQC1
import QtQuick.Window 2.14
import QtQuick.Layouts 1.3
import org.kde.kirigami 2.7 as Kirigami
Item {
width: partitionPage.width
height: partitionPage.height
function listProperty(item)
{
for (var p in item)
console.log(p + ": " + item[p]);
}
Connections {
target: choicePage
onPartitionListModelInitialized: {
// Need to wait for partition model to initialize
// followed by partitionListModel
// Requires further refactor to have partitionListModel ready
// when choicePage is loaded instead of waiting for choicePage
// to load partitionModel first.
partitionView.model = choicePage.partitionListModel
}
}
RowLayout {
id: headerRowLayout
anchors.top: parent.top
width: parent.width
height: Kirigami.Units.gridUnits * 2
Item {
id: partitionTypeBox
Layout.preferredWidth: Kirigami.Units.gridUnit * 5
Layout.fillHeight: true
Item {
id: partitionTypeIcon
anchors.left: parent.left
width: parent.width * 0.35
height: parent.height
Image {
anchors.centerIn: parent
width: Kirigami.Units.iconSizes.large
height: width
source: "images/partition-table.svg"
}
}
Label {
id: partitionTypeLabel
anchors.left: partitionTypeIcon.right
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
}
}
Kirigami.Separator {
Layout.fillHeight: true
Layout.preferredWidth: 1
}
Label {
text: "Select Storage Device:"
font.bold: true
Layout.fillHeight: true
verticalAlignment: Qt.AlignVCenter
horizontalAlignment: Qt.AlignLeft
}
ComboBox {
id: deviceComboBox
Layout.fillWidth: true
Layout.fillHeight: true
model: core.deviceModel
textRole: "display"
currentIndex: core.currentDeviceIndex
onCurrentIndexChanged: {
core.currentDeviceIndex = currentIndex
choicePage.setDeviceIndex(currentIndex)
}
Component.onCompleted: {
choicePage.setupActions()
}
}
Item {
Layout.preferredWidth: Kirigami.Units.gridUnit * 5
Layout.fillHeight: true
}
}
Kirigami.Separator {
id: headerBoxLine
anchors.top: headerRowLayout.bottom
width: parent.width
height: 1
}
Item {
anchors.top: headerBoxLine.bottom
anchors.bottom: bottomSelectionBoxLine.top
anchors.left: parent.left
anchors.right: parent.right
ColumnLayout {
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
spacing: Kirigami.Units.smallSpacing
ButtonGroup {
id: buttonGroup
}
RadioButton {
id: eraseBtn
objectName: "eraseBtn"
Layout.fillWidth: true
Layout.fillHeight: true
visible: choicePage.eraseButtonEnabled
enabled: choicePage.eraseButtonEnabled
ButtonGroup.group: buttonGroup
text: choicePage.eraseButtonLabel;
onClicked: {
choicePage.setInstallChoice(0)
}
}
RadioButton {
id: alongSideBtn
Layout.fillWidth: true
Layout.fillHeight: true
visible: choicePage.alongSideButtonEnabled
enabled: choicePage.alongSideButtonEnabled
ButtonGroup.group: buttonGroup
text: choicePage.alongSideButtonLabel;
onClicked: {
choicePage.setInstallChoice(1)
}
}
RadioButton {
id: replaceBtn
Layout.fillWidth: true
Layout.fillHeight: true
visible: choicePage.replaceButtonEnabled
enabled: choicePage.replaceButtonEnabled
ButtonGroup.group: buttonGroup
text: choicePage.replaceButtonLabel;
onClicked: {
choicePage.setInstallChoice(2)
}
}
RadioButton {
id: manualBtn
Layout.fillWidth: true
Layout.fillHeight: true
visible: choicePage.manualButtonEnabled
enabled: choicePage.manualButtonEnabled
ButtonGroup.group: buttonGroup
text: choicePage.somethingElseButtonLabel;
onClicked: {
choicePage.setInstallChoice(3)
}
}
RowLayout {
id: partitionViewLayout
Layout.fillWidth: true
Layout.preferredHeight: Kirigami.Units.gridUnits * 3
spacing: Kirigami.Units.smallSpacing
Repeater {
id: partitionView
delegate: Item {
id: partitionItem
Layout.preferredWidth: Kirigami.Units.gridUnit * 4
Layout.preferredHeight: Kirigami.Units.gridUnit * 3
ColumnLayout{
anchors.fill: parent
spacing: Kirigami.Units.smallSpacing
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: Kirigami.Units.gridUnit * 1.5
color: model.decoration
Label {
anchors.centerIn: parent
text: model.display
fontSizeMode: Text.Fit
font.pixelSize: parent.height * 0.25
minimumPixelSize: 8
color: Kirigami.Theme.textColor
}
MouseArea {
anchors.fill: parent
onClicked: {
listProperty(model)
}
}
}
Label {
Layout.fillWidth: true
Layout.fillHeight: true
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
fontSizeMode: Text.Fit
font.pixelSize: parent.height * 0.25
minimumPixelSize: 8
color: Kirigami.Theme.textColor
text: model.toolTip.replace(" ", "\n")
}
}
}
onCountChanged: {
partitionView.forceLayout()
}
}
}
// ToDo: Partitioning Tree View Before and After View
}
}
Kirigami.Separator {
id: bottomSelectionBoxLine
anchors.bottom: selectionBoxes.top
width: parent.width
height: 1
visible: selectionBoxes.visible
}
Item {
id: selectionBoxes
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
height: parent.height * 0.2
visible: eraseBtn.checked || replaceBtn.checked || alongSideBtn.checked
ColumnLayout {
id: selectionBoxesLayout
width: parent.width
height: parent.height
ComboBox {
id: eraseSwapComboBox
Layout.fillWidth: true
Layout.fillHeight: true
model: choicePage.getEraseSwapChoices()
textRole: "label"
currentIndex: choicePage.getInitialSwapChoice()
onCurrentIndexChanged: {
choicePage.setSwapChoice(currentIndex)
}
visible: eraseBtn.checked
}
RadioButton {
id: encryptPartitionButton
Layout.fillWidth: true
Layout.fillHeight: true
text: "Encrypt Partition"
onClicked: {
if (encryptPartitionButton.checked) {
choicePage.setEncryptionSelected(true)
}
}
}
TextField {
id: encryptionPasswordField
Layout.fillWidth: true
Layout.fillHeight: true
visible: encryptPartitionButton.checked
onTextChanged: {
choicePage.setEncryptionPhrase(text)
}
}
}
}
}

View File

@@ -0,0 +1,72 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2022 Aditya Mehra <aix.m@outlook.com>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*/
#include "FlatPartitionModel.h"
#include "core/PartitionModel.h"
PartitionListModel::PartitionListModel( PartitionModel* model, QObject* parent )
: QAbstractListModel( parent )
, m_model( model )
{
connect( m_model, &PartitionModel::rowsInserted, this, &PartitionListModel::rowsInserted );
connect( m_model, &PartitionModel::rowsRemoved, this, &PartitionListModel::rowsRemoved );
connect( m_model, &PartitionModel::dataChanged, this, &PartitionListModel::dataChanged );
}
int PartitionListModel::rowCount( const QModelIndex& parent ) const
{
return m_model->rowCount( parent );
}
QHash< int, QByteArray > PartitionListModel::roleNames() const
{
QHash< int, QByteArray > roles = m_model->roleNames();
roles.insert( Qt::UserRole + 1, "size" );
roles.insert( Qt::UserRole + 2, "partitionData" );
return roles;
}
QVariant PartitionListModel::data( const QModelIndex& index, int role ) const
{
// Convert the treeview index to a flat index
QModelIndex flatIndex = m_model->index( index.row(), 0, index.parent() );
QVariant data = m_model->data( flatIndex, role );
if ( role == PartitionModel::SizeRole )
{
data = m_model->data( flatIndex, PartitionModel::SizeRole );
}
if ( role == Qt::UserRole + 2 )
{
QVariantMap partitionData;
partitionData.insert( "IsFreeSpaceRole", m_model->data( flatIndex, PartitionModel::IsFreeSpaceRole ) );
partitionData.insert( "IsPartitionNewRole", m_model->data( flatIndex, PartitionModel::IsPartitionNewRole ) );
partitionData.insert( "FileSystemLabelRole", m_model->data( flatIndex, PartitionModel::FileSystemLabelRole ) );
partitionData.insert( "FileSystemTypeRole", m_model->data( flatIndex, PartitionModel::FileSystemTypeRole ) );
partitionData.insert( "PartitionPathRole", m_model->data( flatIndex, PartitionModel::PartitionPathRole ) );
partitionData.insert( "PartitionPtrRole", m_model->data( flatIndex, PartitionModel::PartitionPtrRole ) );
partitionData.insert( "OsproberNameRole", m_model->data( flatIndex, PartitionModel::OsproberNameRole ) );
partitionData.insert( "OsproberPathRole", m_model->data( flatIndex, PartitionModel::OsproberPathRole ) );
partitionData.insert( "OsproberCanBeResizedRole", m_model->data( flatIndex, PartitionModel::OsproberCanBeResizedRole ) );
partitionData.insert( "OsproberRawLineRole", m_model->data( flatIndex, PartitionModel::OsproberRawLineRole ) );
partitionData.insert( "OsproberHomePartitionPathRole", m_model->data( flatIndex, PartitionModel::OsproberHomePartitionPathRole ) );
data.setValue( partitionData );
}
return data;
}
QVariantMap PartitionListModel::get( int row ) const
{
return data( index( row, 0 ), Qt::DisplayRole ).toList().first().toMap();
}
QModelIndex PartitionListModel::mapToSource( const QModelIndex& index ) const
{
return m_model->index( index.row(), 0, index.parent() );
}

View File

@@ -0,0 +1,39 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2022 Aditya Mehra <aix.m@outlook.com>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*/
#ifndef FLATPARTITIONMODEL_H
#define FLATPARTITIONMODEL_H
#include <QAbstractListModel>
#include <QObject>
#include <QStringList>
class PartitionModel;
// Flatten the PartionModel.
// This is used by the QML frontend to display the partition table.
class PartitionListModel : public QAbstractListModel
{
Q_OBJECT
public:
explicit PartitionListModel( PartitionModel* model, QObject* parent = nullptr );
int rowCount( const QModelIndex& parent = QModelIndex() ) const override;
QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const override;
QHash< int, QByteArray > roleNames() const override;
Q_INVOKABLE QVariantMap get( int row ) const;
QModelIndex mapToSource( const QModelIndex& index ) const;
private:
PartitionModel* m_model;
};
#endif // FLATPARTITIONMODEL_H

View File

@@ -0,0 +1,120 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2022 Aditya Mehra <Aix.m@outlook.com>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*/
#include "PartitionQmlViewStep.h"
#include "Config.h"
#include "ChoicePageQml.h"
#include "GlobalStorage.h"
#include "JobQueue.h"
#include "core/PartUtils.h"
#include "core/PartitionCoreModule.h"
#include <QtConcurrent/QtConcurrent>
CALAMARES_PLUGIN_FACTORY_DEFINITION( PartitionQmlViewStepFactory, registerPlugin< PartitionQmlViewStep >(); )
PartitionQmlViewStep::PartitionQmlViewStep( QObject* parent )
: Calamares::QmlViewStep( parent )
, m_config( new Config( this ) )
, m_core( nullptr )
, m_choicePage( nullptr )
{
m_choicePage = new ChoicePageQml(m_config, this);
m_core = new PartitionCoreModule( this ); // Unusable before init is complete!
Calamares::QmlViewStep::setContextProperty( "core", m_core );
Calamares::QmlViewStep::setContextProperty( "choicePage", m_choicePage );
emit nextStatusChanged( true );
}
QString
PartitionQmlViewStep::prettyName() const
{
return tr( "Partition" );
}
bool
PartitionQmlViewStep::isNextEnabled() const
{
return true;
}
bool
PartitionQmlViewStep::isBackEnabled() const
{
return true;
}
bool
PartitionQmlViewStep::isAtBeginning() const
{
return true;
}
bool
PartitionQmlViewStep::isAtEnd() const
{
return true;
}
Calamares::JobList
PartitionQmlViewStep::jobs() const
{
return m_core->jobs( m_config );
}
void
PartitionQmlViewStep::onActivate()
{
m_choicePage->init( m_core );
}
void
PartitionQmlViewStep::onLeave()
{
}
QObject*
PartitionQmlViewStep::getConfig()
{
return m_config;
}
QObject* PartitionQmlViewStep::getCore()
{
return m_core;
}
void
PartitionQmlViewStep::setConfigurationMap( const QVariantMap& configurationMap )
{
m_config->setConfigurationMap( configurationMap );
Calamares::QmlViewStep::setConfigurationMap( configurationMap );
m_future = new QFutureWatcher< void >();
connect( m_future,
&QFutureWatcher< void >::finished,
this,
[ this ]
{
this->m_future->deleteLater();
this->m_future = nullptr;
} );
QFuture< void > future = QtConcurrent::run( this, &PartitionQmlViewStep::initPartitionCoreModule );
m_future->setFuture( future );
}
void
PartitionQmlViewStep::initPartitionCoreModule()
{
Q_ASSERT( m_core );
m_core->init();
}

View File

@@ -0,0 +1,60 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2022 Aditya Mehra <Aix.m@outlook.com>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*/
#ifndef PARTITIONQMLVIEWSTEP_H
#define PARTITIONQMLVIEWSTEP_H
#include "Config.h"
#include "DllMacro.h"
#include "utils/PluginFactory.h"
#include "viewpages/QmlViewStep.h"
#include "core/PartitionCoreModule.h"
#include "ChoicePageQml.h"
#include <QObject>
template < typename T >
class QFutureWatcher;
class PLUGINDLLEXPORT PartitionQmlViewStep : public Calamares::QmlViewStep
{
Q_OBJECT
public:
explicit PartitionQmlViewStep( QObject* parent = nullptr );
QString prettyName() const override;
bool isNextEnabled() const override;
bool isBackEnabled() const override;
bool isAtBeginning() const override;
bool isAtEnd() const override;
Calamares::JobList jobs() const override;
void onActivate() override;
void onLeave() override;
void setConfigurationMap( const QVariantMap& configurationMap ) override;
QObject* getConfig() override;
QObject* getCore();
private:
void initPartitionCoreModule();
Config* m_config;
PartitionCoreModule* m_core;
QFutureWatcher< void >* m_future;
ChoicePageQml* m_choicePage;
};
CALAMARES_PLUGIN_FACTORY_DECLARATION( PartitionQmlViewStepFactory )
#endif // PARTITIONQMLVIEWSTEP_H

View File

@@ -0,0 +1,112 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="22"
height="22"
id="svg3813"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="kr_diskusage.svg">
<defs
id="defs3815" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="32"
inkscape:cx="14.427263"
inkscape:cy="11.039521"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1920"
inkscape:window-height="1021"
inkscape:window-x="-4"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:showpageshadow="false">
<inkscape:grid
type="xygrid"
id="grid4109" />
<sodipodi:guide
position="2.0000072,19.999993"
orientation="18,0"
id="guide4115" />
<sodipodi:guide
position="2.0000072,1.9999929"
orientation="0,18"
id="guide4117" />
<sodipodi:guide
position="20.000007,1.9999929"
orientation="-18,0"
id="guide4119" />
<sodipodi:guide
position="20.000007,19.999993"
orientation="0,-18"
id="guide4121" />
<sodipodi:guide
position="3.0000072,18.999993"
orientation="16,0"
id="guide4123" />
<sodipodi:guide
position="3.0000072,2.9999929"
orientation="0,16"
id="guide4125" />
<sodipodi:guide
position="19.000007,2.9999929"
orientation="-16,0"
id="guide4127" />
<sodipodi:guide
position="19.000007,18.999993"
orientation="0,-16"
id="guide4129" />
</sodipodi:namedview>
<metadata
id="metadata3818">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Capa 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-378.85714,-540.07647)">
<path
inkscape:connector-curvature="0"
style="color:#000000;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 389.85714,543.07647 c -4.432,0 -8,3.568 -8,8 0,4.432 3.568,8 8,8 4.432,0 8,-3.568 8,-8 0,-4.432 -3.568,-8 -8,-8 z m 0,1 c 3.878,0 7,3.122 7,7 0,3.878 -3.122,7 -7,7 -3.878,0 -7,-3.122 -7,-7 0,-3.878 3.122,-7 7,-7 z"
id="rect4185" />
<path
inkscape:connector-curvature="0"
style="color:#000000;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 389.85714,547.07647 c -2.216,0 -4,1.784 -4,4 0,2.216 1.784,4 4,4 2.216,0 4,-1.784 4,-4 0,-2.216 -1.784,-4 -4,-4 z m 0,1 c 0.46399,0 0.89764,0.11233 1.28906,0.29883 0.18113,-0.1837 0.43139,-0.29883 0.71094,-0.29883 0.554,0 1,0.446 1,1 0,0.27955 -0.11513,0.52981 -0.29883,0.71094 0.18651,0.39142 0.29883,0.82507 0.29883,1.28906 0,1.662 -1.338,3 -3,3 -1.662,0 -3,-1.338 -3,-3 0,-1.662 1.338,-3 3,-3 z"
id="rect4225" />
<path
inkscape:connector-curvature="0"
style="color:#000000;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 391.85714,547.07647 c -1.108,0 -2,0.892 -2,2 0,1.108 0.892,2 2,2 1.108,0 2,-0.892 2,-2 0,-1.108 -0.892,-2 -2,-2 z m 0,1 c 0.554,0 1,0.446 1,1 0,0.554 -0.446,1 -1,1 -0.554,0 -1,-0.446 -1,-1 0,-0.554 0.446,-1 1,-1 z"
id="rect4230" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@@ -0,0 +1,4 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
# ToDo: use for qml module specific settings

View File

@@ -0,0 +1,46 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2022 Aditya Mehra <aix.m@outlook.com>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*/
import io.calamares.core 1.0
import io.calamares.ui 1.0
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Window 2.14
import QtQuick.Layouts 1.3
import org.kde.kirigami 2.7 as Kirigami
Page {
id: partitionPage
Connections {
target: core
onInitCompleted: {
console.log("Partition Core Module Init Completed")
busyIndicator.running = false
busyIndicator.visible = false
partitionViewLoader.source = "qrc:/ChoosePage.qml"
}
}
BusyIndicator {
id: busyIndicator
anchors.centerIn: parent
running: true
visible: true
width: parent.width / 2
height: parent.height / 2
}
Loader {
id: partitionViewLoader
anchors.fill: parent
}
}

View File

@@ -0,0 +1,7 @@
<RCC>
<qresource>
<file>partitionq.qml</file>
<file>ChoosePage.qml</file>
<file>images/partition-table.svg</file>
</qresource>
</RCC>

View File

@@ -96,7 +96,8 @@ PlasmaLnfPage::PlasmaLnfPage( Config* config, QWidget* parent )
connect( view->selectionModel(),
&QItemSelectionModel::selectionChanged,
[this]( const QItemSelection& selected, const QItemSelection& ) {
[ this ]( const QItemSelection& selected, const QItemSelection& )
{
auto i = selected.indexes();
if ( !i.isEmpty() )
{

View File

@@ -61,7 +61,7 @@ SummaryModel::rowCount( const QModelIndex& ) const
void
SummaryModel::setSummaryList( const Calamares::ViewStepList& steps, bool withWidgets )
{
Q_EMIT beginResetModel();
beginResetModel();
m_summary.clear();
for ( Calamares::ViewStep* step : steps )
@@ -76,7 +76,7 @@ SummaryModel::setSummaryList( const Calamares::ViewStepList& steps, bool withWid
m_summary << StepSummary { step->prettyName(), text, widget };
}
Q_EMIT endResetModel();
endResetModel();
}
Config::Config( QObject* parent )

View File

@@ -45,16 +45,22 @@ TrackingPage::TrackingPage( Config* config, QWidget* parent )
&QCheckBox::stateChanged, \
config->x##Tracking(), \
QOverload< bool >::of( &TrackingStyleConfig::setTracking ) ); \
connect( config->x##Tracking(), &TrackingStyleConfig::trackingChanged, this, [this, config]() { \
this->trackerChanged( config->x##Tracking(), this->ui->x##Group, this->ui->x##CheckBox ); \
} ); \
connect( ui->x##PolicyButton, &QAbstractButton::clicked, config, [config] { \
QString url( config->x##Tracking()->policy() ); \
if ( !url.isEmpty() ) \
{ \
QDesktopServices::openUrl( url ); \
} \
} ); \
connect( config->x##Tracking(), \
&TrackingStyleConfig::trackingChanged, \
this, \
[ this, config ]() \
{ this->trackerChanged( config->x##Tracking(), this->ui->x##Group, this->ui->x##CheckBox ); } ); \
connect( ui->x##PolicyButton, \
&QAbstractButton::clicked, \
config, \
[ config ] \
{ \
QString url( config->x##Tracking()->policy() ); \
if ( !url.isEmpty() ) \
{ \
QDesktopServices::openUrl( url ); \
} \
} ); \
} while ( false )
trackingSetup( install );
@@ -63,16 +69,19 @@ TrackingPage::TrackingPage( Config* config, QWidget* parent )
#undef trackingSetup
connect( config, &Config::generalPolicyChanged, [this]( const QString& url ) {
this->ui->generalPolicyLabel->setVisible( !url.isEmpty() );
} );
connect( ui->generalPolicyLabel, &QLabel::linkActivated, [config] {
QString url( config->generalPolicy() );
if ( !url.isEmpty() )
{
QDesktopServices::openUrl( url );
}
} );
connect( config,
&Config::generalPolicyChanged,
[ this ]( const QString& url ) { this->ui->generalPolicyLabel->setVisible( !url.isEmpty() ); } );
connect( ui->generalPolicyLabel,
&QLabel::linkActivated,
[ config ]
{
QString url( config->generalPolicy() );
if ( !url.isEmpty() )
{
QDesktopServices::openUrl( url );
}
} );
retranslate();
}

View File

@@ -49,7 +49,7 @@ DEFINE_CHECK_FUNC( minLength )
{
cDebug() << Logger::SubEntry << "minLength set to" << minLength;
checks.push_back( PasswordCheck( []() { return QCoreApplication::translate( "PWQ", "Password is too short" ); },
[minLength]( const QString& s ) { return s.length() >= minLength; },
[ minLength ]( const QString& s ) { return s.length() >= minLength; },
PasswordCheck::Weight( 10 ) ) );
}
}
@@ -65,7 +65,7 @@ DEFINE_CHECK_FUNC( maxLength )
{
cDebug() << Logger::SubEntry << "maxLength set to" << maxLength;
checks.push_back( PasswordCheck( []() { return QCoreApplication::translate( "PWQ", "Password is too long" ); },
[maxLength]( const QString& s ) { return s.length() <= maxLength; },
[ maxLength ]( const QString& s ) { return s.length() <= maxLength; },
PasswordCheck::Weight( 10 ) ) );
}
}
@@ -378,8 +378,9 @@ DEFINE_CHECK_FUNC( libpwquality )
/* Something actually added? */
if ( requirement_count )
{
checks.push_back( PasswordCheck( [settings]() { return settings->explanation(); },
[settings]( const QString& s ) {
checks.push_back( PasswordCheck( [ settings ]() { return settings->explanation(); },
[ settings ]( const QString& s )
{
int r = settings->check( s );
if ( r < 0 )
{

View File

@@ -78,6 +78,20 @@ updateGSAutoLogin( bool doAutoLogin, const QString& login )
}
}
static const QStringList&
alwaysForbiddenLoginNames()
{
static QStringList s { QStringLiteral( "root" ), QStringLiteral( "nobody" ) };
return s;
}
static const QStringList&
alwaysForbiddenHostNames()
{
static QStringList s { QStringLiteral( "localhost" ) };
return s;
}
const NamedEnumTable< HostNameAction >&
hostnameActionNames()
{
@@ -98,6 +112,8 @@ hostnameActionNames()
Config::Config( QObject* parent )
: Calamares::ModuleSystem::Config( parent )
, m_forbiddenHostNames( alwaysForbiddenHostNames() )
, m_forbiddenLoginNames( alwaysForbiddenLoginNames() )
{
emit readyChanged( m_isReady ); // false
@@ -201,10 +217,9 @@ Config::setLoginName( const QString& login )
}
const QStringList&
Config::forbiddenLoginNames()
Config::forbiddenLoginNames() const
{
static QStringList forbidden { "root" };
return forbidden;
return m_forbiddenLoginNames;
}
QString
@@ -220,13 +235,6 @@ Config::loginNameStatus() const
{
return tr( "Your username is too long." );
}
for ( const QString& badName : forbiddenLoginNames() )
{
if ( 0 == QString::compare( badName, m_loginName, Qt::CaseSensitive ) )
{
return tr( "'%1' is not allowed as username." ).arg( badName );
}
}
QRegExp validateFirstLetter( "^[a-z_]" );
if ( validateFirstLetter.indexIn( m_loginName ) != 0 )
@@ -238,6 +246,12 @@ Config::loginNameStatus() const
return tr( "Only lowercase letters, numbers, underscore and hyphen are allowed." );
}
// Although we've made the list lower-case, and the RE above forces lower-case, still pass the flag
if ( forbiddenLoginNames().contains( m_loginName, Qt::CaseInsensitive ) )
{
return tr( "'%1' is not allowed as username." ).arg( m_loginName );
}
return QString();
}
@@ -268,10 +282,9 @@ Config::setHostName( const QString& host )
}
const QStringList&
Config::forbiddenHostNames()
Config::forbiddenHostNames() const
{
static QStringList forbidden { "localhost" };
return forbidden;
return m_forbiddenHostNames;
}
QString
@@ -291,12 +304,11 @@ Config::hostnameStatus() const
{
return tr( "Your hostname is too long." );
}
for ( const QString& badName : forbiddenHostNames() )
// "LocalHost" is just as forbidden as "localhost"
if ( forbiddenHostNames().contains( m_hostname, Qt::CaseInsensitive ) )
{
if ( 0 == QString::compare( badName, m_hostname, Qt::CaseSensitive ) )
{
return tr( "'%1' is not allowed as hostname." ).arg( badName );
}
return tr( "'%1' is not allowed as hostname." ).arg( m_hostname );
}
if ( !HOSTNAME_RX.exactMatch( m_hostname ) )
@@ -881,16 +893,41 @@ copyLegacy( const QVariantMap& source, const QString& sourceKey, QVariantMap& ta
}
}
/** @brief Tidy up a list of names
*
* Remove duplicates, apply lowercase, sort.
*/
static void
tidy( QStringList& l )
{
std::for_each( l.begin(), l.end(), []( QString& s ) { s = s.toLower(); } );
l.sort();
l.removeDuplicates();
}
void
Config::setConfigurationMap( const QVariantMap& configurationMap )
{
QString shell( QLatin1String( "/bin/bash" ) ); // as if it's not set at all
if ( configurationMap.contains( "userShell" ) )
// Handle *user* key and subkeys and legacy settings
{
shell = CalamaresUtils::getString( configurationMap, "userShell" );
bool ok = false; // Ignored
QVariantMap userSettings = CalamaresUtils::getSubMap( configurationMap, "user", ok );
// TODO:3.3: Remove calls to copyLegacy
copyLegacy( configurationMap, "userShell", userSettings, "shell" );
QString shell( QLatin1String( "/bin/bash" ) ); // as if it's not set at all
if ( userSettings.contains( "shell" ) )
{
shell = CalamaresUtils::getString( userSettings, "shell" );
}
// Now it might be explicitly set to empty, which is ok
setUserShell( shell );
m_forbiddenLoginNames = CalamaresUtils::getStringList( userSettings, "forbidden_names" );
m_forbiddenLoginNames << alwaysForbiddenLoginNames();
tidy( m_forbiddenLoginNames );
}
// Now it might be explicitly set to empty, which is ok
setUserShell( shell );
setAutoLoginGroup( either< QString, const QString& >(
CalamaresUtils::getString, configurationMap, "autologinGroup", "autoLoginGroup", QString() ) );
@@ -911,6 +948,10 @@ Config::setConfigurationMap( const QVariantMap& configurationMap )
m_writeEtcHosts = CalamaresUtils::getBool( hostnameSettings, "writeHostsFile", true );
m_hostnameTemplate
= CalamaresUtils::getString( hostnameSettings, "template", QStringLiteral( "${first}-${product}" ) );
m_forbiddenHostNames = CalamaresUtils::getStringList( hostnameSettings, "forbidden_names" );
m_forbiddenHostNames << alwaysForbiddenHostNames();
tidy( m_forbiddenHostNames );
}
setConfigurationDefaultGroups( configurationMap, m_defaultGroups );

View File

@@ -252,8 +252,8 @@ public:
bool isReady() const;
static const QStringList& forbiddenLoginNames();
static const QStringList& forbiddenHostNames();
const QStringList& forbiddenLoginNames() const;
const QStringList& forbiddenHostNames() const;
public Q_SLOTS:
/** @brief Sets the user's shell if possible
@@ -347,6 +347,9 @@ private:
bool m_writeEtcHosts = false;
QString m_hostnameTemplate;
QStringList m_forbiddenHostNames;
QStringList m_forbiddenLoginNames;
PasswordCheckList m_passwordChecks;
};

View File

@@ -53,6 +53,9 @@ private Q_SLOTS:
void testAutoLogin_data();
void testAutoLogin();
void testUserYAML_data();
void testUserYAML();
};
UserTests::UserTests() {}
@@ -117,6 +120,11 @@ UserTests::testGetSet()
QVERIFY( c.loginNameStatus().isEmpty() ); // now it's still ok
QCOMPARE( c.loginName(), lg );
QCOMPARE( c.fullName(), ful );
}
// Test forbidden login names
{
QVERIFY( c.forbiddenLoginNames().contains( QStringLiteral( "root" ) ) );
QVERIFY( c.loginNameStatus().isEmpty() ); // it's ok now
c.setLoginName( "root" );
QVERIFY( !c.loginNameStatus().isEmpty() ); // can't be root
}
@@ -298,7 +306,8 @@ UserTests::testHostSuggestions_data()
QTest::newRow( "full " ) << QStringLiteral( "${name}" ) << QStringLiteral( "chuckyeager" );
QTest::newRow( "login+ " ) << QStringLiteral( "${login}-${first}" ) << QStringLiteral( "bill-chuck" );
// This is a bit dodgy: assumes CPU architecture of the testing host
QTest::newRow( " cpu " ) << QStringLiteral( "${cpu}X" ) << QStringLiteral( "x8664X" ); // Assume we don't test on non-amd64
QTest::newRow( " cpu " ) << QStringLiteral( "${cpu}X" )
<< QStringLiteral( "x8664X" ); // Assume we don't test on non-amd64
// These have X X in the template to indicate that they are bogus. Mostly we want
// to see what the template engine does for these.
QTest::newRow( "@prod " ) << QStringLiteral( "X${product}X" ) << QString();
@@ -315,10 +324,11 @@ UserTests::testHostSuggestions()
QFETCH( QString, templateString );
QFETCH( QString, result );
if ( templateString.startsWith('X') && templateString.endsWith('X'))
if ( templateString.startsWith( 'X' ) && templateString.endsWith( 'X' ) )
{
QEXPECT_FAIL( "", "Test is too host-specific", Continue );
cWarning() << Logger::SubEntry << "Next test" << templateString << "->" << makeHostnameSuggestion( templateString, fullName, login );
cWarning() << Logger::SubEntry << "Next test" << templateString << "->"
<< makeHostnameSuggestion( templateString, fullName, login );
}
QCOMPARE( makeHostnameSuggestion( templateString, fullName, login ), result );
}
@@ -453,6 +463,58 @@ UserTests::testAutoLogin()
QCOMPARE( c.autoLoginGroup(), autoLoginGroupName );
}
void
UserTests::testUserYAML_data()
{
QTest::addColumn< QString >( "filename" );
QTest::addColumn< QString >( "shell" );
QTest::newRow( "old, unset " ) << "tests/7ao-shell.conf"
<< "/bin/bash";
QTest::newRow( "old, empty " ) << "tests/7bo-shell.conf"
<< "";
QTest::newRow( "old, relative" ) << "tests/7co-shell.conf"
<< "/bin/ls"; // Setting is ignored
QTest::newRow( "old, invalid " ) << "tests/7do-shell.conf"
<< "";
QTest::newRow( "old, absolute" ) << "tests/7eo-shell.conf"
<< "/usr/bin/dash";
QTest::newRow( "new, unset " ) << "tests/7an-shell.conf"
<< "/bin/bash";
QTest::newRow( "new, empty " ) << "tests/7bn-shell.conf"
<< "";
QTest::newRow( "new, relative" ) << "tests/7cn-shell.conf"
<< "/bin/ls"; // Setting is ignored
QTest::newRow( "new, invalid " ) << "tests/7dn-shell.conf"
<< "";
QTest::newRow( "new, absolute" ) << "tests/7en-shell.conf"
<< "/usr/bin/dash";
}
void
UserTests::testUserYAML()
{
Config c;
c.setUserShell( QStringLiteral( "/bin/ls" ) );
QFETCH( QString, filename );
QFETCH( QString, shell );
// BUILD_AS_TEST is the source-directory path
QFile fi( QString( "%1/%2" ).arg( BUILD_AS_TEST, filename ) );
QVERIFY( fi.exists() );
bool ok = false;
const auto map = CalamaresUtils::loadYaml( fi, &ok );
QVERIFY( ok );
QVERIFY( map.count() > 0 );
QCOMPARE( c.userShell(), QStringLiteral( "/bin/ls" ) );
c.setConfigurationMap( map );
QCOMPARE( c.userShell(), shell );
}
QTEST_GUILESS_MAIN( UserTests )

View File

@@ -0,0 +1,8 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
#
---
# Unset (bogus needed to keep it valid YAML)
user:
# shell: /usr/bin/dash
bogus: true

View File

@@ -0,0 +1,7 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
#
---
# Unset (bogus needed to keep it valid YAML)
# userShell: /usr/bin/dash
bogus: true

View File

@@ -0,0 +1,8 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
#
---
# Explicitly empty
user:
shell: ""

View File

@@ -0,0 +1,7 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
#
---
# Explicitly empty
userShell: ""

View File

@@ -0,0 +1,8 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
#
---
# Non-absolute path is ignored
user:
shell: dash

View File

@@ -0,0 +1,7 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
#
---
# Non-absolute path is ignored
userShell: dash

View File

@@ -0,0 +1,8 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
#
---
# Invalid setting (should be string), won't pass validation
user:
shell: [1]

View File

@@ -0,0 +1,7 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
#
---
# Invalid setting (should be string), won't pass validation
userShell: [1]

View File

@@ -0,0 +1,8 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
#
---
# Explicitly set with full path
user:
shell: /usr/bin/dash

View File

@@ -0,0 +1,7 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
#
---
# Explicitly set with full path
userShell: /usr/bin/dash

View File

@@ -0,0 +1,10 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
#
---
# Explicitly set with full path
user:
shell: /usr/bin/new
bogus: true
userShell: /usr/bin/old

View File

@@ -0,0 +1,10 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
#
---
# Explicitly set with full path
user:
shell: /usr/bin/new
bogus: true
# userShell: /usr/bin/old

View File

@@ -0,0 +1,10 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
#
---
# Explicitly set with full path
user:
# shell: /usr/bin/new
bogus: true
userShell: /usr/bin/old

View File

@@ -140,13 +140,30 @@ allowWeakPasswords: false
# to be unchecked.
allowWeakPasswordsDefault: false
# Shell to be used for the regular user of the target system.
# There are three possible kinds of settings:
# - unset (i.e. commented out, the default), act as if set to /bin/bash
# - empty (explicit), don't pass shell information to useradd at all
# and rely on a correct configuration file in /etc/default/useradd
# - set, non-empty, use that path as shell. No validation is done
# that the shell actually exists or is executable.
# User settings
#
# The user can enter a username, but there are some other
# hidden settings for the user which are configurable in Calamares.
#
# Key *user* has the following sub-keys:
#
# - *shell* Shell to be used for the regular user of the target system.
# There are three possible kinds of settings:
# - unset (i.e. commented out, the default), act as if set to /bin/bash
# - empty (explicit), don't pass shell information to useradd at all
# and rely on a correct configuration file in /etc/default/useradd
# - set, non-empty, use that path as shell. No validation is done
# that the shell actually exists or is executable.
# - *forbidden_names* Login names that may not be used. This list always
# contains "root" and "nobody", but may be extended to list other special
# names for a given distro (eg. "video", or "mysql" might not be a valid
# end-user login name).
user:
shell: /bin/bash
forbidden_names: [ root ]
# TODO:3.3: Remove this setting
#
# This is the legacy setting for user.shell
userShell: /bin/bash
# Hostname settings
@@ -186,10 +203,14 @@ userShell: /bin/bash
# `${key}` values to something that will fit in a hostname, but does not
# apply the same to literal text in the template. Do not use invalid
# characters in the literal text, or no suggeston will be done.
# - *forbidden_names* lists hostnames that may not be used. This list
# always contains "localhost", but may list others that are unsuitable
# or broken in special ways.
hostname:
location: EtcFile
writeHostsFile: true
template: "derp-${cpu}"
forbidden_names: [ localhost ]
# TODO:3.3: Remove this setting
#

View File

@@ -8,6 +8,12 @@ type: object
properties:
# User shell, should be path to /bin/sh or so
userShell: { type: string }
user:
additionalProperties: false
type: object
properties:
shell: { type: string } # Overrides userShell
forbidden_names: { type: array, items: { type: string } }
# Group settings
defaultGroups:
type: array
@@ -47,6 +53,7 @@ properties:
location: { type: string, enum: [ None, EtcFile, Hostnamed, Transient ] }
writeHostsFile: { type: boolean, default: true }
template: { type: string, default: "${first}-${product}" }
forbidden_names: { type: array, items: { type: string } }
# Legacy Hostname setting
setHostname: { type: string, enum: [ None, EtcFile, Hostnamed ] }
writeHostsFile: { type: boolean, default: true }

View File

@@ -165,7 +165,7 @@ WelcomePage::setupButton( Button role, const QString& url )
{
auto size = 2 * QSize( CalamaresUtils::defaultFontHeight(), CalamaresUtils::defaultFontHeight() );
button->setIcon( CalamaresUtils::defaultPixmap( icon, CalamaresUtils::Original, size ) );
connect( button, &QPushButton::clicked, [u]() { QDesktopServices::openUrl( u ); } );
connect( button, &QPushButton::clicked, [ u ]() { QDesktopServices::openUrl( u ); } );
}
else
{

View File

@@ -152,10 +152,10 @@ GeneralRequirements::checkRequirements()
{
checkEntries.append(
{ entry,
[req = m_requiredStorageGiB] { return tr( "has at least %1 GiB available drive space" ).arg( req ); },
[req = m_requiredStorageGiB] {
return tr( "There is not enough drive space. At least %1 GiB is required." ).arg( req );
},
[ req = m_requiredStorageGiB ]
{ return tr( "has at least %1 GiB available drive space" ).arg( req ); },
[ req = m_requiredStorageGiB ]
{ return tr( "There is not enough drive space. At least %1 GiB is required." ).arg( req ); },
enoughStorage,
m_entriesToRequire.contains( entry ) } );
}
@@ -163,8 +163,8 @@ GeneralRequirements::checkRequirements()
{
checkEntries.append(
{ entry,
[req = m_requiredRamGiB] { return tr( "has at least %1 GiB working memory" ).arg( req ); },
[req = m_requiredRamGiB] {
[ req = m_requiredRamGiB ] { return tr( "has at least %1 GiB working memory" ).arg( req ); },
[ req = m_requiredRamGiB ] {
return tr( "The system does not have enough working memory. At least %1 GiB is required." )
.arg( req );
},
@@ -191,7 +191,8 @@ GeneralRequirements::checkRequirements()
{
checkEntries.append( { entry,
[] { return tr( "is running the installer as an administrator (root)" ); },
[] {
[]
{
return Calamares::Settings::instance()->isSetupMode()
? tr( "The setup program is not running with administrator rights." )
: tr( "The installer is not running with administrator rights." );
@@ -203,7 +204,8 @@ GeneralRequirements::checkRequirements()
{
checkEntries.append( { entry,
[] { return tr( "has a screen large enough to show the whole installer" ); },
[] {
[]
{
return Calamares::Settings::instance()->isSetupMode()
? tr( "The screen is too small to display the setup program." )
: tr( "The screen is too small to display the installer." );

View File

@@ -110,10 +110,11 @@ ResultsListDialog::ResultsListDialog( const Calamares::RequirementsModel& model,
m_title = new QLabel( this );
m_title->setObjectName( "resultDialogTitle" );
createResultWidgets(
entriesLayout, m_resultWidgets, model, []( const Calamares::RequirementsModel& m, QModelIndex i ) {
return m.data( i, Calamares::RequirementsModel::HasDetails ).toBool();
} );
createResultWidgets( entriesLayout,
m_resultWidgets,
model,
[]( const Calamares::RequirementsModel& m, QModelIndex i )
{ return m.data( i, Calamares::RequirementsModel::HasDetails ).toBool(); } );
QDialogButtonBox* buttonBox = new QDialogButtonBox( QDialogButtonBox::Close, Qt::Horizontal, this );
buttonBox->setObjectName( "resultDialogButtons" );
@@ -182,9 +183,8 @@ ResultsListWidget::ResultsListWidget( Config* config, QWidget* parent )
// all *mandatory* entries are satisfied (gives errors if not).
const bool requirementsSatisfied = config->requirementsModel()->satisfiedRequirements();
auto isUnSatisfied = []( const Calamares::RequirementsModel& m, QModelIndex i ) {
return !m.data( i, Calamares::RequirementsModel::Satisfied ).toBool();
};
auto isUnSatisfied = []( const Calamares::RequirementsModel& m, QModelIndex i )
{ return !m.data( i, Calamares::RequirementsModel::Satisfied ).toBool(); };
createResultWidgets( entriesLayout, m_resultWidgets, *( config->requirementsModel() ), isUnSatisfied );