From b1cf7eed38f2b4fd2d4522c04af808b184f031f4 Mon Sep 17 00:00:00 2001 From: sc74 Date: Fri, 4 Oct 2024 21:35:09 +0200 Subject: [PATCH] Delete modules --- src/modules/bootloader/bootloader.conf | 83 - src/modules/bootloader/bootloader.schema.yaml | 26 - src/modules/bootloader/main.py | 931 --- src/modules/bootloader/module.desc | 10 - src/modules/bootloader/test.yaml | 7 - src/modules/bootloader/tests/CMakeTests.txt | 10 - .../tests/test-bootloader-efiname.py | 67 - .../displaymanager/displaymanager.conf | 80 - .../displaymanager/displaymanager.schema.yaml | 39 - src/modules/displaymanager/main.py | 1030 --- src/modules/displaymanager/module.desc | 7 - src/modules/displaymanager/tests/1.global | 3 - .../displaymanager/tests/CMakeTests.txt | 13 - .../displaymanager/tests/test-dm-greetd.py | 33 - .../displaymanager/tests/test-dm-sddm.py | 18 - src/modules/dracut/dracut.conf | 10 - src/modules/dracut/dracut.schema.yaml | 9 - src/modules/dracut/main.py | 64 - src/modules/dracut/module.desc | 7 - src/modules/dracutlukscfg/CMakeLists.txt | 13 - .../dracutlukscfg/DracutLuksCfgJob.cpp | 159 - src/modules/dracutlukscfg/DracutLuksCfgJob.h | 40 - src/modules/dummycpp/CMakeLists.txt | 12 - src/modules/dummycpp/DummyCppJob.cpp | 142 - src/modules/dummycpp/DummyCppJob.h | 43 - src/modules/dummycpp/dummycpp.conf | 24 - src/modules/dummycpp/module.desc | 22 - src/modules/dummyprocess/module.desc | 11 - src/modules/dummypython/dummypython.conf | 24 - src/modules/dummypython/main.py | 114 - src/modules/dummypython/module.desc | 9 - src/modules/dummypython/tests/1.global | 6 - src/modules/finishedq/CMakeLists.txt | 31 - src/modules/finishedq/FinishedQmlViewStep.cpp | 92 - src/modules/finishedq/FinishedQmlViewStep.h | 57 - src/modules/finishedq/finishedq-qt6.qml | 99 - src/modules/finishedq/finishedq-qt6.qrc | 6 - src/modules/finishedq/finishedq.conf | 36 - src/modules/finishedq/finishedq.qml | 101 - src/modules/finishedq/finishedq.qrc | 6 - src/modules/finishedq/finishedq@mobile.qml | 122 - src/modules/finishedq/seedling.svg | 1 - src/modules/finishedq/seedling.svg.license | 2 - src/modules/fsresizer/CMakeLists.txt | 38 - src/modules/fsresizer/ResizeFSJob.cpp | 256 - src/modules/fsresizer/ResizeFSJob.h | 71 - src/modules/fsresizer/Tests.cpp | 125 - src/modules/fsresizer/Tests.h | 30 - src/modules/fsresizer/fsresizer.conf | 52 - src/modules/fstab/fstab.conf | 37 - src/modules/fstab/fstab.schema.yaml | 28 - src/modules/fstab/main.py | 432 -- src/modules/fstab/module.desc | 7 - src/modules/fstab/test.yaml | 16 - src/modules/fstab/test2.yaml | 25 - src/modules/grubcfg/grubcfg.conf | 51 - src/modules/grubcfg/grubcfg.schema.yaml | 23 - src/modules/grubcfg/main.py | 329 - src/modules/grubcfg/module.desc | 7 - src/modules/grubcfg/tests/1.global | 5 - src/modules/grubcfg/tests/2.global | 11 - src/modules/grubcfg/tests/2.job | 11 - src/modules/grubcfg/tests/3.global | 11 - src/modules/grubcfg/tests/3.job | 12 - src/modules/grubcfg/tests/4.global | 11 - src/modules/grubcfg/tests/4.job | 12 - src/modules/grubcfg/tests/CMakeTests.txt | 17 - src/modules/hostinfo/CMakeLists.txt | 37 - src/modules/hostinfo/HostInfoJob.cpp | 190 - src/modules/hostinfo/HostInfoJob.h | 55 - src/modules/hostinfo/Tests.cpp | 87 - src/modules/hwclock/main.py | 56 - src/modules/hwclock/module.desc | 8 - src/modules/initcpio/CMakeLists.txt | 20 - src/modules/initcpio/InitcpioJob.cpp | 97 - src/modules/initcpio/InitcpioJob.h | 41 - src/modules/initcpio/Tests.cpp | 46 - src/modules/initcpio/Tests.h | 27 - src/modules/initcpio/initcpio.conf | 26 - src/modules/initcpio/initcpio.schema.yaml | 11 - src/modules/initcpiocfg/initcpiocfg.conf | 11 - .../initcpiocfg/initcpiocfg.schema.yaml | 11 - src/modules/initcpiocfg/main.py | 266 - src/modules/initcpiocfg/module.desc | 12 - src/modules/initramfs/CMakeLists.txt | 20 - src/modules/initramfs/InitramfsJob.cpp | 90 - src/modules/initramfs/InitramfsJob.h | 41 - src/modules/initramfs/Tests.cpp | 74 - src/modules/initramfs/Tests.h | 30 - src/modules/initramfs/initramfs.conf | 39 - src/modules/initramfscfg/encrypt_hook | 29 - src/modules/initramfscfg/encrypt_hook_nokey | 25 - src/modules/initramfscfg/main.py | 94 - src/modules/initramfscfg/module.desc | 8 - .../interactiveterminal/CMakeLists.txt | 25 - .../InteractiveTerminalPage.cpp | 128 - .../InteractiveTerminalPage.h | 37 - .../InteractiveTerminalViewStep.cpp | 95 - .../InteractiveTerminalViewStep.h | 54 - .../interactiveterminal.conf | 17 - src/modules/keyboardq/CMakeLists.txt | 29 - src/modules/keyboardq/KeyboardQmlViewStep.cpp | 94 - src/modules/keyboardq/KeyboardQmlViewStep.h | 52 - src/modules/keyboardq/data/Key-qt6.qml | 180 - src/modules/keyboardq/data/Key.qml | 180 - src/modules/keyboardq/data/Keyboard-qt6.qml | 224 - src/modules/keyboardq/data/Keyboard.qml | 223 - src/modules/keyboardq/data/afgani-qt6.xml | 65 - src/modules/keyboardq/data/afgani.xml | 65 - src/modules/keyboardq/data/ar-qt6.xml | 65 - src/modules/keyboardq/data/ar.xml | 65 - src/modules/keyboardq/data/backspace.svg | 7 - .../keyboardq/data/backspace.svg.license | 2 - .../keyboardq/data/button_bkg_center.png | Bin 4289 -> 0 bytes .../data/button_bkg_center.png.license | 2 - .../keyboardq/data/button_bkg_left.png | Bin 5549 -> 0 bytes .../data/button_bkg_left.png.license | 2 - .../keyboardq/data/button_bkg_right.png | Bin 5955 -> 0 bytes .../data/button_bkg_right.png.license | 2 - src/modules/keyboardq/data/de-qt6.xml | 66 - src/modules/keyboardq/data/de.xml | 66 - src/modules/keyboardq/data/empty-qt6.xml | 64 - src/modules/keyboardq/data/empty.xml | 64 - src/modules/keyboardq/data/en-qt6.xml | 64 - src/modules/keyboardq/data/en.xml | 64 - src/modules/keyboardq/data/enter.svg | 43 - src/modules/keyboardq/data/enter.svg.license | 2 - src/modules/keyboardq/data/es-qt6.xml | 64 - src/modules/keyboardq/data/es.xml | 64 - src/modules/keyboardq/data/fr-qt6.xml | 66 - src/modules/keyboardq/data/fr.xml | 66 - src/modules/keyboardq/data/generic-qt6.xml | 64 - src/modules/keyboardq/data/generic.xml | 64 - src/modules/keyboardq/data/generic_qz-qt6.xml | 66 - src/modules/keyboardq/data/generic_qz.xml | 66 - .../keyboardq/data/pan-end-symbolic.svg | 15 - .../data/pan-end-symbolic.svg.license | 2 - src/modules/keyboardq/data/pt-qt6.xml | 64 - src/modules/keyboardq/data/pt.xml | 64 - src/modules/keyboardq/data/ru-qt6.xml | 64 - src/modules/keyboardq/data/ru.xml | 64 - src/modules/keyboardq/data/scan.xml | 64 - src/modules/keyboardq/data/shift.svg | 7 - src/modules/keyboardq/data/shift.svg.license | 2 - src/modules/keyboardq/keyboardq-qt6.qml | 356 - src/modules/keyboardq/keyboardq-qt6.qrc | 29 - src/modules/keyboardq/keyboardq.conf | 19 - src/modules/keyboardq/keyboardq.qml | 356 - src/modules/keyboardq/keyboardq.qrc | 29 - src/modules/license/CMakeLists.txt | 18 - src/modules/license/LicensePage.cpp | 201 - src/modules/license/LicensePage.h | 100 - src/modules/license/LicensePage.ui | 172 - src/modules/license/LicenseViewStep.cpp | 114 - src/modules/license/LicenseViewStep.h | 52 - src/modules/license/LicenseWidget.cpp | 198 - src/modules/license/LicenseWidget.h | 45 - src/modules/license/README.md | 26 - src/modules/license/license.conf | 53 - src/modules/license/license.schema.yaml | 21 - src/modules/localeq/CMakeLists.txt | 42 - src/modules/localeq/LocaleQmlViewStep.cpp | 91 - src/modules/localeq/LocaleQmlViewStep.h | 51 - src/modules/localeq/Map-qt6.qml | 263 - src/modules/localeq/Map.qml | 263 - src/modules/localeq/Offline-qt6.qml | 243 - src/modules/localeq/Offline.qml | 243 - src/modules/localeq/img/locale.svg | 5720 ----------------- src/modules/localeq/img/locale.svg.license | 2 - src/modules/localeq/img/minus.png | Bin 177 -> 0 bytes src/modules/localeq/img/minus.png.license | 2 - src/modules/localeq/img/pin.svg | 60 - src/modules/localeq/img/pin.svg.license | 2 - src/modules/localeq/img/plus.png | Bin 483 -> 0 bytes src/modules/localeq/img/plus.png.license | 2 - src/modules/localeq/localeq-qt6.qml | 259 - src/modules/localeq/localeq-qt6.qrc | 11 - src/modules/localeq/localeq.conf | 100 - src/modules/localeq/localeq.qml | 259 - src/modules/localeq/localeq.qrc | 11 - src/modules/luksbootkeyfile/CMakeLists.txt | 14 - .../luksbootkeyfile/LuksBootKeyFileJob.cpp | 343 - .../luksbootkeyfile/LuksBootKeyFileJob.h | 42 - src/modules/luksbootkeyfile/Tests.cpp | 168 - .../luksbootkeyfile/luksbootkeyfile.conf | 14 - .../luksbootkeyfile.schema.yaml | 9 - .../luksopenswaphookcfg/CMakeLists.txt | 17 - src/modules/luksopenswaphookcfg/LOSHInfo.h | 66 - src/modules/luksopenswaphookcfg/LOSHJob.cpp | 179 - src/modules/luksopenswaphookcfg/LOSHJob.h | 37 - src/modules/luksopenswaphookcfg/Tests.cpp | 248 - .../luksopenswaphookcfg.conf | 7 - .../luksopenswaphookcfg.schema.yaml | 10 - src/modules/machineid/CMakeLists.txt | 15 - src/modules/machineid/MachineIdJob.cpp | 188 - src/modules/machineid/MachineIdJob.h | 62 - src/modules/machineid/Tests.cpp | 264 - src/modules/machineid/Workers.cpp | 191 - src/modules/machineid/Workers.h | 70 - src/modules/machineid/machineid.conf | 56 - src/modules/machineid/machineid.schema.yaml | 17 - src/modules/mkinitfs/main.py | 50 - src/modules/mkinitfs/module.desc | 7 - src/modules/mount/main.py | 379 -- src/modules/mount/module.desc | 7 - src/modules/mount/mount.conf | 125 - src/modules/mount/mount.schema.yaml | 43 - src/modules/mount/tests/1.global | 12 - src/modules/mount/tests/1.job | 6 - src/modules/mount/tests/2.global | 8 - src/modules/mount/tests/2.job | 6 - src/modules/mount/tests/3.global | 8 - src/modules/mount/tests/3.job | 6 - src/modules/mount/tests/4.global | 11 - src/modules/mount/tests/4.job | 12 - src/modules/networkcfg/main.py | 187 - src/modules/networkcfg/module.desc | 8 - src/modules/oemid/CMakeLists.txt | 17 - src/modules/oemid/IDJob.cpp | 89 - src/modules/oemid/IDJob.h | 33 - src/modules/oemid/OEMPage.ui | 100 - src/modules/oemid/OEMViewStep.cpp | 150 - src/modules/oemid/OEMViewStep.h | 57 - src/modules/oemid/oemid.conf | 16 - src/modules/openrcdmcryptcfg/main.py | 81 - src/modules/openrcdmcryptcfg/module.desc | 7 - .../openrcdmcryptcfg/openrcdmcryptcfg.conf | 5 - src/modules/partition/CMakeLists.txt | 122 - src/modules/partition/Config.cpp | 466 -- src/modules/partition/Config.h | 214 - src/modules/partition/PartitionViewStep.cpp | 763 --- src/modules/partition/PartitionViewStep.h | 89 - src/modules/partition/README.md | 96 - .../partition/core/BootLoaderModel.cpp | 215 - src/modules/partition/core/BootLoaderModel.h | 75 - src/modules/partition/core/ColorUtils.cpp | 197 - src/modules/partition/core/ColorUtils.h | 49 - src/modules/partition/core/DeviceList.cpp | 197 - src/modules/partition/core/DeviceList.h | 40 - src/modules/partition/core/DeviceModel.cpp | 150 - src/modules/partition/core/DeviceModel.h | 53 - src/modules/partition/core/KPMHelpers.cpp | 339 - src/modules/partition/core/KPMHelpers.h | 154 - src/modules/partition/core/OsproberEntry.h | 54 - src/modules/partition/core/PartUtils.cpp | 681 -- src/modules/partition/core/PartUtils.h | 154 - .../partition/core/PartitionActions.cpp | 258 - src/modules/partition/core/PartitionActions.h | 95 - .../partition/core/PartitionCoreModule.cpp | 1223 ---- .../partition/core/PartitionCoreModule.h | 279 - src/modules/partition/core/PartitionInfo.cpp | 118 - src/modules/partition/core/PartitionInfo.h | 62 - .../partition/core/PartitionLayout.cpp | 378 -- src/modules/partition/core/PartitionLayout.h | 131 - src/modules/partition/core/PartitionModel.cpp | 338 - src/modules/partition/core/PartitionModel.h | 116 - src/modules/partition/core/SizeUtils.h | 28 - src/modules/partition/gui/BootInfoWidget.cpp | 94 - src/modules/partition/gui/BootInfoWidget.h | 32 - src/modules/partition/gui/ChoicePage.cpp | 1762 ----- src/modules/partition/gui/ChoicePage.h | 177 - src/modules/partition/gui/ChoicePage.ui | 224 - .../partition/gui/CreatePartitionDialog.cpp | 362 -- .../partition/gui/CreatePartitionDialog.h | 98 - .../partition/gui/CreatePartitionDialog.ui | 344 - .../gui/CreatePartitionTableDialog.ui | 142 - .../partition/gui/CreateVolumeGroupDialog.cpp | 47 - .../partition/gui/CreateVolumeGroupDialog.h | 33 - .../partition/gui/DeviceInfoWidget.cpp | 155 - src/modules/partition/gui/DeviceInfoWidget.h | 37 - .../gui/EditExistingPartitionDialog.cpp | 384 -- .../gui/EditExistingPartitionDialog.h | 64 - .../gui/EditExistingPartitionDialog.ui | 289 - src/modules/partition/gui/EncryptWidget.cpp | 217 - src/modules/partition/gui/EncryptWidget.h | 68 - src/modules/partition/gui/EncryptWidget.ui | 100 - .../gui/ListPhysicalVolumeWidgetItem.cpp | 29 - .../gui/ListPhysicalVolumeWidgetItem.h | 29 - .../partition/gui/PartitionBarsView.cpp | 535 -- src/modules/partition/gui/PartitionBarsView.h | 91 - .../partition/gui/PartitionDialogHelpers.cpp | 146 - .../partition/gui/PartitionDialogHelpers.h | 79 - .../partition/gui/PartitionLabelsView.cpp | 604 -- .../partition/gui/PartitionLabelsView.h | 84 - src/modules/partition/gui/PartitionPage.cpp | 689 -- src/modules/partition/gui/PartitionPage.h | 89 - src/modules/partition/gui/PartitionPage.ui | 241 - .../partition/gui/PartitionSizeController.cpp | 221 - .../partition/gui/PartitionSizeController.h | 72 - .../partition/gui/PartitionSplitterWidget.cpp | 636 -- .../partition/gui/PartitionSplitterWidget.h | 94 - .../gui/PartitionViewSelectionFilter.h | 19 - .../partition/gui/ResizeVolumeGroupDialog.cpp | 59 - .../partition/gui/ResizeVolumeGroupDialog.h | 35 - src/modules/partition/gui/ScanningDialog.cpp | 76 - src/modules/partition/gui/ScanningDialog.h | 43 - .../partition/gui/VolumeGroupBaseDialog.cpp | 185 - .../partition/gui/VolumeGroupBaseDialog.h | 71 - .../partition/gui/VolumeGroupBaseDialog.ui | 210 - .../partition/jobs/AutoMountManagementJob.cpp | 40 - .../partition/jobs/AutoMountManagementJob.h | 42 - .../jobs/ChangeFilesystemLabelJob.cpp | 86 - .../partition/jobs/ChangeFilesystemLabelJob.h | 40 - src/modules/partition/jobs/ClearMountsJob.cpp | 396 -- src/modules/partition/jobs/ClearMountsJob.h | 59 - .../partition/jobs/ClearTempMountsJob.cpp | 76 - .../partition/jobs/ClearTempMountsJob.h | 31 - .../partition/jobs/CreatePartitionJob.cpp | 283 - .../partition/jobs/CreatePartitionJob.h | 44 - .../jobs/CreatePartitionTableJob.cpp | 106 - .../partition/jobs/CreatePartitionTableJob.h | 48 - .../partition/jobs/CreateVolumeGroupJob.cpp | 70 - .../partition/jobs/CreateVolumeGroupJob.h | 42 - .../jobs/DeactivateVolumeGroupJob.cpp | 52 - .../partition/jobs/DeactivateVolumeGroupJob.h | 34 - .../partition/jobs/DeletePartitionJob.cpp | 120 - .../partition/jobs/DeletePartitionJob.h | 44 - .../partition/jobs/FillGlobalStorageJob.cpp | 400 -- .../partition/jobs/FillGlobalStorageJob.h | 49 - .../partition/jobs/FormatPartitionJob.cpp | 85 - .../partition/jobs/FormatPartitionJob.h | 42 - src/modules/partition/jobs/PartitionJob.cpp | 29 - src/modules/partition/jobs/PartitionJob.h | 43 - .../partition/jobs/RemoveVolumeGroupJob.cpp | 47 - .../partition/jobs/RemoveVolumeGroupJob.h | 35 - .../partition/jobs/ResizePartitionJob.cpp | 90 - .../partition/jobs/ResizePartitionJob.h | 47 - .../partition/jobs/ResizeVolumeGroupJob.cpp | 89 - .../partition/jobs/ResizeVolumeGroupJob.h | 43 - .../partition/jobs/SetPartitionFlagsJob.cpp | 150 - .../partition/jobs/SetPartitionFlagsJob.h | 43 - src/modules/partition/partition.conf | 321 - src/modules/partition/partition.schema.yaml | 46 - src/modules/partition/tests/1a-legacy.conf | 2 - src/modules/partition/tests/1b-legacy.conf | 2 - src/modules/partition/tests/2a-legacy.conf | 9 - src/modules/partition/tests/2b-modern.conf | 6 - src/modules/partition/tests/2c-mixed.conf | 7 - src/modules/partition/tests/2d-overlap.conf | 9 - .../partition/tests/3a-min-too-large.conf | 5 - .../partition/tests/AutoMountTests.cpp | 88 - src/modules/partition/tests/CMakeLists.txt | 76 - .../partition/tests/ClearMountsJobTests.cpp | 68 - .../partition/tests/ClearMountsJobTests.h | 25 - src/modules/partition/tests/ConfigTests.cpp | 230 - .../partition/tests/CreateLayoutsTests.cpp | 153 - .../partition/tests/CreateLayoutsTests.h | 39 - src/modules/partition/tests/DevicesTests.cpp | 85 - .../partition/tests/PartitionJobTests.cpp | 443 -- .../partition/tests/PartitionJobTests.h | 66 - src/modules/plasmalnf/CMakeLists.txt | 53 - src/modules/plasmalnf/Config.cpp | 167 - src/modules/plasmalnf/Config.h | 77 - src/modules/plasmalnf/PlasmaLnfJob.cpp | 72 - src/modules/plasmalnf/PlasmaLnfJob.h | 35 - src/modules/plasmalnf/PlasmaLnfPage.cpp | 117 - src/modules/plasmalnf/PlasmaLnfPage.h | 39 - src/modules/plasmalnf/PlasmaLnfViewStep.cpp | 99 - src/modules/plasmalnf/PlasmaLnfViewStep.h | 51 - src/modules/plasmalnf/ThemeInfo.cpp | 316 - src/modules/plasmalnf/ThemeInfo.h | 75 - src/modules/plasmalnf/page_plasmalnf.qrc | 5 - src/modules/plasmalnf/page_plasmalnf.ui | 37 - src/modules/plasmalnf/plasmalnf.conf | 83 - src/modules/plasmalnf/view-preview.png | Bin 560 -> 0 bytes .../plasmalnf/view-preview.png.license | 2 - src/modules/plasmalnf/view-preview.svg | 13 - .../plasmalnf/view-preview.svg.license | 2 - src/modules/plymouthcfg/main.py | 65 - src/modules/plymouthcfg/module.desc | 7 - src/modules/plymouthcfg/plymouthcfg.conf | 31 - .../plymouthcfg/plymouthcfg.schema.yaml | 9 - src/modules/preservefiles/CMakeLists.txt | 17 - src/modules/preservefiles/Item.cpp | 159 - src/modules/preservefiles/Item.h | 74 - src/modules/preservefiles/PreserveFiles.cpp | 120 - src/modules/preservefiles/PreserveFiles.h | 39 - src/modules/preservefiles/Tests.cpp | 93 - src/modules/preservefiles/preservefiles.conf | 70 - .../preservefiles/preservefiles.schema.yaml | 37 - src/modules/preservefiles/tests/1a-log.conf | 7 - .../preservefiles/tests/1b-config.conf | 6 - src/modules/preservefiles/tests/1c-src.conf | 6 - .../preservefiles/tests/1d-filename.conf | 6 - src/modules/preservefiles/tests/1e-empty.conf | 3 - src/modules/preservefiles/tests/1f-bad.conf | 4 - src/modules/rawfs/main.py | 182 - src/modules/rawfs/module.desc | 9 - src/modules/rawfs/rawfs.conf | 32 - src/modules/rawfs/tests/1.global | 11 - src/modules/rawfs/tests/1.job | 17 - src/modules/rawfs/tests/CMakeTests.txt | 12 - src/modules/removeuser/CMakeLists.txt | 12 - src/modules/removeuser/RemoveUserJob.cpp | 62 - src/modules/removeuser/RemoveUserJob.h | 40 - src/modules/removeuser/removeuser.conf | 13 - src/modules/removeuser/removeuser.schema.yaml | 10 - src/modules/services-openrc/main.py | 131 - src/modules/services-openrc/module.desc | 7 - .../services-openrc/services-openrc.conf | 49 - src/modules/services-systemd/main.py | 86 - src/modules/services-systemd/module.desc | 7 - .../services-systemd/services-systemd.conf | 54 - .../services-systemd.schema.yaml | 21 - src/modules/summary/CMakeLists.txt | 18 - src/modules/summary/Config.cpp | 92 - src/modules/summary/Config.h | 63 - src/modules/summary/SummaryModel.cpp | 74 - src/modules/summary/SummaryModel.h | 67 - src/modules/summary/SummaryPage.cpp | 176 - src/modules/summary/SummaryPage.h | 61 - src/modules/summary/SummaryViewStep.cpp | 97 - src/modules/summary/SummaryViewStep.h | 51 - src/modules/summaryq/CMakeLists.txt | 28 - src/modules/summaryq/SummaryQmlViewStep.cpp | 73 - src/modules/summaryq/SummaryQmlViewStep.h | 49 - src/modules/summaryq/img/keyboard.svg | 22 - src/modules/summaryq/img/keyboard.svg.license | 2 - src/modules/summaryq/img/lokalize.svg | 39 - src/modules/summaryq/img/lokalize.svg.license | 2 - src/modules/summaryq/summaryq-qt6.qml | 111 - src/modules/summaryq/summaryq-qt6.qrc | 7 - src/modules/summaryq/summaryq.qml | 112 - src/modules/summaryq/summaryq.qrc | 7 - src/modules/tracking/CMakeLists.txt | 23 - src/modules/tracking/Config.cpp | 250 - src/modules/tracking/Config.h | 186 - src/modules/tracking/Tests.cpp | 59 - src/modules/tracking/TrackingJobs.cpp | 301 - src/modules/tracking/TrackingJobs.h | 37 - src/modules/tracking/TrackingPage.cpp | 156 - src/modules/tracking/TrackingPage.h | 69 - src/modules/tracking/TrackingType.h | 26 - src/modules/tracking/TrackingViewStep.cpp | 115 - src/modules/tracking/TrackingViewStep.h | 57 - src/modules/tracking/level-install.svg | 194 - .../tracking/level-install.svg.license | 2 - src/modules/tracking/level-machine.svg | 271 - .../tracking/level-machine.svg.license | 2 - src/modules/tracking/level-none.svg | 212 - src/modules/tracking/level-none.svg.license | 2 - src/modules/tracking/level-user.svg | 224 - src/modules/tracking/level-user.svg.license | 2 - src/modules/tracking/page_trackingstep.qrc | 9 - src/modules/tracking/page_trackingstep.ui | 310 - src/modules/tracking/tracking.conf | 105 - src/modules/umount/CMakeLists.txt | 15 - src/modules/umount/Tests.cpp | 52 - src/modules/umount/UmountJob.cpp | 160 - src/modules/umount/UmountJob.h | 41 - src/modules/umount/umount.conf | 14 - src/modules/umount/umount.schema.yaml | 9 - src/modules/unpackfs/main.py | 500 -- src/modules/unpackfs/module.desc | 10 - src/modules/unpackfs/runtests.sh | 37 - src/modules/unpackfs/tests/1.global | 4 - src/modules/unpackfs/tests/2.global | 4 - src/modules/unpackfs/tests/3.global | 4 - src/modules/unpackfs/tests/3.job | 4 - src/modules/unpackfs/tests/4.global | 4 - src/modules/unpackfs/tests/4.job | 10 - src/modules/unpackfs/tests/5.global | 4 - src/modules/unpackfs/tests/5.job | 7 - src/modules/unpackfs/tests/6.global | 4 - src/modules/unpackfs/tests/6.job | 7 - src/modules/unpackfs/tests/7.global | 4 - src/modules/unpackfs/tests/7.job | 7 - src/modules/unpackfs/tests/8.global | 6 - src/modules/unpackfs/tests/8.job | 7 - src/modules/unpackfs/tests/9.global | 5 - src/modules/unpackfs/tests/9.job | 8 - src/modules/unpackfs/unpackfs.conf | 100 - src/modules/unpackfs/unpackfs.schema.yaml | 21 - src/modules/users/CMakeLists.txt | 137 - src/modules/users/CheckPWQuality.cpp | 400 -- src/modules/users/CheckPWQuality.h | 80 - src/modules/users/Config.cpp | 1009 --- src/modules/users/Config.h | 356 - src/modules/users/CreateUserJob.cpp | 165 - src/modules/users/CreateUserJob.h | 32 - src/modules/users/MiscJobs.cpp | 210 - src/modules/users/MiscJobs.h | 50 - src/modules/users/SetHostNameJob.cpp | 161 - src/modules/users/SetHostNameJob.h | 33 - src/modules/users/SetPasswordJob.cpp | 112 - src/modules/users/SetPasswordJob.h | 34 - src/modules/users/TestGroupInformation.cpp | 177 - src/modules/users/TestPasswordJob.cpp | 55 - src/modules/users/TestSetHostNameJob.cpp | 163 - src/modules/users/Tests.cpp | 518 -- src/modules/users/UsersPage.cpp | 285 - src/modules/users/UsersPage.h | 54 - src/modules/users/UsersViewStep.cpp | 119 - src/modules/users/UsersViewStep.h | 56 - src/modules/users/images/invalid.png | Bin 7822 -> 0 bytes src/modules/users/images/invalid.png.license | 2 - src/modules/users/images/valid.png | Bin 7284 -> 0 bytes src/modules/users/images/valid.png.license | 2 - src/modules/users/page_usersetup.ui | 623 -- src/modules/users/tests/3-wing.conf | 5 - src/modules/users/tests/4-audio.conf | 9 - src/modules/users/tests/5-issue-1523.conf | 14 - src/modules/users/tests/6a-issue-1672.conf | 7 - src/modules/users/tests/6b-issue-1672.conf | 7 - src/modules/users/tests/6c-issue-1672.conf | 7 - src/modules/users/tests/6d-issue-1672.conf | 7 - src/modules/users/tests/6e-issue-1672.conf | 7 - src/modules/users/tests/7an-shell.conf | 8 - src/modules/users/tests/7ao-shell.conf | 7 - src/modules/users/tests/7bn-shell.conf | 8 - src/modules/users/tests/7bo-shell.conf | 7 - src/modules/users/tests/7cn-shell.conf | 8 - src/modules/users/tests/7co-shell.conf | 7 - src/modules/users/tests/7dn-shell.conf | 8 - src/modules/users/tests/7do-shell.conf | 7 - src/modules/users/tests/7en-shell.conf | 8 - src/modules/users/tests/7eo-shell.conf | 7 - src/modules/users/tests/7fb-shell.conf | 10 - src/modules/users/tests/7fn-shell.conf | 10 - src/modules/users/tests/7fo-shell.conf | 10 - src/modules/users/users.conf | 274 - src/modules/users/users.qrc | 6 - src/modules/users/users.schema.yaml | 71 - src/modules/usersq/CMakeLists.txt | 51 - src/modules/usersq/UsersQmlViewStep.cpp | 79 - src/modules/usersq/UsersQmlViewStep.h | 54 - src/modules/usersq/usersq-qt6.qml | 425 -- src/modules/usersq/usersq-qt6.qrc | 5 - src/modules/usersq/usersq.conf | 44 - src/modules/usersq/usersq.qml | 426 -- src/modules/usersq/usersq.qrc | 5 - src/modules/welcomeq/CMakeLists.txt | 48 - src/modules/welcomeq/Recommended.qml | 91 - src/modules/welcomeq/Requirements.qml | 108 - src/modules/welcomeq/WelcomeQmlViewStep.cpp | 94 - src/modules/welcomeq/WelcomeQmlViewStep.h | 70 - .../welcomeq/img/chevron-left-solid.svg | 1 - .../img/chevron-left-solid.svg.license | 2 - .../welcomeq/img/language-icon-48px.png | Bin 2315 -> 0 bytes .../img/language-icon-48px.png.license | 2 - src/modules/welcomeq/img/squid.png | Bin 8313 -> 0 bytes src/modules/welcomeq/img/squid.png.license | 2 - src/modules/welcomeq/release_notes.qml | 94 - src/modules/welcomeq/welcomeq-qt6.qml | 169 - src/modules/welcomeq/welcomeq-qt6.qrc | 11 - src/modules/welcomeq/welcomeq.conf | 40 - src/modules/welcomeq/welcomeq.qml | 169 - src/modules/welcomeq/welcomeq.qrc | 11 - src/modules/zfs/CMakeLists.txt | 12 - src/modules/zfs/README.md | 21 - src/modules/zfs/ZfsJob.cpp | 371 -- src/modules/zfs/ZfsJob.h | 89 - src/modules/zfs/zfs.conf | 45 - src/modules/zfs/zfs.schema.yaml | 24 - src/modules/zfshostid/main.py | 44 - src/modules/zfshostid/module.desc | 8 - src/modules/zfshostid/zfshostid.schema.yaml | 7 - 557 files changed, 58580 deletions(-) delete mode 100644 src/modules/bootloader/bootloader.conf delete mode 100644 src/modules/bootloader/bootloader.schema.yaml delete mode 100644 src/modules/bootloader/main.py delete mode 100644 src/modules/bootloader/module.desc delete mode 100644 src/modules/bootloader/test.yaml delete mode 100644 src/modules/bootloader/tests/CMakeTests.txt delete mode 100644 src/modules/bootloader/tests/test-bootloader-efiname.py delete mode 100644 src/modules/displaymanager/displaymanager.conf delete mode 100644 src/modules/displaymanager/displaymanager.schema.yaml delete mode 100644 src/modules/displaymanager/main.py delete mode 100644 src/modules/displaymanager/module.desc delete mode 100644 src/modules/displaymanager/tests/1.global delete mode 100644 src/modules/displaymanager/tests/CMakeTests.txt delete mode 100644 src/modules/displaymanager/tests/test-dm-greetd.py delete mode 100644 src/modules/displaymanager/tests/test-dm-sddm.py delete mode 100644 src/modules/dracut/dracut.conf delete mode 100644 src/modules/dracut/dracut.schema.yaml delete mode 100644 src/modules/dracut/main.py delete mode 100644 src/modules/dracut/module.desc delete mode 100644 src/modules/dracutlukscfg/CMakeLists.txt delete mode 100644 src/modules/dracutlukscfg/DracutLuksCfgJob.cpp delete mode 100644 src/modules/dracutlukscfg/DracutLuksCfgJob.h delete mode 100644 src/modules/dummycpp/CMakeLists.txt delete mode 100644 src/modules/dummycpp/DummyCppJob.cpp delete mode 100644 src/modules/dummycpp/DummyCppJob.h delete mode 100644 src/modules/dummycpp/dummycpp.conf delete mode 100644 src/modules/dummycpp/module.desc delete mode 100644 src/modules/dummyprocess/module.desc delete mode 100644 src/modules/dummypython/dummypython.conf delete mode 100644 src/modules/dummypython/main.py delete mode 100644 src/modules/dummypython/module.desc delete mode 100644 src/modules/dummypython/tests/1.global delete mode 100644 src/modules/finishedq/CMakeLists.txt delete mode 100644 src/modules/finishedq/FinishedQmlViewStep.cpp delete mode 100644 src/modules/finishedq/FinishedQmlViewStep.h delete mode 100644 src/modules/finishedq/finishedq-qt6.qml delete mode 100644 src/modules/finishedq/finishedq-qt6.qrc delete mode 100644 src/modules/finishedq/finishedq.conf delete mode 100644 src/modules/finishedq/finishedq.qml delete mode 100644 src/modules/finishedq/finishedq.qrc delete mode 100644 src/modules/finishedq/finishedq@mobile.qml delete mode 100644 src/modules/finishedq/seedling.svg delete mode 100644 src/modules/finishedq/seedling.svg.license delete mode 100644 src/modules/fsresizer/CMakeLists.txt delete mode 100644 src/modules/fsresizer/ResizeFSJob.cpp delete mode 100644 src/modules/fsresizer/ResizeFSJob.h delete mode 100644 src/modules/fsresizer/Tests.cpp delete mode 100644 src/modules/fsresizer/Tests.h delete mode 100644 src/modules/fsresizer/fsresizer.conf delete mode 100644 src/modules/fstab/fstab.conf delete mode 100644 src/modules/fstab/fstab.schema.yaml delete mode 100755 src/modules/fstab/main.py delete mode 100644 src/modules/fstab/module.desc delete mode 100644 src/modules/fstab/test.yaml delete mode 100644 src/modules/fstab/test2.yaml delete mode 100644 src/modules/grubcfg/grubcfg.conf delete mode 100644 src/modules/grubcfg/grubcfg.schema.yaml delete mode 100644 src/modules/grubcfg/main.py delete mode 100644 src/modules/grubcfg/module.desc delete mode 100644 src/modules/grubcfg/tests/1.global delete mode 100644 src/modules/grubcfg/tests/2.global delete mode 100644 src/modules/grubcfg/tests/2.job delete mode 100644 src/modules/grubcfg/tests/3.global delete mode 100644 src/modules/grubcfg/tests/3.job delete mode 100644 src/modules/grubcfg/tests/4.global delete mode 100644 src/modules/grubcfg/tests/4.job delete mode 100644 src/modules/grubcfg/tests/CMakeTests.txt delete mode 100644 src/modules/hostinfo/CMakeLists.txt delete mode 100644 src/modules/hostinfo/HostInfoJob.cpp delete mode 100644 src/modules/hostinfo/HostInfoJob.h delete mode 100644 src/modules/hostinfo/Tests.cpp delete mode 100644 src/modules/hwclock/main.py delete mode 100644 src/modules/hwclock/module.desc delete mode 100644 src/modules/initcpio/CMakeLists.txt delete mode 100644 src/modules/initcpio/InitcpioJob.cpp delete mode 100644 src/modules/initcpio/InitcpioJob.h delete mode 100644 src/modules/initcpio/Tests.cpp delete mode 100644 src/modules/initcpio/Tests.h delete mode 100644 src/modules/initcpio/initcpio.conf delete mode 100644 src/modules/initcpio/initcpio.schema.yaml delete mode 100644 src/modules/initcpiocfg/initcpiocfg.conf delete mode 100644 src/modules/initcpiocfg/initcpiocfg.schema.yaml delete mode 100644 src/modules/initcpiocfg/main.py delete mode 100644 src/modules/initcpiocfg/module.desc delete mode 100644 src/modules/initramfs/CMakeLists.txt delete mode 100644 src/modules/initramfs/InitramfsJob.cpp delete mode 100644 src/modules/initramfs/InitramfsJob.h delete mode 100644 src/modules/initramfs/Tests.cpp delete mode 100644 src/modules/initramfs/Tests.h delete mode 100644 src/modules/initramfs/initramfs.conf delete mode 100755 src/modules/initramfscfg/encrypt_hook delete mode 100755 src/modules/initramfscfg/encrypt_hook_nokey delete mode 100644 src/modules/initramfscfg/main.py delete mode 100644 src/modules/initramfscfg/module.desc delete mode 100644 src/modules/interactiveterminal/CMakeLists.txt delete mode 100644 src/modules/interactiveterminal/InteractiveTerminalPage.cpp delete mode 100644 src/modules/interactiveterminal/InteractiveTerminalPage.h delete mode 100644 src/modules/interactiveterminal/InteractiveTerminalViewStep.cpp delete mode 100644 src/modules/interactiveterminal/InteractiveTerminalViewStep.h delete mode 100644 src/modules/interactiveterminal/interactiveterminal.conf delete mode 100644 src/modules/keyboardq/CMakeLists.txt delete mode 100644 src/modules/keyboardq/KeyboardQmlViewStep.cpp delete mode 100644 src/modules/keyboardq/KeyboardQmlViewStep.h delete mode 100644 src/modules/keyboardq/data/Key-qt6.qml delete mode 100644 src/modules/keyboardq/data/Key.qml delete mode 100644 src/modules/keyboardq/data/Keyboard-qt6.qml delete mode 100644 src/modules/keyboardq/data/Keyboard.qml delete mode 100644 src/modules/keyboardq/data/afgani-qt6.xml delete mode 100644 src/modules/keyboardq/data/afgani.xml delete mode 100644 src/modules/keyboardq/data/ar-qt6.xml delete mode 100644 src/modules/keyboardq/data/ar.xml delete mode 100755 src/modules/keyboardq/data/backspace.svg delete mode 100644 src/modules/keyboardq/data/backspace.svg.license delete mode 100755 src/modules/keyboardq/data/button_bkg_center.png delete mode 100644 src/modules/keyboardq/data/button_bkg_center.png.license delete mode 100755 src/modules/keyboardq/data/button_bkg_left.png delete mode 100644 src/modules/keyboardq/data/button_bkg_left.png.license delete mode 100755 src/modules/keyboardq/data/button_bkg_right.png delete mode 100644 src/modules/keyboardq/data/button_bkg_right.png.license delete mode 100644 src/modules/keyboardq/data/de-qt6.xml delete mode 100644 src/modules/keyboardq/data/de.xml delete mode 100644 src/modules/keyboardq/data/empty-qt6.xml delete mode 100644 src/modules/keyboardq/data/empty.xml delete mode 100644 src/modules/keyboardq/data/en-qt6.xml delete mode 100644 src/modules/keyboardq/data/en.xml delete mode 100755 src/modules/keyboardq/data/enter.svg delete mode 100644 src/modules/keyboardq/data/enter.svg.license delete mode 100644 src/modules/keyboardq/data/es-qt6.xml delete mode 100644 src/modules/keyboardq/data/es.xml delete mode 100644 src/modules/keyboardq/data/fr-qt6.xml delete mode 100644 src/modules/keyboardq/data/fr.xml delete mode 100644 src/modules/keyboardq/data/generic-qt6.xml delete mode 100644 src/modules/keyboardq/data/generic.xml delete mode 100644 src/modules/keyboardq/data/generic_qz-qt6.xml delete mode 100644 src/modules/keyboardq/data/generic_qz.xml delete mode 100644 src/modules/keyboardq/data/pan-end-symbolic.svg delete mode 100644 src/modules/keyboardq/data/pan-end-symbolic.svg.license delete mode 100644 src/modules/keyboardq/data/pt-qt6.xml delete mode 100644 src/modules/keyboardq/data/pt.xml delete mode 100644 src/modules/keyboardq/data/ru-qt6.xml delete mode 100644 src/modules/keyboardq/data/ru.xml delete mode 100644 src/modules/keyboardq/data/scan.xml delete mode 100755 src/modules/keyboardq/data/shift.svg delete mode 100644 src/modules/keyboardq/data/shift.svg.license delete mode 100644 src/modules/keyboardq/keyboardq-qt6.qml delete mode 100644 src/modules/keyboardq/keyboardq-qt6.qrc delete mode 100644 src/modules/keyboardq/keyboardq.conf delete mode 100644 src/modules/keyboardq/keyboardq.qml delete mode 100644 src/modules/keyboardq/keyboardq.qrc delete mode 100644 src/modules/license/CMakeLists.txt delete mode 100644 src/modules/license/LicensePage.cpp delete mode 100644 src/modules/license/LicensePage.h delete mode 100644 src/modules/license/LicensePage.ui delete mode 100644 src/modules/license/LicenseViewStep.cpp delete mode 100644 src/modules/license/LicenseViewStep.h delete mode 100644 src/modules/license/LicenseWidget.cpp delete mode 100644 src/modules/license/LicenseWidget.h delete mode 100644 src/modules/license/README.md delete mode 100644 src/modules/license/license.conf delete mode 100644 src/modules/license/license.schema.yaml delete mode 100644 src/modules/localeq/CMakeLists.txt delete mode 100644 src/modules/localeq/LocaleQmlViewStep.cpp delete mode 100644 src/modules/localeq/LocaleQmlViewStep.h delete mode 100644 src/modules/localeq/Map-qt6.qml delete mode 100644 src/modules/localeq/Map.qml delete mode 100644 src/modules/localeq/Offline-qt6.qml delete mode 100644 src/modules/localeq/Offline.qml delete mode 100755 src/modules/localeq/img/locale.svg delete mode 100644 src/modules/localeq/img/locale.svg.license delete mode 100644 src/modules/localeq/img/minus.png delete mode 100644 src/modules/localeq/img/minus.png.license delete mode 100644 src/modules/localeq/img/pin.svg delete mode 100644 src/modules/localeq/img/pin.svg.license delete mode 100644 src/modules/localeq/img/plus.png delete mode 100644 src/modules/localeq/img/plus.png.license delete mode 100644 src/modules/localeq/localeq-qt6.qml delete mode 100644 src/modules/localeq/localeq-qt6.qrc delete mode 100644 src/modules/localeq/localeq.conf delete mode 100644 src/modules/localeq/localeq.qml delete mode 100644 src/modules/localeq/localeq.qrc delete mode 100644 src/modules/luksbootkeyfile/CMakeLists.txt delete mode 100644 src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp delete mode 100644 src/modules/luksbootkeyfile/LuksBootKeyFileJob.h delete mode 100644 src/modules/luksbootkeyfile/Tests.cpp delete mode 100644 src/modules/luksbootkeyfile/luksbootkeyfile.conf delete mode 100644 src/modules/luksbootkeyfile/luksbootkeyfile.schema.yaml delete mode 100644 src/modules/luksopenswaphookcfg/CMakeLists.txt delete mode 100644 src/modules/luksopenswaphookcfg/LOSHInfo.h delete mode 100644 src/modules/luksopenswaphookcfg/LOSHJob.cpp delete mode 100644 src/modules/luksopenswaphookcfg/LOSHJob.h delete mode 100644 src/modules/luksopenswaphookcfg/Tests.cpp delete mode 100644 src/modules/luksopenswaphookcfg/luksopenswaphookcfg.conf delete mode 100644 src/modules/luksopenswaphookcfg/luksopenswaphookcfg.schema.yaml delete mode 100644 src/modules/machineid/CMakeLists.txt delete mode 100644 src/modules/machineid/MachineIdJob.cpp delete mode 100644 src/modules/machineid/MachineIdJob.h delete mode 100644 src/modules/machineid/Tests.cpp delete mode 100644 src/modules/machineid/Workers.cpp delete mode 100644 src/modules/machineid/Workers.h delete mode 100644 src/modules/machineid/machineid.conf delete mode 100644 src/modules/machineid/machineid.schema.yaml delete mode 100644 src/modules/mkinitfs/main.py delete mode 100644 src/modules/mkinitfs/module.desc delete mode 100644 src/modules/mount/main.py delete mode 100644 src/modules/mount/module.desc delete mode 100644 src/modules/mount/mount.conf delete mode 100644 src/modules/mount/mount.schema.yaml delete mode 100644 src/modules/mount/tests/1.global delete mode 100644 src/modules/mount/tests/1.job delete mode 100644 src/modules/mount/tests/2.global delete mode 100644 src/modules/mount/tests/2.job delete mode 100644 src/modules/mount/tests/3.global delete mode 100644 src/modules/mount/tests/3.job delete mode 100644 src/modules/mount/tests/4.global delete mode 100644 src/modules/mount/tests/4.job delete mode 100644 src/modules/networkcfg/main.py delete mode 100644 src/modules/networkcfg/module.desc delete mode 100644 src/modules/oemid/CMakeLists.txt delete mode 100644 src/modules/oemid/IDJob.cpp delete mode 100644 src/modules/oemid/IDJob.h delete mode 100644 src/modules/oemid/OEMPage.ui delete mode 100644 src/modules/oemid/OEMViewStep.cpp delete mode 100644 src/modules/oemid/OEMViewStep.h delete mode 100644 src/modules/oemid/oemid.conf delete mode 100644 src/modules/openrcdmcryptcfg/main.py delete mode 100644 src/modules/openrcdmcryptcfg/module.desc delete mode 100644 src/modules/openrcdmcryptcfg/openrcdmcryptcfg.conf delete mode 100644 src/modules/partition/CMakeLists.txt delete mode 100644 src/modules/partition/Config.cpp delete mode 100644 src/modules/partition/Config.h delete mode 100644 src/modules/partition/PartitionViewStep.cpp delete mode 100644 src/modules/partition/PartitionViewStep.h delete mode 100644 src/modules/partition/README.md delete mode 100644 src/modules/partition/core/BootLoaderModel.cpp delete mode 100644 src/modules/partition/core/BootLoaderModel.h delete mode 100644 src/modules/partition/core/ColorUtils.cpp delete mode 100644 src/modules/partition/core/ColorUtils.h delete mode 100644 src/modules/partition/core/DeviceList.cpp delete mode 100644 src/modules/partition/core/DeviceList.h delete mode 100644 src/modules/partition/core/DeviceModel.cpp delete mode 100644 src/modules/partition/core/DeviceModel.h delete mode 100644 src/modules/partition/core/KPMHelpers.cpp delete mode 100644 src/modules/partition/core/KPMHelpers.h delete mode 100644 src/modules/partition/core/OsproberEntry.h delete mode 100644 src/modules/partition/core/PartUtils.cpp delete mode 100644 src/modules/partition/core/PartUtils.h delete mode 100644 src/modules/partition/core/PartitionActions.cpp delete mode 100644 src/modules/partition/core/PartitionActions.h delete mode 100644 src/modules/partition/core/PartitionCoreModule.cpp delete mode 100644 src/modules/partition/core/PartitionCoreModule.h delete mode 100644 src/modules/partition/core/PartitionInfo.cpp delete mode 100644 src/modules/partition/core/PartitionInfo.h delete mode 100644 src/modules/partition/core/PartitionLayout.cpp delete mode 100644 src/modules/partition/core/PartitionLayout.h delete mode 100644 src/modules/partition/core/PartitionModel.cpp delete mode 100644 src/modules/partition/core/PartitionModel.h delete mode 100644 src/modules/partition/core/SizeUtils.h delete mode 100644 src/modules/partition/gui/BootInfoWidget.cpp delete mode 100644 src/modules/partition/gui/BootInfoWidget.h delete mode 100644 src/modules/partition/gui/ChoicePage.cpp delete mode 100644 src/modules/partition/gui/ChoicePage.h delete mode 100644 src/modules/partition/gui/ChoicePage.ui delete mode 100644 src/modules/partition/gui/CreatePartitionDialog.cpp delete mode 100644 src/modules/partition/gui/CreatePartitionDialog.h delete mode 100644 src/modules/partition/gui/CreatePartitionDialog.ui delete mode 100644 src/modules/partition/gui/CreatePartitionTableDialog.ui delete mode 100644 src/modules/partition/gui/CreateVolumeGroupDialog.cpp delete mode 100644 src/modules/partition/gui/CreateVolumeGroupDialog.h delete mode 100644 src/modules/partition/gui/DeviceInfoWidget.cpp delete mode 100644 src/modules/partition/gui/DeviceInfoWidget.h delete mode 100644 src/modules/partition/gui/EditExistingPartitionDialog.cpp delete mode 100644 src/modules/partition/gui/EditExistingPartitionDialog.h delete mode 100644 src/modules/partition/gui/EditExistingPartitionDialog.ui delete mode 100644 src/modules/partition/gui/EncryptWidget.cpp delete mode 100644 src/modules/partition/gui/EncryptWidget.h delete mode 100644 src/modules/partition/gui/EncryptWidget.ui delete mode 100644 src/modules/partition/gui/ListPhysicalVolumeWidgetItem.cpp delete mode 100644 src/modules/partition/gui/ListPhysicalVolumeWidgetItem.h delete mode 100644 src/modules/partition/gui/PartitionBarsView.cpp delete mode 100644 src/modules/partition/gui/PartitionBarsView.h delete mode 100644 src/modules/partition/gui/PartitionDialogHelpers.cpp delete mode 100644 src/modules/partition/gui/PartitionDialogHelpers.h delete mode 100644 src/modules/partition/gui/PartitionLabelsView.cpp delete mode 100644 src/modules/partition/gui/PartitionLabelsView.h delete mode 100644 src/modules/partition/gui/PartitionPage.cpp delete mode 100644 src/modules/partition/gui/PartitionPage.h delete mode 100644 src/modules/partition/gui/PartitionPage.ui delete mode 100644 src/modules/partition/gui/PartitionSizeController.cpp delete mode 100644 src/modules/partition/gui/PartitionSizeController.h delete mode 100644 src/modules/partition/gui/PartitionSplitterWidget.cpp delete mode 100644 src/modules/partition/gui/PartitionSplitterWidget.h delete mode 100644 src/modules/partition/gui/PartitionViewSelectionFilter.h delete mode 100644 src/modules/partition/gui/ResizeVolumeGroupDialog.cpp delete mode 100644 src/modules/partition/gui/ResizeVolumeGroupDialog.h delete mode 100644 src/modules/partition/gui/ScanningDialog.cpp delete mode 100644 src/modules/partition/gui/ScanningDialog.h delete mode 100644 src/modules/partition/gui/VolumeGroupBaseDialog.cpp delete mode 100644 src/modules/partition/gui/VolumeGroupBaseDialog.h delete mode 100644 src/modules/partition/gui/VolumeGroupBaseDialog.ui delete mode 100644 src/modules/partition/jobs/AutoMountManagementJob.cpp delete mode 100644 src/modules/partition/jobs/AutoMountManagementJob.h delete mode 100644 src/modules/partition/jobs/ChangeFilesystemLabelJob.cpp delete mode 100644 src/modules/partition/jobs/ChangeFilesystemLabelJob.h delete mode 100644 src/modules/partition/jobs/ClearMountsJob.cpp delete mode 100644 src/modules/partition/jobs/ClearMountsJob.h delete mode 100644 src/modules/partition/jobs/ClearTempMountsJob.cpp delete mode 100644 src/modules/partition/jobs/ClearTempMountsJob.h delete mode 100644 src/modules/partition/jobs/CreatePartitionJob.cpp delete mode 100644 src/modules/partition/jobs/CreatePartitionJob.h delete mode 100644 src/modules/partition/jobs/CreatePartitionTableJob.cpp delete mode 100644 src/modules/partition/jobs/CreatePartitionTableJob.h delete mode 100644 src/modules/partition/jobs/CreateVolumeGroupJob.cpp delete mode 100644 src/modules/partition/jobs/CreateVolumeGroupJob.h delete mode 100644 src/modules/partition/jobs/DeactivateVolumeGroupJob.cpp delete mode 100644 src/modules/partition/jobs/DeactivateVolumeGroupJob.h delete mode 100644 src/modules/partition/jobs/DeletePartitionJob.cpp delete mode 100644 src/modules/partition/jobs/DeletePartitionJob.h delete mode 100644 src/modules/partition/jobs/FillGlobalStorageJob.cpp delete mode 100644 src/modules/partition/jobs/FillGlobalStorageJob.h delete mode 100644 src/modules/partition/jobs/FormatPartitionJob.cpp delete mode 100644 src/modules/partition/jobs/FormatPartitionJob.h delete mode 100644 src/modules/partition/jobs/PartitionJob.cpp delete mode 100644 src/modules/partition/jobs/PartitionJob.h delete mode 100644 src/modules/partition/jobs/RemoveVolumeGroupJob.cpp delete mode 100644 src/modules/partition/jobs/RemoveVolumeGroupJob.h delete mode 100644 src/modules/partition/jobs/ResizePartitionJob.cpp delete mode 100644 src/modules/partition/jobs/ResizePartitionJob.h delete mode 100644 src/modules/partition/jobs/ResizeVolumeGroupJob.cpp delete mode 100644 src/modules/partition/jobs/ResizeVolumeGroupJob.h delete mode 100644 src/modules/partition/jobs/SetPartitionFlagsJob.cpp delete mode 100644 src/modules/partition/jobs/SetPartitionFlagsJob.h delete mode 100644 src/modules/partition/partition.conf delete mode 100644 src/modules/partition/partition.schema.yaml delete mode 100644 src/modules/partition/tests/1a-legacy.conf delete mode 100644 src/modules/partition/tests/1b-legacy.conf delete mode 100644 src/modules/partition/tests/2a-legacy.conf delete mode 100644 src/modules/partition/tests/2b-modern.conf delete mode 100644 src/modules/partition/tests/2c-mixed.conf delete mode 100644 src/modules/partition/tests/2d-overlap.conf delete mode 100644 src/modules/partition/tests/3a-min-too-large.conf delete mode 100644 src/modules/partition/tests/AutoMountTests.cpp delete mode 100644 src/modules/partition/tests/CMakeLists.txt delete mode 100644 src/modules/partition/tests/ClearMountsJobTests.cpp delete mode 100644 src/modules/partition/tests/ClearMountsJobTests.h delete mode 100644 src/modules/partition/tests/ConfigTests.cpp delete mode 100644 src/modules/partition/tests/CreateLayoutsTests.cpp delete mode 100644 src/modules/partition/tests/CreateLayoutsTests.h delete mode 100644 src/modules/partition/tests/DevicesTests.cpp delete mode 100644 src/modules/partition/tests/PartitionJobTests.cpp delete mode 100644 src/modules/partition/tests/PartitionJobTests.h delete mode 100644 src/modules/plasmalnf/CMakeLists.txt delete mode 100644 src/modules/plasmalnf/Config.cpp delete mode 100644 src/modules/plasmalnf/Config.h delete mode 100644 src/modules/plasmalnf/PlasmaLnfJob.cpp delete mode 100644 src/modules/plasmalnf/PlasmaLnfJob.h delete mode 100644 src/modules/plasmalnf/PlasmaLnfPage.cpp delete mode 100644 src/modules/plasmalnf/PlasmaLnfPage.h delete mode 100644 src/modules/plasmalnf/PlasmaLnfViewStep.cpp delete mode 100644 src/modules/plasmalnf/PlasmaLnfViewStep.h delete mode 100644 src/modules/plasmalnf/ThemeInfo.cpp delete mode 100644 src/modules/plasmalnf/ThemeInfo.h delete mode 100644 src/modules/plasmalnf/page_plasmalnf.qrc delete mode 100644 src/modules/plasmalnf/page_plasmalnf.ui delete mode 100644 src/modules/plasmalnf/plasmalnf.conf delete mode 100644 src/modules/plasmalnf/view-preview.png delete mode 100644 src/modules/plasmalnf/view-preview.png.license delete mode 100644 src/modules/plasmalnf/view-preview.svg delete mode 100644 src/modules/plasmalnf/view-preview.svg.license delete mode 100644 src/modules/plymouthcfg/main.py delete mode 100644 src/modules/plymouthcfg/module.desc delete mode 100644 src/modules/plymouthcfg/plymouthcfg.conf delete mode 100644 src/modules/plymouthcfg/plymouthcfg.schema.yaml delete mode 100644 src/modules/preservefiles/CMakeLists.txt delete mode 100644 src/modules/preservefiles/Item.cpp delete mode 100644 src/modules/preservefiles/Item.h delete mode 100644 src/modules/preservefiles/PreserveFiles.cpp delete mode 100644 src/modules/preservefiles/PreserveFiles.h delete mode 100644 src/modules/preservefiles/Tests.cpp delete mode 100644 src/modules/preservefiles/preservefiles.conf delete mode 100644 src/modules/preservefiles/preservefiles.schema.yaml delete mode 100644 src/modules/preservefiles/tests/1a-log.conf delete mode 100644 src/modules/preservefiles/tests/1b-config.conf delete mode 100644 src/modules/preservefiles/tests/1c-src.conf delete mode 100644 src/modules/preservefiles/tests/1d-filename.conf delete mode 100644 src/modules/preservefiles/tests/1e-empty.conf delete mode 100644 src/modules/preservefiles/tests/1f-bad.conf delete mode 100644 src/modules/rawfs/main.py delete mode 100644 src/modules/rawfs/module.desc delete mode 100644 src/modules/rawfs/rawfs.conf delete mode 100644 src/modules/rawfs/tests/1.global delete mode 100644 src/modules/rawfs/tests/1.job delete mode 100644 src/modules/rawfs/tests/CMakeTests.txt delete mode 100644 src/modules/removeuser/CMakeLists.txt delete mode 100644 src/modules/removeuser/RemoveUserJob.cpp delete mode 100644 src/modules/removeuser/RemoveUserJob.h delete mode 100644 src/modules/removeuser/removeuser.conf delete mode 100644 src/modules/removeuser/removeuser.schema.yaml delete mode 100644 src/modules/services-openrc/main.py delete mode 100644 src/modules/services-openrc/module.desc delete mode 100644 src/modules/services-openrc/services-openrc.conf delete mode 100644 src/modules/services-systemd/main.py delete mode 100644 src/modules/services-systemd/module.desc delete mode 100644 src/modules/services-systemd/services-systemd.conf delete mode 100644 src/modules/services-systemd/services-systemd.schema.yaml delete mode 100644 src/modules/summary/CMakeLists.txt delete mode 100644 src/modules/summary/Config.cpp delete mode 100644 src/modules/summary/Config.h delete mode 100644 src/modules/summary/SummaryModel.cpp delete mode 100644 src/modules/summary/SummaryModel.h delete mode 100644 src/modules/summary/SummaryPage.cpp delete mode 100644 src/modules/summary/SummaryPage.h delete mode 100644 src/modules/summary/SummaryViewStep.cpp delete mode 100644 src/modules/summary/SummaryViewStep.h delete mode 100644 src/modules/summaryq/CMakeLists.txt delete mode 100644 src/modules/summaryq/SummaryQmlViewStep.cpp delete mode 100644 src/modules/summaryq/SummaryQmlViewStep.h delete mode 100644 src/modules/summaryq/img/keyboard.svg delete mode 100644 src/modules/summaryq/img/keyboard.svg.license delete mode 100644 src/modules/summaryq/img/lokalize.svg delete mode 100644 src/modules/summaryq/img/lokalize.svg.license delete mode 100644 src/modules/summaryq/summaryq-qt6.qml delete mode 100644 src/modules/summaryq/summaryq-qt6.qrc delete mode 100644 src/modules/summaryq/summaryq.qml delete mode 100644 src/modules/summaryq/summaryq.qrc delete mode 100644 src/modules/tracking/CMakeLists.txt delete mode 100644 src/modules/tracking/Config.cpp delete mode 100644 src/modules/tracking/Config.h delete mode 100644 src/modules/tracking/Tests.cpp delete mode 100644 src/modules/tracking/TrackingJobs.cpp delete mode 100644 src/modules/tracking/TrackingJobs.h delete mode 100644 src/modules/tracking/TrackingPage.cpp delete mode 100644 src/modules/tracking/TrackingPage.h delete mode 100644 src/modules/tracking/TrackingType.h delete mode 100644 src/modules/tracking/TrackingViewStep.cpp delete mode 100644 src/modules/tracking/TrackingViewStep.h delete mode 100644 src/modules/tracking/level-install.svg delete mode 100644 src/modules/tracking/level-install.svg.license delete mode 100644 src/modules/tracking/level-machine.svg delete mode 100644 src/modules/tracking/level-machine.svg.license delete mode 100644 src/modules/tracking/level-none.svg delete mode 100644 src/modules/tracking/level-none.svg.license delete mode 100644 src/modules/tracking/level-user.svg delete mode 100644 src/modules/tracking/level-user.svg.license delete mode 100644 src/modules/tracking/page_trackingstep.qrc delete mode 100644 src/modules/tracking/page_trackingstep.ui delete mode 100644 src/modules/tracking/tracking.conf delete mode 100644 src/modules/umount/CMakeLists.txt delete mode 100644 src/modules/umount/Tests.cpp delete mode 100644 src/modules/umount/UmountJob.cpp delete mode 100644 src/modules/umount/UmountJob.h delete mode 100644 src/modules/umount/umount.conf delete mode 100644 src/modules/umount/umount.schema.yaml delete mode 100644 src/modules/unpackfs/main.py delete mode 100644 src/modules/unpackfs/module.desc delete mode 100644 src/modules/unpackfs/runtests.sh delete mode 100644 src/modules/unpackfs/tests/1.global delete mode 100644 src/modules/unpackfs/tests/2.global delete mode 100644 src/modules/unpackfs/tests/3.global delete mode 100644 src/modules/unpackfs/tests/3.job delete mode 100644 src/modules/unpackfs/tests/4.global delete mode 100644 src/modules/unpackfs/tests/4.job delete mode 100644 src/modules/unpackfs/tests/5.global delete mode 100644 src/modules/unpackfs/tests/5.job delete mode 100644 src/modules/unpackfs/tests/6.global delete mode 100644 src/modules/unpackfs/tests/6.job delete mode 100644 src/modules/unpackfs/tests/7.global delete mode 100644 src/modules/unpackfs/tests/7.job delete mode 100644 src/modules/unpackfs/tests/8.global delete mode 100644 src/modules/unpackfs/tests/8.job delete mode 100644 src/modules/unpackfs/tests/9.global delete mode 100644 src/modules/unpackfs/tests/9.job delete mode 100644 src/modules/unpackfs/unpackfs.conf delete mode 100644 src/modules/unpackfs/unpackfs.schema.yaml delete mode 100644 src/modules/users/CMakeLists.txt delete mode 100644 src/modules/users/CheckPWQuality.cpp delete mode 100644 src/modules/users/CheckPWQuality.h delete mode 100644 src/modules/users/Config.cpp delete mode 100644 src/modules/users/Config.h delete mode 100644 src/modules/users/CreateUserJob.cpp delete mode 100644 src/modules/users/CreateUserJob.h delete mode 100644 src/modules/users/MiscJobs.cpp delete mode 100644 src/modules/users/MiscJobs.h delete mode 100644 src/modules/users/SetHostNameJob.cpp delete mode 100644 src/modules/users/SetHostNameJob.h delete mode 100644 src/modules/users/SetPasswordJob.cpp delete mode 100644 src/modules/users/SetPasswordJob.h delete mode 100644 src/modules/users/TestGroupInformation.cpp delete mode 100644 src/modules/users/TestPasswordJob.cpp delete mode 100644 src/modules/users/TestSetHostNameJob.cpp delete mode 100644 src/modules/users/Tests.cpp delete mode 100644 src/modules/users/UsersPage.cpp delete mode 100644 src/modules/users/UsersPage.h delete mode 100644 src/modules/users/UsersViewStep.cpp delete mode 100644 src/modules/users/UsersViewStep.h delete mode 100644 src/modules/users/images/invalid.png delete mode 100644 src/modules/users/images/invalid.png.license delete mode 100644 src/modules/users/images/valid.png delete mode 100644 src/modules/users/images/valid.png.license delete mode 100644 src/modules/users/page_usersetup.ui delete mode 100644 src/modules/users/tests/3-wing.conf delete mode 100644 src/modules/users/tests/4-audio.conf delete mode 100644 src/modules/users/tests/5-issue-1523.conf delete mode 100644 src/modules/users/tests/6a-issue-1672.conf delete mode 100644 src/modules/users/tests/6b-issue-1672.conf delete mode 100644 src/modules/users/tests/6c-issue-1672.conf delete mode 100644 src/modules/users/tests/6d-issue-1672.conf delete mode 100644 src/modules/users/tests/6e-issue-1672.conf delete mode 100644 src/modules/users/tests/7an-shell.conf delete mode 100644 src/modules/users/tests/7ao-shell.conf delete mode 100644 src/modules/users/tests/7bn-shell.conf delete mode 100644 src/modules/users/tests/7bo-shell.conf delete mode 100644 src/modules/users/tests/7cn-shell.conf delete mode 100644 src/modules/users/tests/7co-shell.conf delete mode 100644 src/modules/users/tests/7dn-shell.conf delete mode 100644 src/modules/users/tests/7do-shell.conf delete mode 100644 src/modules/users/tests/7en-shell.conf delete mode 100644 src/modules/users/tests/7eo-shell.conf delete mode 100644 src/modules/users/tests/7fb-shell.conf delete mode 100644 src/modules/users/tests/7fn-shell.conf delete mode 100644 src/modules/users/tests/7fo-shell.conf delete mode 100644 src/modules/users/users.conf delete mode 100644 src/modules/users/users.qrc delete mode 100644 src/modules/users/users.schema.yaml delete mode 100644 src/modules/usersq/CMakeLists.txt delete mode 100644 src/modules/usersq/UsersQmlViewStep.cpp delete mode 100644 src/modules/usersq/UsersQmlViewStep.h delete mode 100644 src/modules/usersq/usersq-qt6.qml delete mode 100644 src/modules/usersq/usersq-qt6.qrc delete mode 100644 src/modules/usersq/usersq.conf delete mode 100644 src/modules/usersq/usersq.qml delete mode 100644 src/modules/usersq/usersq.qrc delete mode 100644 src/modules/welcomeq/CMakeLists.txt delete mode 100644 src/modules/welcomeq/Recommended.qml delete mode 100644 src/modules/welcomeq/Requirements.qml delete mode 100644 src/modules/welcomeq/WelcomeQmlViewStep.cpp delete mode 100644 src/modules/welcomeq/WelcomeQmlViewStep.h delete mode 100644 src/modules/welcomeq/img/chevron-left-solid.svg delete mode 100644 src/modules/welcomeq/img/chevron-left-solid.svg.license delete mode 100644 src/modules/welcomeq/img/language-icon-48px.png delete mode 100644 src/modules/welcomeq/img/language-icon-48px.png.license delete mode 100644 src/modules/welcomeq/img/squid.png delete mode 100644 src/modules/welcomeq/img/squid.png.license delete mode 100644 src/modules/welcomeq/release_notes.qml delete mode 100644 src/modules/welcomeq/welcomeq-qt6.qml delete mode 100644 src/modules/welcomeq/welcomeq-qt6.qrc delete mode 100644 src/modules/welcomeq/welcomeq.conf delete mode 100644 src/modules/welcomeq/welcomeq.qml delete mode 100644 src/modules/welcomeq/welcomeq.qrc delete mode 100644 src/modules/zfs/CMakeLists.txt delete mode 100644 src/modules/zfs/README.md delete mode 100644 src/modules/zfs/ZfsJob.cpp delete mode 100644 src/modules/zfs/ZfsJob.h delete mode 100644 src/modules/zfs/zfs.conf delete mode 100644 src/modules/zfs/zfs.schema.yaml delete mode 100644 src/modules/zfshostid/main.py delete mode 100644 src/modules/zfshostid/module.desc delete mode 100644 src/modules/zfshostid/zfshostid.schema.yaml diff --git a/src/modules/bootloader/bootloader.conf b/src/modules/bootloader/bootloader.conf deleted file mode 100644 index 9679f6696c..0000000000 --- a/src/modules/bootloader/bootloader.conf +++ /dev/null @@ -1,83 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Bootloader configuration. The bootloader is installed to allow -# the system to start (and pick one of the installed operating -# systems to run). -# -# Take note that Debian-derivatives that use unmodified GRUB EFI packages -# should specifically set *efiBootloaderId* to "debian" because that is -# hard-coded in `grubx64.efi`. ---- -# A variable from global storage which overrides the value of efiBootLoader -#efiBootLoaderVar: "packagechooser_bootloader" - -# Define which bootloader you want to use for EFI installations -# Possible options are 'grub', 'sb-shim', 'refind` and 'systemd-boot'. -efiBootLoader: "grub" - -# systemd-boot configuration files settings - -# kernelSearchPath is the path relative to the root of the install to search for kernels -# A kernel is identified by finding files which match regular expression, kernelPattern -kernelSearchPath: "/usr/lib/modules" -kernelPattern: "^vmlinuz.*" - -# loaderEntries is an array of options to add to loader.conf for systemd-boot -# please note that the "default" option is added programmatically -loaderEntries: - - "timeout 5" - - "console-mode keep" - -# systemd-boot and refind support custom kernel params -kernelParams: [ "quiet" ] - -# A list of kernel names that refind should accept as kernels -#refindKernelList: [ "linux","linux-lts","linux-zen","linux-hardened" ] - -# GRUB 2 binary names and boot directory -# Some distributions (e.g. Fedora) use grub2-* (resp. /boot/grub2/) names. -# These names are also used when using sb-shim, since that needs some -# GRUB functionality (notably grub-probe) to work. As needed, you may use -# complete paths like `/usr/bin/efibootmgr` for the executables. -# -grubInstall: "grub-install" -grubMkconfig: "grub-mkconfig" -grubCfg: "/boot/grub/grub.cfg" -grubProbe: "grub-probe" -efiBootMgr: "efibootmgr" - -# Optionally set the bootloader ID to use for EFI. This is passed to -# grub-install --bootloader-id. -# -# If not set here, the value from bootloaderEntryName from branding.desc -# is used, with problematic characters (space and slash) replaced. -# -# The ID is also used as a directory name within the EFI environment, -# and the bootloader is copied from /boot/efi/EFI// . When -# setting the option here, keep in mind that the name is sanitized -# (problematic characters, see above, are replaced). -# -# There are some special words possible at the end of *efiBootloaderId*: -# ${SERIAL} can be used to obtain a uniquely-numbered suffix -# that is added to the Id (yielding, e.g., `dirname1` or `dirname72`) -# ${RANDOM} can be used to obtain a unique 4-digit hex suffix -# ${PHRASE} can be used to obtain a unique 1-to-3-word suffix -# from a dictionary of space-themed words -# These words must be at the **end** of the *efiBootloaderId* value. -# There must also be at most one of them. If there is none, no suffix- -# processing is done and the *efiBootloaderId* is used unchanged. -# -# NOTE: Debian derivatives that use the unmodified Debian GRUB EFI -# packages may need to set this to "debian" because that is -# hard-coded in `grubx64.efi`. -# -# efiBootloaderId: "dirname" - -# Optionally install a copy of the GRUB EFI bootloader as the EFI -# fallback loader (either bootia32.efi or bootx64.efi depending on -# the system). This may be needed on certain systems (Intel DH87MC -# seems to be the only one). If you set this to false, take care -# to add another module to optionally install the fallback on those -# boards that need it. -installEFIFallback: true diff --git a/src/modules/bootloader/bootloader.schema.yaml b/src/modules/bootloader/bootloader.schema.yaml deleted file mode 100644 index 2b01bae956..0000000000 --- a/src/modules/bootloader/bootloader.schema.yaml +++ /dev/null @@ -1,26 +0,0 @@ -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later ---- -$schema: https://json-schema.org/schema# -$id: https://calamares.io/schemas/bootloader -additionalProperties: false -type: object -properties: - efiBootLoaderVar: { type: string } - efiBootLoader: { type: string } - kernelSearchPath: { type: string } - kernelName: { type: string } - kernelParams: { type: array, items: { type: string } } - kernelPattern: { type: string } - loaderEntries: { type: array, items: { type: string } } - refindKernelList: { type: array, items: { type: string } } - - # Programs - grubInstall: { type: string } - grubMkconfig: { type: string } - grubCfg: { type: string } - grubProbe: { type: string } - efiBootMgr: { type: string } - - efiBootloaderId: { type: string } - installEFIFallback: { type: boolean } diff --git a/src/modules/bootloader/main.py b/src/modules/bootloader/main.py deleted file mode 100644 index 1899028396..0000000000 --- a/src/modules/bootloader/main.py +++ /dev/null @@ -1,931 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2014 Aurélien Gâteau -# SPDX-FileCopyrightText: 2014 Anke Boersma -# SPDX-FileCopyrightText: 2014 Daniel Hillenbrand -# SPDX-FileCopyrightText: 2014 Benjamin Vaudour -# SPDX-FileCopyrightText: 2014-2019 Kevin Kofler -# SPDX-FileCopyrightText: 2015-2018 Philip Mueller -# SPDX-FileCopyrightText: 2016-2017 Teo Mrnjavac -# SPDX-FileCopyrightText: 2017 Alf Gaida -# SPDX-FileCopyrightText: 2017-2019 Adriaan de Groot -# SPDX-FileCopyrightText: 2017 Gabriel Craciunescu -# SPDX-FileCopyrightText: 2017 Ben Green -# SPDX-FileCopyrightText: 2021 Neal Gompa -# SPDX-License-Identifier: GPL-3.0-or-later -# -# Calamares is Free Software: see the License-Identifier above. -# - -import fileinput -import os -import re -import shutil -import subprocess - -import libcalamares - -from libcalamares.utils import check_target_env_call - -import gettext - -_ = gettext.translation("calamares-python", - localedir=libcalamares.utils.gettext_path(), - languages=libcalamares.utils.gettext_languages(), - fallback=True).gettext - -# This is the sanitizer used all over to tidy up filenames -# to make identifiers (or to clean up names to make filenames). -file_name_sanitizer = str.maketrans(" /()", "_-__") - - -def pretty_name(): - return _("Install bootloader.") - - -def get_uuid(): - """ - Checks and passes 'uuid' to other routine. - - :return: - """ - partitions = libcalamares.globalstorage.value("partitions") - - for partition in partitions: - if partition["mountPoint"] == "/": - libcalamares.utils.debug("Root partition uuid: \"{!s}\"".format(partition["uuid"])) - return partition["uuid"] - - return "" - - -def get_kernel_line(kernel_type): - """ - Passes 'kernel_line' to other routine based on configuration file. - - :param kernel_type: - :return: - """ - if kernel_type == "fallback": - if "fallbackKernelLine" in libcalamares.job.configuration: - return libcalamares.job.configuration["fallbackKernelLine"] - else: - return " (fallback)" - else: - if "kernelLine" in libcalamares.job.configuration: - return libcalamares.job.configuration["kernelLine"] - else: - return "" - - -def get_zfs_root(): - """ - Looks in global storage to find the zfs root - - :return: A string containing the path to the zfs root or None if it is not found - """ - - zfs = libcalamares.globalstorage.value("zfsDatasets") - - if not zfs: - libcalamares.utils.warning("Failed to locate zfs dataset list") - return None - - # Find the root dataset - for dataset in zfs: - try: - if dataset["mountpoint"] == "/": - return dataset["zpool"] + "/" + dataset["dsName"] - except KeyError: - # This should be impossible - libcalamares.utils.warning("Internal error handling zfs dataset") - raise - - return None - - -def is_btrfs_root(partition): - """ Returns True if the partition object refers to a btrfs root filesystem - - :param partition: A partition map from global storage - :return: True if btrfs and root, False otherwise - """ - return partition["mountPoint"] == "/" and partition["fs"] == "btrfs" - - -def is_zfs_root(partition): - """ Returns True if the partition object refers to a zfs root filesystem - - :param partition: A partition map from global storage - :return: True if zfs and root, False otherwise - """ - return partition["mountPoint"] == "/" and partition["fs"] == "zfs" - - -def get_kernel_params(uuid): - kernel_params = libcalamares.job.configuration.get("kernelParams", ["quiet"]) - kernel_params.append("rw") - - partitions = libcalamares.globalstorage.value("partitions") - swap_uuid = "" - swap_outer_mappername = None - swap_outer_uuid = None - - cryptdevice_params = [] - - has_dracut = libcalamares.utils.target_env_call(["sh", "-c", "which dracut"]) == 0 - uses_systemd_hook = libcalamares.utils.target_env_call(["sh", "-c", - "grep -q \"^HOOKS.*systemd\" /etc/mkinitcpio.conf"]) == 0 - use_systemd_naming = has_dracut or uses_systemd_hook - - - # Take over swap settings: - # - unencrypted swap partition sets swap_uuid - # - encrypted root sets cryptdevice_params - for partition in partitions: - if partition["fs"] == "linuxswap" and not partition.get("claimed", None): - # Skip foreign swap - continue - has_luks = "luksMapperName" in partition - if partition["fs"] == "linuxswap" and not has_luks: - swap_uuid = partition["uuid"] - - if partition["fs"] == "linuxswap" and has_luks: - swap_outer_mappername = partition["luksMapperName"] - swap_outer_uuid = partition["luksUuid"] - - if partition["mountPoint"] == "/" and has_luks: - if use_systemd_naming: - cryptdevice_params = [f"rd.luks.uuid={partition['luksUuid']}"] - else: - cryptdevice_params = [f"cryptdevice=UUID={partition['luksUuid']}:{partition['luksMapperName']}"] - cryptdevice_params.append(f"root=/dev/mapper/{partition['luksMapperName']}") - - # btrfs and zfs handling - for partition in partitions: - # If a btrfs root subvolume wasn't set, it means the root is directly on the partition - # and this option isn't needed - if is_btrfs_root(partition): - btrfs_root_subvolume = libcalamares.globalstorage.value("btrfsRootSubvolume") - if btrfs_root_subvolume: - kernel_params.append("rootflags=subvol=" + btrfs_root_subvolume) - - # zfs needs to be told the location of the root dataset - if is_zfs_root(partition): - zfs_root_path = get_zfs_root() - if zfs_root_path is not None: - kernel_params.append("root=ZFS=" + zfs_root_path) - else: - # Something is really broken if we get to this point - libcalamares.utils.warning("Internal error handling zfs dataset") - raise Exception("Internal zfs data missing, please contact your distribution") - - if cryptdevice_params: - kernel_params.extend(cryptdevice_params) - else: - kernel_params.append("root=UUID={!s}".format(uuid)) - - if swap_uuid: - kernel_params.append("resume=UUID={!s}".format(swap_uuid)) - - if use_systemd_naming and swap_outer_uuid: - kernel_params.append(f"rd.luks.uuid={swap_outer_uuid}") - - if swap_outer_mappername: - kernel_params.append(f"resume=/dev/mapper/{swap_outer_mappername}") - - return kernel_params - - -def create_systemd_boot_conf(installation_root_path, efi_dir, uuid, kernel, kernel_version): - """ - Creates systemd-boot configuration files based on given parameters. - - :param installation_root_path: A string containing the absolute path to the root of the installation - :param efi_dir: A string containing the path to the efi dir relative to the root of the installation - :param uuid: A string containing the UUID of the root volume - :param kernel: A string containing the path to the kernel relative to the root of the installation - :param kernel_version: The kernel version string - """ - - # Get the kernel params and write them to /etc/kernel/cmdline - # This file is used by kernel-install - kernel_params = " ".join(get_kernel_params(uuid)) - kernel_cmdline_path = os.path.join(installation_root_path, "etc", "kernel") - os.makedirs(kernel_cmdline_path, exist_ok=True) - with open(os.path.join(kernel_cmdline_path, "cmdline"), "w") as cmdline_file: - cmdline_file.write(kernel_params) - - libcalamares.utils.debug(f"Configuring kernel version {kernel_version}") - - # get the machine-id - with open(os.path.join(installation_root_path, "etc", "machine-id"), 'r') as machineid_file: - machine_id = machineid_file.read().rstrip('\n') - - # Ensure the directory exists - machine_dir = os.path.join(installation_root_path + efi_dir, machine_id) - os.makedirs(machine_dir, exist_ok=True) - - # Call kernel-install for each kernel - libcalamares.utils.target_env_process_output(["kernel-install", - "add", - kernel_version, - os.path.join("/", kernel)]) - - -def create_loader(loader_path, installation_root_path): - """ - Writes configuration for loader. - - :param loader_path: The absolute path to the loader.conf file - :param installation_root_path: The path to the root of the target installation - """ - - # get the machine-id - with open(os.path.join(installation_root_path, "etc", "machine-id"), 'r') as machineid_file: - machine_id = machineid_file.read().rstrip('\n') - - try: - loader_entries = libcalamares.job.configuration["loaderEntries"] - except KeyError: - libcalamares.utils.debug("No aditional loader entries found in config") - loader_entries = [] - pass - - lines = [f"default {machine_id}*"] - - lines.extend(loader_entries) - - with open(loader_path, 'w') as loader_file: - for line in lines: - loader_file.write(line + "\n") - - -class SuffixIterator(object): - """ - Wrapper for one of the "generator" classes below to behave like - a proper Python iterator. The iterator is initialized with a - maximum number of attempts to generate a new suffix. - """ - - def __init__(self, attempts, generator): - self.generator = generator - self.attempts = attempts - self.counter = 0 - - def __iter__(self): - return self - - def __next__(self): - self.counter += 1 - if self.counter <= self.attempts: - return self.generator.next() - raise StopIteration - - -class serialEfi(object): - """ - EFI Id generator that appends a serial number to the given name. - """ - - def __init__(self, name): - self.name = name - # So the first call to next() will bump it to 0 - self.counter = -1 - - def next(self): - self.counter += 1 - if self.counter > 0: - return "{!s}{!s}".format(self.name, self.counter) - else: - return self.name - - -def render_in_base(value, base_values, length=-1): - """ - Renders @p value in base-N, where N is the number of - items in @p base_values. When rendering, use the items - of @p base_values (e.g. use "0123456789" to get regular decimal - rendering, or "ABCDEFGHIJ" for letters-as-numbers 'encoding'). - - If length is positive, pads out to at least that long with - leading "zeroes", whatever base_values[0] is. - """ - if value < 0: - raise ValueError("Cannot render negative values") - if len(base_values) < 2: - raise ValueError("Insufficient items for base-N rendering") - if length < 1: - length = 1 - digits = [] - base = len(base_values) - while value > 0: - place = value % base - value = value // base - digits.append(base_values[place]) - while len(digits) < length: - digits.append(base_values[0]) - return "".join(reversed(digits)) - - -class randomEfi(object): - """ - EFI Id generator that appends a random 4-digit hex number to the given name. - """ - - def __init__(self, name): - self.name = name - # So the first call to next() will bump it to 0 - self.counter = -1 - - def next(self): - self.counter += 1 - if self.counter > 0: - import random - v = random.randint(0, 65535) # 16 bits - return "{!s}{!s}".format(self.name, render_in_base(v, "0123456789ABCDEF", 4)) - else: - return self.name - - -class phraseEfi(object): - """ - EFI Id generator that appends a random phrase to the given name. - """ - words = ("Sun", "Moon", "Mars", "Soyuz", "Falcon", "Kuaizhou", "Gaganyaan") - - def __init__(self, name): - self.name = name - # So the first call to next() will bump it to 0 - self.counter = -1 - - def next(self): - self.counter += 1 - if self.counter > 0: - import random - desired_length = 1 + self.counter // 5 - v = random.randint(0, len(self.words) ** desired_length) - return "{!s}{!s}".format(self.name, render_in_base(v, self.words)) - else: - return self.name - - -def get_efi_suffix_generator(name): - """ - Handle EFI bootloader Ids with ${} for suffix-processing. - """ - if "${" not in name: - raise ValueError("Misplaced call to get_efi_suffix_generator, no ${}") - if not name.endswith("}"): - raise ValueError("Misplaced call to get_efi_suffix_generator, no trailing ${}") - if name.count("${") > 1: - raise ValueError("EFI ID {!r} contains multiple generators".format(name)) - import re - prefix, generator_name = re.match("(.*)\${([^}]*)}$", name).groups() - if generator_name not in ("SERIAL", "RANDOM", "PHRASE"): - raise ValueError("EFI suffix {!r} is unknown".format(generator_name)) - - generator = None - if generator_name == "SERIAL": - generator = serialEfi(prefix) - elif generator_name == "RANDOM": - generator = randomEfi(prefix) - elif generator_name == "PHRASE": - generator = phraseEfi(prefix) - if generator is None: - raise ValueError("EFI suffix {!r} is unsupported".format(generator_name)) - - return generator - - -def change_efi_suffix(efi_directory, bootloader_id): - """ - Returns a label based on @p bootloader_id that is usable within - @p efi_directory. If there is a ${} suffix marker - in the given id, tries to generate a unique label. - """ - if bootloader_id.endswith("}") and "${" in bootloader_id: - # Do 10 attempts with any suffix generator - g = SuffixIterator(10, get_efi_suffix_generator(bootloader_id)) - else: - # Just one attempt - g = [bootloader_id] - - for candidate_name in g: - if not os.path.exists(os.path.join(efi_directory, candidate_name)): - return candidate_name - return bootloader_id - - -def efi_label(efi_directory): - """ - Returns a sanitized label, possibly unique, that can be - used within @p efi_directory. - """ - if "efiBootloaderId" in libcalamares.job.configuration: - efi_bootloader_id = change_efi_suffix(efi_directory, libcalamares.job.configuration["efiBootloaderId"]) - else: - branding = libcalamares.globalstorage.value("branding") - efi_bootloader_id = branding["bootloaderEntryName"] - - return efi_bootloader_id.translate(file_name_sanitizer) - - -def efi_word_size(): - # get bitness of the underlying UEFI - try: - sysfile = open("/sys/firmware/efi/fw_platform_size", "r") - efi_bitness = sysfile.read(2) - except Exception: - # if the kernel is older than 4.0, the UEFI bitness likely isn't - # exposed to the userspace so we assume a 64 bit UEFI here - efi_bitness = "64" - return efi_bitness - - -def efi_boot_next(): - """ - Tell EFI to definitely boot into the just-installed - system next time. - """ - boot_mgr = libcalamares.job.configuration["efiBootMgr"] - boot_entry = None - efi_bootvars = subprocess.check_output([boot_mgr], universal_newlines=True) - for line in efi_bootvars.split('\n'): - if not line: - continue - words = line.split() - if len(words) >= 2 and words[0] == "BootOrder:": - boot_entry = words[1].split(',')[0] - break - if boot_entry: - subprocess.call([boot_mgr, "-n", boot_entry]) - - -def get_kernels(installation_root_path): - """ - Gets a list of kernels and associated values for each kernel. This will work as is for many distros. - If not, it should be safe to modify it to better support your distro - - :param installation_root_path: A string with the absolute path to the root of the installation - - Returns a list of 3-tuples - - Each 3-tuple contains the kernel, kernel_type and kernel_version - """ - try: - kernel_search_path = libcalamares.job.configuration["kernelSearchPath"] - except KeyError: - libcalamares.utils.warning("No kernel pattern found in configuration, using '/usr/lib/modules'") - kernel_search_path = "/usr/lib/modules" - pass - - kernel_list = [] - - try: - kernel_pattern = libcalamares.job.configuration["kernelPattern"] - except KeyError: - libcalamares.utils.warning("No kernel pattern found in configuration, using 'vmlinuz'") - kernel_pattern = "vmlinuz" - pass - - # find all the installed kernels - for root, dirs, files in os.walk(os.path.join(installation_root_path, kernel_search_path.lstrip('/'))): - for file in files: - if re.search(kernel_pattern, file): - rel_root = os.path.relpath(root, installation_root_path) - kernel_list.append((os.path.join(rel_root, file), "default", os.path.basename(root))) - - return kernel_list - - -def install_clr_boot_manager(): - """ - Installs clr-boot-manager as the bootloader for EFI systems - """ - libcalamares.utils.debug("Bootloader: clr-boot-manager") - - installation_root_path = libcalamares.globalstorage.value("rootMountPoint") - kernel_config_path = os.path.join(installation_root_path, "etc", "kernel") - os.makedirs(kernel_config_path, exist_ok=True) - cmdline_path = os.path.join(kernel_config_path, "cmdline") - - # Get the kernel params - uuid = get_uuid() - kernel_params = " ".join(get_kernel_params(uuid)) - - # Write out the cmdline file for clr-boot-manager - with open(cmdline_path, "w") as cmdline_file: - cmdline_file.write(kernel_params) - - check_target_env_call(["clr-boot-manager", "update"]) - - -def install_systemd_boot(efi_directory): - """ - Installs systemd-boot as bootloader for EFI setups. - - :param efi_directory: - """ - libcalamares.utils.debug("Bootloader: systemd-boot") - installation_root_path = libcalamares.globalstorage.value("rootMountPoint") - install_efi_directory = installation_root_path + efi_directory - uuid = get_uuid() - loader_path = os.path.join(install_efi_directory, - "loader", - "loader.conf") - subprocess.call(["bootctl", - "--path={!s}".format(install_efi_directory), - "install"]) - - for (kernel, kernel_type, kernel_version) in get_kernels(installation_root_path): - create_systemd_boot_conf(installation_root_path, - efi_directory, - uuid, - kernel, - kernel_version) - - create_loader(loader_path, installation_root_path) - - -def get_grub_efi_parameters(): - """ - Returns a 3-tuple of suitable parameters for GRUB EFI installation, - depending on the host machine architecture. The return is - - target name - - grub.efi name - - boot.efi name - all three are strings. May return None if there is no suitable - set for the current machine. May return unsuitable values if the - host architecture is unknown (e.g. defaults to x86_64). - """ - import platform - efi_bitness = efi_word_size() - cpu_type = platform.machine() - - if efi_bitness == "32": - # Assume all 32-bitters are legacy x86 - return "i386-efi", "grubia32.efi", "bootia32.efi" - elif efi_bitness == "64" and cpu_type == "aarch64": - return "arm64-efi", "grubaa64.efi", "bootaa64.efi" - elif efi_bitness == "64" and cpu_type == "loongarch64": - return "loongarch64-efi", "grubloongarch64.efi", "bootloongarch64.efi" - elif efi_bitness == "64": - # If it's not ARM, must by AMD64 - return "x86_64-efi", "grubx64.efi", "bootx64.efi" - libcalamares.utils.warning( - "Could not find GRUB parameters for bits {b} and cpu {c}".format(b=repr(efi_bitness), c=repr(cpu_type))) - return None - - -def run_grub_mkconfig(partitions, output_file): - """ - Runs grub-mkconfig in the target environment - - :param partitions: The partitions list from global storage - :param output_file: A string containing the path to the generating grub config file - :return: - """ - - # zfs needs an environment variable set for grub-mkconfig - if any([is_zfs_root(partition) for partition in partitions]): - check_target_env_call(["sh", "-c", "ZPOOL_VDEV_NAME_PATH=1 " + - libcalamares.job.configuration["grubMkconfig"] + " -o " + output_file]) - else: - # The input file /etc/default/grub should already be filled out by the - # grubcfg job module. - check_target_env_call([libcalamares.job.configuration["grubMkconfig"], "-o", output_file]) - - -def run_grub_install(fw_type, partitions, efi_directory): - """ - Runs grub-install in the target environment - - :param fw_type: A string which is "efi" for UEFI installs. Any other value results in a BIOS install - :param partitions: The partitions list from global storage - :param efi_directory: The path of the efi directory relative to the root of the install - :return: - """ - - is_zfs = any([is_zfs_root(partition) for partition in partitions]) - - # zfs needs an environment variable set for grub - if is_zfs: - check_target_env_call(["sh", "-c", "echo ZPOOL_VDEV_NAME_PATH=1 >> /etc/environment"]) - - if fw_type == "efi": - assert efi_directory is not None - efi_bootloader_id = efi_label(efi_directory) - efi_target, efi_grub_file, efi_boot_file = get_grub_efi_parameters() - - if is_zfs: - check_target_env_call(["sh", "-c", "ZPOOL_VDEV_NAME_PATH=1 " + libcalamares.job.configuration["grubInstall"] - + " --target=" + efi_target + " --efi-directory=" + efi_directory - + " --bootloader-id=" + efi_bootloader_id + " --force"]) - else: - check_target_env_call([libcalamares.job.configuration["grubInstall"], - "--target=" + efi_target, - "--efi-directory=" + efi_directory, - "--bootloader-id=" + efi_bootloader_id, - "--force"]) - else: - assert efi_directory is None - if libcalamares.globalstorage.value("bootLoader") is None: - return - - boot_loader = libcalamares.globalstorage.value("bootLoader") - if boot_loader["installPath"] is None: - return - - if is_zfs: - check_target_env_call(["sh", "-c", "ZPOOL_VDEV_NAME_PATH=1 " - + libcalamares.job.configuration["grubInstall"] - + " --target=i386-pc --recheck --force " - + boot_loader["installPath"]]) - else: - check_target_env_call([libcalamares.job.configuration["grubInstall"], - "--target=i386-pc", - "--recheck", - "--force", - boot_loader["installPath"]]) - - -def install_grub(efi_directory, fw_type): - """ - Installs grub as bootloader, either in pc or efi mode. - - :param efi_directory: - :param fw_type: - """ - # get the partition from global storage - partitions = libcalamares.globalstorage.value("partitions") - if not partitions: - libcalamares.utils.warning(_("Failed to install grub, no partitions defined in global storage")) - return - - if fw_type == "efi": - libcalamares.utils.debug("Bootloader: grub (efi)") - installation_root_path = libcalamares.globalstorage.value("rootMountPoint") - install_efi_directory = installation_root_path + efi_directory - - if not os.path.isdir(install_efi_directory): - os.makedirs(install_efi_directory) - - efi_bootloader_id = efi_label(efi_directory) - - efi_target, efi_grub_file, efi_boot_file = get_grub_efi_parameters() - - run_grub_install(fw_type, partitions, efi_directory) - - # VFAT is weird, see issue CAL-385 - install_efi_directory_firmware = (vfat_correct_case( - install_efi_directory, - "EFI")) - if not os.path.exists(install_efi_directory_firmware): - os.makedirs(install_efi_directory_firmware) - - # there might be several values for the boot directory - # most usual they are boot, Boot, BOOT - - install_efi_boot_directory = (vfat_correct_case( - install_efi_directory_firmware, - "boot")) - if not os.path.exists(install_efi_boot_directory): - os.makedirs(install_efi_boot_directory) - - # Workaround for some UEFI firmwares - fallback = "installEFIFallback" - libcalamares.utils.debug("UEFI Fallback: " + str(libcalamares.job.configuration.get(fallback, ""))) - if libcalamares.job.configuration.get(fallback, True): - libcalamares.utils.debug(" .. installing '{!s}' fallback firmware".format(efi_boot_file)) - efi_file_source = os.path.join(install_efi_directory_firmware, - efi_bootloader_id, - efi_grub_file) - efi_file_target = os.path.join(install_efi_boot_directory, efi_boot_file) - - shutil.copy2(efi_file_source, efi_file_target) - else: - libcalamares.utils.debug("Bootloader: grub (bios)") - run_grub_install(fw_type, partitions, None) - - run_grub_mkconfig(partitions, libcalamares.job.configuration["grubCfg"]) - - -def install_secureboot(efi_directory): - """ - Installs the secureboot shim in the system by calling efibootmgr. - """ - efi_bootloader_id = efi_label(efi_directory) - - installation_root_path = libcalamares.globalstorage.value("rootMountPoint") - install_efi_directory = installation_root_path + efi_directory - - if efi_word_size() == "64": - install_efi_bin = "shimx64.efi" - elif efi_word_size() == "32": - install_efi_bin = "shimia32.efi" - else: - libcalamares.utils.warning(f"Unknown efi word size of {efi_word_size()} found") - return None - - # Copied, roughly, from openSUSE's install script, - # and pythonified. *disk* is something like /dev/sda, - # while *drive* may return "(disk/dev/sda,gpt1)" .. - # we're interested in the numbers in the second part - # of that tuple. - efi_drive = subprocess.check_output([ - libcalamares.job.configuration["grubProbe"], - "-t", "drive", "--device-map=", install_efi_directory]).decode("ascii") - efi_disk = subprocess.check_output([ - libcalamares.job.configuration["grubProbe"], - "-t", "disk", "--device-map=", install_efi_directory]).decode("ascii") - - efi_drive_partition = efi_drive.replace("(", "").replace(")", "").split(",")[1] - # Get the first run of digits from the partition - efi_partition_number = None - c = 0 - start = None - while c < len(efi_drive_partition): - if efi_drive_partition[c].isdigit() and start is None: - start = c - if not efi_drive_partition[c].isdigit() and start is not None: - efi_partition_number = efi_drive_partition[start:c] - break - c += 1 - if efi_partition_number is None: - raise ValueError("No partition number found for %s" % install_efi_directory) - - subprocess.call([ - libcalamares.job.configuration["efiBootMgr"], - "-c", - "-w", - "-L", efi_bootloader_id, - "-d", efi_disk, - "-p", efi_partition_number, - "-l", install_efi_directory + "/" + install_efi_bin]) - - efi_boot_next() - - # The input file /etc/default/grub should already be filled out by the - # grubcfg job module. - check_target_env_call([libcalamares.job.configuration["grubMkconfig"], - "-o", os.path.join(efi_directory, "EFI", - efi_bootloader_id, "grub.cfg")]) - - -def vfat_correct_case(parent, name): - for candidate in os.listdir(parent): - if name.lower() == candidate.lower(): - return os.path.join(parent, candidate) - return os.path.join(parent, name) - - -def efi_partitions(efi_boot_path): - """ - The (one) partition mounted on @p efi_boot_path, or an empty list. - """ - return [p for p in libcalamares.globalstorage.value("partitions") if p["mountPoint"] == efi_boot_path] - - -def update_refind_config(efi_directory, installation_root_path): - """ - :param efi_directory: The path to the efi directory relative to the root - :param installation_root_path: The path to the root of the installation - """ - try: - kernel_list = libcalamares.job.configuration["refindKernelList"] - except KeyError: - libcalamares.utils.warning('refindKernelList not set. Skipping updating refind.conf') - return - - # Update the config in the file - for line in fileinput.input(installation_root_path + efi_directory + "/EFI/refind/refind.conf", inplace=True): - line = line.strip() - if line.startswith("#extra_kernel_version_strings") or line.startswith("extra_kernel_version_strings"): - line = line.lstrip("#") - for kernel in kernel_list: - if kernel not in line: - line += "," + kernel - print(line) - - -def install_refind(efi_directory): - try: - installation_root_path = libcalamares.globalstorage.value("rootMountPoint") - except KeyError: - libcalamares.utils.warning('Global storage value "rootMountPoint" missing') - - install_efi_directory = installation_root_path + efi_directory - uuid = get_uuid() - kernel_params = " ".join(get_kernel_params(uuid)) - conf_path = os.path.join(installation_root_path, "boot/refind_linux.conf") - - check_target_env_call(["refind-install"]) - - with open(conf_path, "r") as refind_file: - filedata = [x.strip() for x in refind_file.readlines()] - - with open(conf_path, 'w') as refind_file: - for line in filedata: - if line.startswith('"Boot with standard options"'): - line = f'"Boot with standard options" "{kernel_params}"' - elif line.startswith('"Boot to single-user mode"'): - line = f'"Boot to single-user mode" "{kernel_params}" single' - refind_file.write(line + "\n") - - update_refind_config(efi_directory, installation_root_path) - - -def prepare_bootloader(fw_type): - """ - Prepares bootloader. - Based on value 'efi_boot_loader', it either calls systemd-boot - or grub to be installed. - - :param fw_type: - :return: - """ - - # Get the boot loader selection from global storage if it is set in the config file - try: - gs_name = libcalamares.job.configuration["efiBootLoaderVar"] - if libcalamares.globalstorage.contains(gs_name): - efi_boot_loader = libcalamares.globalstorage.value(gs_name) - else: - libcalamares.utils.warning( - f"Specified global storage value not found in global storage") - return None - except KeyError: - # If the conf value for using global storage is not set, use the setting from the config file. - try: - efi_boot_loader = libcalamares.job.configuration["efiBootLoader"] - except KeyError: - if fw_type == "efi": - libcalamares.utils.warning("Configuration missing both efiBootLoader and efiBootLoaderVar on an EFI " - "system, bootloader not installed") - return - else: - pass - - # If the user has selected not to install bootloader, bail out here - if efi_boot_loader.casefold() == "none": - libcalamares.utils.debug("Skipping bootloader installation since no bootloader was selected") - return None - - efi_directory = libcalamares.globalstorage.value("efiSystemPartition") - - if efi_boot_loader == "clr-boot-manager": - if fw_type != "efi": - # Grub has to be installed first on non-EFI systems - install_grub(efi_directory, fw_type) - install_clr_boot_manager() - elif efi_boot_loader == "systemd-boot" and fw_type == "efi": - install_systemd_boot(efi_directory) - elif efi_boot_loader == "sb-shim" and fw_type == "efi": - install_secureboot(efi_directory) - elif efi_boot_loader == "refind" and fw_type == "efi": - install_refind(efi_directory) - elif efi_boot_loader == "grub" or fw_type != "efi": - install_grub(efi_directory, fw_type) - else: - libcalamares.utils.debug("WARNING: the combination of " - "boot-loader '{!s}' and firmware '{!s}' " - "is not supported.".format(efi_boot_loader, fw_type)) - - -def run(): - """ - Starts procedure and passes 'fw_type' to other routine. - - :return: - """ - - fw_type = libcalamares.globalstorage.value("firmwareType") - - if libcalamares.globalstorage.value("bootLoader") is None and fw_type != "efi": - libcalamares.utils.warning("Non-EFI system, and no bootloader is set.") - return None - - partitions = libcalamares.globalstorage.value("partitions") - if fw_type == "efi": - efi_system_partition = libcalamares.globalstorage.value("efiSystemPartition") - esp_found = [p for p in partitions if p["mountPoint"] == efi_system_partition] - if not esp_found: - libcalamares.utils.warning("EFI system, but nothing mounted on {!s}".format(efi_system_partition)) - return None - - try: - prepare_bootloader(fw_type) - except subprocess.CalledProcessError as e: - libcalamares.utils.warning(str(e)) - libcalamares.utils.debug("stdout:" + str(e.stdout)) - libcalamares.utils.debug("stderr:" + str(e.stderr)) - return (_("Bootloader installation error"), - _("The bootloader could not be installed. The installation command
{!s}
returned error " - "code {!s}.") - .format(e.cmd, e.returncode)) - - return None diff --git a/src/modules/bootloader/module.desc b/src/modules/bootloader/module.desc deleted file mode 100644 index 44a1c0ee56..0000000000 --- a/src/modules/bootloader/module.desc +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -type: "job" -interface: "python" -name: "bootloader" -script: "main.py" -# The partition module sets up the EFI firmware type -# global key, which is used to decide how to install. -requiredModules: [ "partition" ] diff --git a/src/modules/bootloader/test.yaml b/src/modules/bootloader/test.yaml deleted file mode 100644 index 4623b55f7d..0000000000 --- a/src/modules/bootloader/test.yaml +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -rootMountPoint: /tmp/mount -bootLoader: - installPath: /dev/sdb -branding: - shortProductName: "Generic Distro" diff --git a/src/modules/bootloader/tests/CMakeTests.txt b/src/modules/bootloader/tests/CMakeTests.txt deleted file mode 100644 index e13529258d..0000000000 --- a/src/modules/bootloader/tests/CMakeTests.txt +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# We have tests to exercise some of the module internals. -# Those tests conventionally live in Python files here in the tests/ directory. Add them. -add_test( - NAME test-bootloader-efiname - COMMAND env PYTHONPATH=.: python3 ${CMAKE_CURRENT_LIST_DIR}/test-bootloader-efiname.py - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} -) diff --git a/src/modules/bootloader/tests/test-bootloader-efiname.py b/src/modules/bootloader/tests/test-bootloader-efiname.py deleted file mode 100644 index 4756fd7fd9..0000000000 --- a/src/modules/bootloader/tests/test-bootloader-efiname.py +++ /dev/null @@ -1,67 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Calamares Boilerplate -import libcalamares -libcalamares.globalstorage = libcalamares.GlobalStorage(None) -libcalamares.globalstorage.insert("testing", True) - -# Module prep-work -from src.modules.bootloader import main - -# Specific Bootloader test -g = main.get_efi_suffix_generator("derp${SERIAL}") -assert g is not None -assert g.next() == "derp" # First time, no suffix -for n in range(9): - print(g.next()) -# We called next() 10 times in total, starting from 0 -assert g.next() == "derp10" - -g = main.get_efi_suffix_generator("derp${RANDOM}") -assert g is not None -for n in range(10): - print(g.next()) -# it's random, nothing to assert - -g = main.get_efi_suffix_generator("derp${PHRASE}") -assert g is not None -for n in range(10): - print(g.next()) -# it's random, nothing to assert - -# Check invalid things -try: - g = main.get_efi_suffix_generator("derp") - raise TypeError("Shouldn't get generator (no indicator)") -except ValueError as e: - pass - -try: - g = main.get_efi_suffix_generator("derp${HEX}") - raise TypeError("Shouldn't get generator (unknown indicator)") -except ValueError as e: - pass - -try: - g = main.get_efi_suffix_generator("derp${SERIAL}x") - raise TypeError("Shouldn't get generator (trailing garbage)") -except ValueError as e: - pass - -try: - g = main.get_efi_suffix_generator("derp${SERIAL}${RANDOM}") - raise TypeError("Shouldn't get generator (multiple indicators)") -except ValueError as e: - pass - - -# Try the generator (assuming no calamares- test files exist in /tmp) -import os -assert "calamares-single" == main.change_efi_suffix("/tmp", "calamares-single") -assert "calamares-serial" == main.change_efi_suffix("/tmp", "calamares-serial${SERIAL}") -try: - os.makedirs("/tmp/calamares-serial", exist_ok=True) - assert "calamares-serial1" == main.change_efi_suffix("/tmp", "calamares-serial${SERIAL}") -finally: - os.rmdir("/tmp/calamares-serial") diff --git a/src/modules/displaymanager/displaymanager.conf b/src/modules/displaymanager/displaymanager.conf deleted file mode 100644 index d0a6a35919..0000000000 --- a/src/modules/displaymanager/displaymanager.conf +++ /dev/null @@ -1,80 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Configure one or more display managers (e.g. SDDM) -# with a "best effort" approach. -# -# This module also sets up autologin, if the feature is enabled in -# globalstorage (where it would come from the users page). ---- -# The DM module attempts to set up all the DMs found in this list, in the -# precise order listed. The displaymanagers list can also be set in -# globalstorage, and in that case it overrides the setting here. -# -# If *sysconfigSetup* is set to *true* (see below, only relevant for -# openSUSE derivatives) then this list is ignored and only sysconfig -# is attempted. You can also list "sysconfig" in this list instead. -# -displaymanagers: - - slim - - sddm - - lightdm - - gdm - - mdm - - lxdm - - greetd - -# Enable the following settings to force a desktop environment -# in your displaymanager configuration file. This will attempt -# to configure the given DE (without checking if it is installed). -# The DM configuration for each potential DM may **or may not** -# support configuring a default DE, so the keys are mandatory -# but their interpretation is up to the DM configuration. -# -# Subkeys of *defaultDesktopEnvironment* are (all mandatory): -# - *executable* a full path to an executable -# - *desktopFile* a .desktop filename -# -# If this is **not** set, then Calamares will look for installed -# DE's and pick the first one it finds that is actually installed. -# -# If this **is** set, and the *executable* key doesn't point to -# an installed file, then the .desktop file's TryExec key is -# used instead. -# - -#defaultDesktopEnvironment: -# executable: "startkde" -# desktopFile: "plasma" - -#If true, try to ensure that the user, group, /var directory etc. for the -#display manager are set up correctly. This is normally done by the distribution -#packages, and best left to them. Therefore, it is disabled by default. -basicSetup: false - -# If true, setup autologin for openSUSE. This only makes sense on openSUSE -# derivatives or other systems where /etc/sysconfig/displaymanager exists. -# -# The preferred way to pick sysconfig is to just list it in the -# *displaymanagers* list (as the only one). -# -sysconfigSetup: false - -# Some DMs have specific settings. These can be customized here. -# -# greetd has configurable user and group; the user and group is created if it -# does not exist, and the user is set as default-session user. -# -# Some greeters for greetd (e.g gtkgreet or regreet) have support for a user's GTK CSS style to change appearance. -# -# lightdm has a list of greeters to look for, preferring them in order if -# they are installed (if not, picks the alphabetically first greeter that is installed). -# -greetd: - greeter_user: "tom_bombadil" - greeter_group: "wheel" - greeter_css_location: "/etc/greetd/style.css" -lightdm: - preferred_greeters: ["lightdm-greeter.desktop", "slick-greeter.desktop"] -sddm: - configuration_file: "/etc/sddm.conf" diff --git a/src/modules/displaymanager/displaymanager.schema.yaml b/src/modules/displaymanager/displaymanager.schema.yaml deleted file mode 100644 index dcd2baa31e..0000000000 --- a/src/modules/displaymanager/displaymanager.schema.yaml +++ /dev/null @@ -1,39 +0,0 @@ -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later ---- -$schema: https://json-schema.org/schema# -$id: https://calamares.io/schemas/displaymanager -additionalProperties: false -type: object -properties: - displaymanagers: - type: array - items: - type: string - enum: [slim, sddm, lightdm, gdm, mdm, lxdm, greetd] - minItems: 1 # Must be non-empty, if present at all - defaultDesktopEnvironment: - type: object - properties: - executable: { type: string } - desktopFile: { type: string } - required: [ executable, desktopFile ] - basicSetup: { type: boolean, default: false } - sysconfigSetup: { type: boolean, default: false } - greetd: - type: object - properties: - greeter_user: { type: string } - greeter_group: { type: string } - greeter_css_location: { type: string } - additionalProperties: false - lightdm: - type: object - properties: - preferred_greeters: { type: array, items: { type: string } } - additionalProperties: false - sddm: - type: object - properties: - configuration_file: { type: string } - additionalProperties: false diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py deleted file mode 100644 index 7ec6af774f..0000000000 --- a/src/modules/displaymanager/main.py +++ /dev/null @@ -1,1030 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2014-2018 Philip Müller -# SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac -# SPDX-FileCopyrightText: 2014 Kevin Kofler -# SPDX-FileCopyrightText: 2017 Alf Gaida -# SPDX-FileCopyrightText: 2017 Bernhard Landauer -# SPDX-FileCopyrightText: 2017 2019, Adriaan de Groot -# SPDX-FileCopyrightText: 2019 Dominic Hayes -# SPDX-License-Identifier: GPL-3.0-or-later -# -# Calamares is Free Software: see the License-Identifier above. -# - -import abc -import os -import libcalamares - -from libcalamares.utils import gettext_path, gettext_languages - -import gettext -_translation = gettext.translation("calamares-python", - localedir=gettext_path(), - languages=gettext_languages(), - fallback=True) -_ = _translation.gettext -_n = _translation.ngettext - -class DesktopEnvironment: - """ - Desktop Environment -- some utility functions for a desktop - environment (e.g. finding out if it is installed). This - is independent of the *Display Manager*, which is what - we're configuring in this module. - """ - def __init__(self, exec, desktop): - self.executable = exec - self.desktop_file = desktop - - def _search_executable(self, root_mount_point, pathname): - """ - Search for @p pathname within @p root_mount_point . - If the pathname is absolute, just check there inside - the target, otherwise earch in a sort-of-sensible $PATH. - - Returns the full (including @p root_mount_point) path - to that executable, or None. - """ - if pathname.startswith("/"): - path = [""] - else: - path = ["/bin/", "/usr/bin/", "/sbin/", "/usr/local/bin/"] - - for p in path: - absolute_path = "{!s}{!s}{!s}".format(root_mount_point, p, pathname) - if os.path.exists(absolute_path): - return absolute_path - return None - - def _search_tryexec(self, root_mount_point, absolute_desktop_file): - """ - Check @p absolute_desktop_file for a TryExec line and, if that is - found, search for the command (executable pathname) within - @p root_mount_point. The .desktop file must live within the - target root. - - Returns the full (including @p root_mount_point) for the executable - from TryExec, or None. - """ - assert absolute_desktop_file.startswith(root_mount_point) - with open(absolute_desktop_file, "r") as f: - for tryexec_line in [x for x in f.readlines() if x.startswith("TryExec")]: - try: - key, value = tryexec_line.split("=") - if key.strip() == "TryExec": - return self._search_executable(root_mount_point, value.strip()) - except: - pass - return None - - def find_executable(self, root_mount_point): - """ - Returns the full path of the configured executable within @p root_mount_point, - or None if it isn't found. May search in a semi-sensible $PATH. - """ - return self._search_executable(root_mount_point, self.executable) - - def find_desktop_file(self, root_mount_point): - """ - Returns the full path of the .desktop file within @p root_mount_point, - or None if it isn't found. Searches both X11 and Wayland sessions. - """ - x11_sessions = "{!s}/usr/share/xsessions/{!s}.desktop".format(root_mount_point, self.desktop_file) - wayland_sessions = "{!s}/usr/share/wayland-sessions/{!s}.desktop".format(root_mount_point, self.desktop_file) - for candidate in (x11_sessions, wayland_sessions): - if os.path.exists(candidate): - return candidate - return None - - def is_installed(self, root_mount_point): - """ - Check if this environment is installed in the - target system at @p root_mount_point. - """ - desktop_file = self.find_desktop_file(root_mount_point) - if desktop_file is None: - return False - - return (self.find_executable(root_mount_point) is not None or - self._search_tryexec(root_mount_point, desktop_file) is not None) - - def update_from_desktop_file(self, root_mount_point): - """ - Find thie DE in the target system at @p root_mount_point. - This can update the *executable* configuration value if - the configured executable isn't found but the TryExec line - from the .desktop file is. - - The .desktop file is mandatory for a DE. - - Returns True if the DE is installed. - """ - desktop_file = self.find_desktop_file(root_mount_point) - if desktop_file is None: - return False - - executable_file = self.find_executable(root_mount_point) - if executable_file is not None: - # .desktop found and executable as well. - return True - - executable_file = self._search_tryexec(root_mount_point, desktop_file) - if executable_file is not None: - # Found from the .desktop file, so update own executable config - if root_mount_point and executable_file.startswith(root_mount_point): - executable_file = executable_file[len(root_mount_point):] - if not executable_file: - # Somehow chopped down to nothing - return False - - if executable_file[0] != "/": - executable_file = "/" + executable_file - self.executable = executable_file - return True - # This is to double-check - return self.is_installed(root_mount_point) - - -# This is the list of desktop environments that Calamares looks -# for; if no default environment is **explicitly** configured -# in the `displaymanager.conf` then the first one from this list -# that is found, is used. -# -# Each DE has a sample executable to look for, and a .desktop filename. -# If the executable exists, the DE is assumed to be installed -# and to use the given .desktop filename. -# -# If the .desktop file exists and contains a TryExec line and that -# TryExec executable exists (searched in /bin, /usr/bin, /sbin and -# /usr/local/bin) then the DE is assumed to be installed -# and to use that .desktop filename. -desktop_environments = [ - DesktopEnvironment('/usr/bin/startplasma-x11', 'plasma'), # KDE Plasma 5.17+ - DesktopEnvironment('/usr/bin/startkde', 'plasma'), # KDE Plasma 5 - DesktopEnvironment('/usr/bin/startkde', 'kde-plasma'), # KDE Plasma 4 - DesktopEnvironment( - '/usr/bin/budgie-desktop', 'budgie-desktop' # Budgie v10 - ), - DesktopEnvironment( - '/usr/bin/budgie-session', 'budgie-desktop' # Budgie v8 - ), - DesktopEnvironment('/usr/bin/gnome-session', 'gnome'), - DesktopEnvironment('/usr/bin/cinnamon-session-cinnamon', 'cinnamon'), - DesktopEnvironment('/usr/bin/mate-session', 'mate'), - DesktopEnvironment('/usr/bin/enlightenment_start', 'enlightenment'), - DesktopEnvironment('/usr/bin/lxsession', 'LXDE'), - DesktopEnvironment('/usr/bin/startlxde', 'LXDE'), - DesktopEnvironment('/usr/bin/lxqt-session', 'lxqt'), - DesktopEnvironment('/usr/bin/pekwm', 'pekwm'), - DesktopEnvironment('/usr/bin/pantheon-session', 'pantheon'), - DesktopEnvironment('/usr/bin/startdde', 'deepin'), - DesktopEnvironment('/usr/bin/startxfce4', 'xfce'), - DesktopEnvironment('/usr/bin/openbox-session', 'openbox'), - DesktopEnvironment('/usr/bin/i3', 'i3'), - DesktopEnvironment('/usr/bin/awesome', 'awesome'), - DesktopEnvironment('/usr/bin/bspwm', 'bspwm'), - DesktopEnvironment('/usr/bin/herbstluftwm', 'herbstluftwm'), - DesktopEnvironment('/usr/bin/qtile', 'qtile'), - DesktopEnvironment('/usr/bin/xmonad', 'xmonad'), - DesktopEnvironment('/usr/bin/dwm', 'dwm'), - DesktopEnvironment('/usr/bin/jwm', 'jwm'), - DesktopEnvironment('/usr/bin/icewm-session', 'icewm-session'), - DesktopEnvironment('/usr/bin/fvwm3', 'fvwm3'), - DesktopEnvironment('/usr/bin/sway', 'sway'), - DesktopEnvironment('/usr/bin/ukui-session', 'ukui'), - DesktopEnvironment('/usr/bin/cutefish-session', 'cutefish-xsession'), - DesktopEnvironment('/usr/bin/river', 'river'), - DesktopEnvironment('/usr/bin/Hyprland', 'hyprland'), -] - - -def find_desktop_environment(root_mount_point): - """ - Checks which desktop environment is currently installed. - - :param root_mount_point: - :return: - """ - libcalamares.utils.debug("Using rootMountPoint {!r}".format(root_mount_point)) - for desktop_environment in desktop_environments: - if desktop_environment.is_installed(root_mount_point): - libcalamares.utils.debug(".. selected DE {!s}".format(desktop_environment.desktop_file)) - return desktop_environment - return None - - -class DisplayManager(metaclass=abc.ABCMeta): - """ - Display Manager -- a base class for DM configuration. - """ - name = None - executable = None - - def __init__(self, root_mount_point): - self.root_mount_point = root_mount_point - - def have_dm(self): - """ - Is this DM installed in the target system? - The default implementation checks for `executable` - in the target system. - """ - if self.executable is None: - return False - - bin_path = "{!s}/usr/bin/{!s}".format(self.root_mount_point, self.executable) - sbin_path = "{!s}/usr/sbin/{!s}".format(self.root_mount_point, self.executable) - return os.path.exists(bin_path) or os.path.exists(sbin_path) - - # The four abstract methods below are called in the order listed here. - # They must all be implemented by subclasses, but not all of them - # actually do something for all DMs. - - @abc.abstractmethod - def basic_setup(self): - """ - Do basic setup (e.g. users, groups, directory creation) for this DM. - """ - # Some implementations do nothing - - @abc.abstractmethod - def desktop_environment_setup(self, desktop_environment): - """ - Configure the given @p desktop_environment as the default one, in - the configuration files for this DM. - """ - # Many implementations do nothing - - @abc.abstractmethod - def greeter_setup(self): - """ - Additional setup for the greeter. - """ - # Most implementations do nothing - - @abc.abstractmethod - def set_autologin(self, username, do_autologin, default_desktop_environment): - """ - Configure the DM inside the given @p root_mount_point with - autologin (if @p do_autologin is True) for the given @p username. - If the DM supports it, set the default DE to @p default_desktop_environment - as well. - """ - - -class DMmdm(DisplayManager): - name = "mdm" - executable = "mdm" - - def set_autologin(self, username, do_autologin, default_desktop_environment): - # Systems with MDM as Desktop Manager - mdm_conf_path = os.path.join(self.root_mount_point, "etc/mdm/custom.conf") - - if os.path.exists(mdm_conf_path): - with open(mdm_conf_path, 'r') as mdm_conf: - text = mdm_conf.readlines() - - with open(mdm_conf_path, 'w') as mdm_conf: - for line in text: - if 'AutomaticLogin=' in line: - line = "" - if 'AutomaticLoginEnable=True' in line: - line = "" - if '[daemon]' in line: - if do_autologin: - line = ( - "[daemon]\n" - "AutomaticLogin={!s}\n" - "AutomaticLoginEnable=True\n".format(username) - ) - else: - line = ( - "[daemon]\n" - "AutomaticLoginEnable=False\n" - ) - - mdm_conf.write(line) - else: - with open(mdm_conf_path, 'w') as mdm_conf: - mdm_conf.write( - '# Calamares - Configure automatic login for user\n' - ) - mdm_conf.write('[daemon]\n') - - if do_autologin: - mdm_conf.write("AutomaticLogin={!s}\n".format(username)) - mdm_conf.write('AutomaticLoginEnable=True\n') - else: - mdm_conf.write('AutomaticLoginEnable=False\n') - - def basic_setup(self): - if libcalamares.utils.target_env_call( - ['getent', 'group', 'mdm'] - ) != 0: - libcalamares.utils.target_env_call( - ['groupadd', '-g', '128', 'mdm'] - ) - - if libcalamares.utils.target_env_call( - ['getent', 'passwd', 'mdm'] - ) != 0: - libcalamares.utils.target_env_call( - ['useradd', - '-c', '"Linux Mint Display Manager"', - '-u', '128', - '-g', 'mdm', - '-d', '/var/lib/mdm', - '-s', '/usr/bin/nologin', - 'mdm' - ] - ) - - libcalamares.utils.target_env_call( - ['passwd', '-l', 'mdm'] - ) - libcalamares.utils.target_env_call( - ['chown', 'root:mdm', '/var/lib/mdm'] - ) - libcalamares.utils.target_env_call( - ['chmod', '1770', '/var/lib/mdm'] - ) - - def desktop_environment_setup(self, default_desktop_environment): - os.system( - "sed -i \"s|default.desktop|{!s}.desktop|g\" " - "{!s}/etc/mdm/custom.conf".format( - default_desktop_environment.desktop_file, - self.root_mount_point - ) - ) - - def greeter_setup(self): - pass - - -class DMgdm(DisplayManager): - name = "gdm" - executable = "gdm" - config = None # Set by have_dm() - - def have_dm(self): - """ - GDM exists with different executable names, so search - for one of them and use it. - """ - for executable, config in ( - ( "gdm", "etc/gdm/custom.conf" ), - ( "gdm3", "etc/gdm3/daemon.conf" ) - ): - bin_path = "{!s}/usr/bin/{!s}".format(self.root_mount_point, executable) - sbin_path = "{!s}/usr/sbin/{!s}".format(self.root_mount_point, executable) - if os.path.exists(bin_path) or os.path.exists(sbin_path): - # Keep the found-executable name around for later - self.executable = executable - self.config = config - return True - - return False - - def set_autologin(self, username, do_autologin, default_desktop_environment): - if self.config is None: - raise ValueError( "No config file for GDM has been set." ) - - # Systems with GDM as Desktop Manager - gdm_conf_path = os.path.join(self.root_mount_point, self.config) - - if os.path.exists(gdm_conf_path): - with open(gdm_conf_path, 'r') as gdm_conf: - text = gdm_conf.readlines() - - with open(gdm_conf_path, 'w') as gdm_conf: - for line in text: - if 'AutomaticLogin=' in line: - line = "" - if 'AutomaticLoginEnable=True' in line: - line = "" - if '[daemon]' in line: - if do_autologin: - line = ( - "[daemon]\n" - "AutomaticLogin={!s}\n" - "AutomaticLoginEnable=True\n".format(username) - ) - else: - line = "[daemon]\nAutomaticLoginEnable=False\n" - - gdm_conf.write(line) - else: - with open(gdm_conf_path, 'w') as gdm_conf: - gdm_conf.write( - '# Calamares - Enable automatic login for user\n' - ) - gdm_conf.write('[daemon]\n') - - if do_autologin: - gdm_conf.write("AutomaticLogin={!s}\n".format(username)) - gdm_conf.write('AutomaticLoginEnable=True\n') - else: - gdm_conf.write('AutomaticLoginEnable=False\n') - - if (do_autologin): - accountservice_dir = "{!s}/var/lib/AccountsService/users".format( - self.root_mount_point - ) - userfile_path = "{!s}/{!s}".format(accountservice_dir, username) - if os.path.exists(accountservice_dir): - with open(userfile_path, "w") as userfile: - userfile.write("[User]\n") - - if default_desktop_environment is not None: - userfile.write("XSession={!s}\n".format( - default_desktop_environment.desktop_file)) - - userfile.write("Icon=\n") - - def basic_setup(self): - if libcalamares.utils.target_env_call( - ['getent', 'group', 'gdm'] - ) != 0: - libcalamares.utils.target_env_call( - ['groupadd', '-g', '120', 'gdm'] - ) - - if libcalamares.utils.target_env_call( - ['getent', 'passwd', 'gdm'] - ) != 0: - libcalamares.utils.target_env_call( - ['useradd', - '-c', '"Gnome Display Manager"', - '-u', '120', - '-g', 'gdm', - '-d', '/var/lib/gdm', - '-s', '/usr/bin/nologin', - 'gdm' - ] - ) - - libcalamares.utils.target_env_call( - ['passwd', '-l', 'gdm'] - ) - libcalamares.utils.target_env_call( - ['chown', '-R', 'gdm:gdm', '/var/lib/gdm'] - ) - - def desktop_environment_setup(self, desktop_environment): - pass - - def greeter_setup(self): - pass - - -class DMlxdm(DisplayManager): - name = "lxdm" - executable = "lxdm" - - def set_autologin(self, username, do_autologin, default_desktop_environment): - # Systems with LXDM as Desktop Manager - lxdm_conf_path = os.path.join(self.root_mount_point, "etc/lxdm/lxdm.conf") - text = [] - - if os.path.exists(lxdm_conf_path): - with open(lxdm_conf_path, 'r') as lxdm_conf: - text = lxdm_conf.readlines() - - with open(lxdm_conf_path, 'w') as lxdm_conf: - for line in text: - if 'autologin=' in line: - if do_autologin: - line = "autologin={!s}\n".format(username) - else: - line = "# autologin=\n" - - lxdm_conf.write(line) - else: - return ( - _("Cannot write LXDM configuration file"), - _("LXDM config file {!s} does not exist").format(lxdm_conf_path) - ) - - def basic_setup(self): - if libcalamares.utils.target_env_call( - ['getent', 'group', 'lxdm'] - ) != 0: - libcalamares.utils.target_env_call( - ['groupadd', '--system', 'lxdm'] - ) - - libcalamares.utils.target_env_call( - ['chgrp', '-R', 'lxdm', '/var/lib/lxdm'] - ) - libcalamares.utils.target_env_call( - ['chgrp', 'lxdm', '/etc/lxdm/lxdm.conf'] - ) - libcalamares.utils.target_env_call( - ['chmod', '+r', '/etc/lxdm/lxdm.conf'] - ) - - def desktop_environment_setup(self, default_desktop_environment): - os.system( - "sed -i -e \"s|^.*session=.*|session={!s}|\" " - "{!s}/etc/lxdm/lxdm.conf".format( - default_desktop_environment.executable, - self.root_mount_point - ) - ) - - def greeter_setup(self): - pass - - -class DMlightdm(DisplayManager): - name = "lightdm" - executable = "lightdm" - - # Can be overridden in the .conf file. With no value it won't match any - # desktop file in the xgreeters directory and instead we end up picking - # the alphabetically first file there. - preferred_greeters = [] - - def set_autologin(self, username, do_autologin, default_desktop_environment): - # Systems with LightDM as Desktop Manager - # Ideally, we should use configparser for the ini conf file, - # but we just do a simple text replacement for now, as it - # worksforme(tm) - lightdm_conf_path = os.path.join( - self.root_mount_point, "etc/lightdm/lightdm.conf" - ) - text = [] - addseat = False - loopcount = 0 - - if os.path.exists(lightdm_conf_path): - with open(lightdm_conf_path, 'r') as lightdm_conf: - text = lightdm_conf.readlines() - # Check to make sure [SeatDefaults] or [Seat:*] is in the config, - # otherwise we'll risk malforming the config - addseat = '[SeatDefaults]' not in text and '[Seat:*]' not in text - - with open(lightdm_conf_path, 'w') as lightdm_conf: - if addseat: - # Prepend Seat line to start of file rather than leaving it without one - # This keeps the config from being malformed for LightDM - text = ["[Seat:*]\n"] + text - for line in text: - if 'autologin-user=' in line: - if do_autologin: - line = "autologin-user={!s}\n".format(username) - else: - line = "#autologin-user=\n" - - lightdm_conf.write(line) - else: - try: - # Create a new lightdm.conf file; this is documented to be - # read last, after everything in lightdm.conf.d/ - with open(lightdm_conf_path, 'w') as lightdm_conf: - if do_autologin: - lightdm_conf.write( - "[Seat:*]\nautologin-user={!s}\n".format(username)) - else: - lightdm_conf.write( - "[Seat:*]\n#autologin-user=\n") - except FileNotFoundError: - return ( - _("Cannot write LightDM configuration file"), - _("LightDM config file {!s} does not exist").format(lightdm_conf_path) - ) - - def basic_setup(self): - libcalamares.utils.target_env_call( - ['mkdir', '-p', '/run/lightdm'] - ) - - if libcalamares.utils.target_env_call( - ['getent', 'group', 'lightdm'] - ) != 0: - libcalamares.utils.target_env_call( - ['groupadd', '-g', '620', 'lightdm'] - ) - - if libcalamares.utils.target_env_call( - ['getent', 'passwd', 'lightdm'] - ) != 0: - libcalamares.utils.target_env_call( - ['useradd', '-c', - '"LightDM Display Manager"', - '-u', '620', - '-g', 'lightdm', - '-d', '/var/run/lightdm', - '-s', '/usr/bin/nologin', - 'lightdm' - ] - ) - - libcalamares.utils.target_env_call(['passwd', '-l', 'lightdm']) - libcalamares.utils.target_env_call(['chown', '-R', 'lightdm:lightdm', '/run/lightdm']) - libcalamares.utils.target_env_call(['chmod', '+r' '/etc/lightdm/lightdm.conf']) - - def desktop_environment_setup(self, default_desktop_environment): - os.system( - "sed -i -e \"s/^.*user-session=.*/user-session={!s}/\" " - "{!s}/etc/lightdm/lightdm.conf".format( - default_desktop_environment.desktop_file, - self.root_mount_point - ) - ) - - def find_preferred_greeter(self): - """ - On Debian, lightdm-greeter.desktop is typically a symlink managed - by update-alternatives pointing to /etc/alternatives/lightdm-greeter - which is also a symlink to a real .desktop file back in /usr/share/xgreeters/ - - Returns a path *into the mounted target* of the preferred greeter -- usually - a .desktop file that specifies where the actual executable is. May return - None to indicate nothing-was-found. - """ - greeters_dir = "usr/share/xgreeters" - greeters_target_path = os.path.join(self.root_mount_point, greeters_dir) - available_names = os.listdir(greeters_target_path) - available_names.sort() - desktop_names = [n for n in self.preferred_greeters if n in available_names] # Preferred ones - if desktop_names: - return desktop_names[0] - desktop_names = [n for n in available_names if n.endswith(".desktop")] # .. otherwise any .desktop - if desktop_names: - return desktop_names[0] - return None - - def greeter_setup(self): - lightdm_conf_path = os.path.join(self.root_mount_point, "etc/lightdm/lightdm.conf") - greeter_name = self.find_preferred_greeter() - - if greeter_name is not None: - greeter = os.path.basename(greeter_name) # Follow symlinks, hope they are not absolute - if greeter.endswith('.desktop'): - greeter = greeter[:-8] # Remove ".desktop" from end - - libcalamares.utils.debug("found greeter {!s}".format(greeter)) - os.system( - "sed -i -e \"s/^.*greeter-session=.*" - "/greeter-session={!s}/\" {!s}".format( - greeter, - lightdm_conf_path - ) - ) - libcalamares.utils.debug("{!s} configured as greeter.".format(greeter)) - else: - libcalamares.utils.error("No greeter found at all, preferred {!s}".format(self.preferred_greeters)) - return ( - _("Cannot configure LightDM"), - _("No LightDM greeter installed.") - ) - - -class DMslim(DisplayManager): - name = "slim" - executable = "slim" - - def set_autologin(self, username, do_autologin, default_desktop_environment): - # Systems with Slim as Desktop Manager - slim_conf_path = os.path.join(self.root_mount_point, "etc/slim.conf") - text = [] - - if os.path.exists(slim_conf_path): - with open(slim_conf_path, 'r') as slim_conf: - text = slim_conf.readlines() - - with open(slim_conf_path, 'w') as slim_conf: - for line in text: - if 'auto_login' in line: - if do_autologin: - line = 'auto_login yes\n' - else: - line = 'auto_login no\n' - - if do_autologin and 'default_user' in line: - line = "default_user {!s}\n".format(username) - - slim_conf.write(line) - else: - return ( - _("Cannot write SLIM configuration file"), - _("SLIM config file {!s} does not exist").format(slim_conf_path) - ) - - - def basic_setup(self): - pass - - def desktop_environment_setup(self, desktop_environment): - pass - - def greeter_setup(self): - pass - - -class DMsddm(DisplayManager): - name = "sddm" - executable = "sddm" - - configuration_file = "etc/sddm.conf" - - def set_autologin(self, username, do_autologin, default_desktop_environment): - import configparser - - # Systems with Sddm as Desktop Manager - sddm_conf_path = os.path.join(self.root_mount_point, self.configuration_file) - - sddm_config = configparser.ConfigParser(strict=False) - # Make everything case sensitive - sddm_config.optionxform = str - - if os.path.isfile(sddm_conf_path): - sddm_config.read(sddm_conf_path) - - if 'Autologin' not in sddm_config: - sddm_config.add_section('Autologin') - - if do_autologin: - sddm_config.set('Autologin', 'User', username) - elif sddm_config.has_option('Autologin', 'User'): - sddm_config.remove_option('Autologin', 'User') - - if default_desktop_environment is not None: - sddm_config.set( - 'Autologin', - 'Session', - default_desktop_environment.desktop_file - ) - - with open(sddm_conf_path, 'w') as sddm_config_file: - sddm_config.write(sddm_config_file, space_around_delimiters=False) - - - def basic_setup(self): - pass - - def desktop_environment_setup(self, desktop_environment): - pass - - def greeter_setup(self): - pass - - -class DMgreetd(DisplayManager): - name = "greetd" - executable = "greetd" - greeter_user = "greeter" - greeter_group = "greetd" - greeter_css_location = None - config_data = {} - - def os_path(self, path): - return os.path.join(self.root_mount_point, path) - - def config_path(self): - return self.os_path("etc/greetd/config.toml") - - def environments_path(self): - return self.os_path("etc/greetd/environments") - - def config_load(self): - import toml - - if (os.path.exists(self.config_path())): - with open(self.config_path(), "r") as f: - self.config_data = toml.load(f) - - self.config_data['terminal'] = dict(vt = "next") - - default_session_group = self.config_data.get('default_session', None) - if not default_session_group: - self.config_data['default_session'] = {} - - self.config_data['default_session']['user'] = self.greeter_user - - return self.config_data - - def config_write(self): - import toml - with open(self.config_path(), "w") as f: - toml.dump(self.config_data, f) - - def basic_setup(self): - if libcalamares.utils.target_env_call( - ['getent', 'group', self.greeter_group] - ) != 0: - libcalamares.utils.target_env_call( - ['groupadd', self.greeter_group] - ) - - if libcalamares.utils.target_env_call( - ['getent', 'passwd', self.greeter_user] - ) != 0: - libcalamares.utils.target_env_call( - ['useradd', - '-c', '"Greeter User"', - '-g', self.greeter_group, - '-s', '/bin/bash', - self.greeter_user - ] - ) - - def desktop_environment_setup(self, default_desktop_environment): - with open(self.environments_path(), 'w') as envs_file: - envs_file.write(default_desktop_environment.executable) - envs_file.write("\n") - - def greeter_setup(self): - pass - - def set_autologin(self, username, do_autologin, default_desktop_environment): - self.config_load() - - de_command = default_desktop_environment.executable - if os.path.exists(self.os_path("usr/bin/gtkgreet")) and os.path.exists(self.os_path("usr/bin/cage")): - self.config_data['default_session']['command'] = "cage -d -s -- gtkgreet" - if self.greeter_css_location: - self.config_data['default_session']['command'] += f" -s {self.greeter_css_location}" - elif os.path.exists(self.os_path("usr/bin/tuigreet")): - tuigreet_base_cmd = "tuigreet --remember --time --issue --asterisks --cmd " - self.config_data['default_session']['command'] = tuigreet_base_cmd + de_command - elif os.path.exists(self.os_path("usr/bin/ddlm")): - self.config_data['default_session']['command'] = "ddlm --target " + de_command - else: - self.config_data['default_session']['command'] = "agreety --cmd " + de_command - - if do_autologin: - # Log in as user, with given DE - self.config_data['initial_session'] = dict(command = de_command, user = username) - elif 'initial_session' in self.config_data: - # No autologin, remove any autologin that was copied from the live ISO - del self.config_data['initial_session'] - - self.config_write() - - -class DMsysconfig(DisplayManager): - name = "sysconfig" - executable = None - - def set_autologin(self, username, do_autologin, default_desktop_environment): - dmauto = "DISPLAYMANAGER_AUTOLOGIN" - - os.system( - "sed -i -e 's|^{!s}=.*|{!s}=\"{!s}\"|' " - "{!s}/etc/sysconfig/displaymanager".format( - dmauto, dmauto, - username if do_autologin else "", - self.root_mount_point - ) - ) - - - def basic_setup(self): - pass - - def desktop_environment_setup(self, desktop_environment): - pass - - def greeter_setup(self): - pass - - # For openSUSE-derivatives, there is only sysconfig to configure, - # and no special DM configuration for it. Instead, check that - # sysconfig is available in the target. - def have_dm(self): - config = "{!s}/etc/sysconfig/displaymanager".format(self.root_mount_point) - return os.path.exists(config) - - -# Collect all the subclasses of DisplayManager defined above, -# and index them based on the name property of each class. -display_managers = [ - (c.name, c) - for c in globals().values() - if type(c) is abc.ABCMeta and issubclass(c, DisplayManager) and c.name -] - - -def run(): - """ - Configure display managers. - - We acquire a list of displaymanagers, either from config or (overridden) - from globalstorage. This module will try to set up (including autologin) - all the displaymanagers in the list, in that specific order. Most distros - will probably only ship one displaymanager. - If a displaymanager is in the list but not installed, a debugging message - is printed and the entry ignored. - """ - # Get configuration settings for display managers - displaymanagers = None - if "displaymanagers" in libcalamares.job.configuration: - displaymanagers = libcalamares.job.configuration["displaymanagers"] - - if libcalamares.globalstorage.contains("displayManagers"): - displaymanagers = libcalamares.globalstorage.value("displayManagers") - - if ("sysconfigSetup" in libcalamares.job.configuration - and libcalamares.job.configuration["sysconfigSetup"]): - displaymanagers = ["sysconfig"] - - if not displaymanagers: - return ( - _("No display managers selected for the displaymanager module."), - _("The displaymanagers list is empty or undefined in both " - "globalstorage and displaymanager.conf.") - ) - - # Get instances that are actually installed - root_mount_point = libcalamares.globalstorage.value("rootMountPoint") - dm_impl = [] - dm_names = displaymanagers[:] - for dm in dm_names: - # Find the implementation class - dm_instance = None - impl = [ cls for name, cls in display_managers if name == dm ] - if len(impl) == 1: - dm_instance = impl[0](root_mount_point) - if dm_instance.have_dm(): - dm_impl.append(dm_instance) - else: - dm_instance = None - else: - libcalamares.utils.debug("{!s} has {!s} implementation classes.".format(dm, len(impl))) - - if dm_instance is None: - libcalamares.utils.debug("{!s} selected but not installed".format(dm)) - if dm in displaymanagers: - displaymanagers.remove(dm) - - if not dm_impl: - libcalamares.utils.warning( - "No display managers selected for the displaymanager module. " - "The list is empty after checking for installed display managers." - ) - return None - - # Pick up remaining settings - if "defaultDesktopEnvironment" in libcalamares.job.configuration: - entry = libcalamares.job.configuration["defaultDesktopEnvironment"] - default_desktop_environment = DesktopEnvironment( - entry["executable"], entry["desktopFile"] - ) - # Adjust if executable is bad, but desktopFile isn't. - if not default_desktop_environment.update_from_desktop_file(root_mount_point): - libcalamares.utils.warning( - "The configured default desktop environment, {!s}, " - "can not be found.".format(default_desktop_environment.desktop_file)) - else: - default_desktop_environment = find_desktop_environment( - root_mount_point - ) - - if "basicSetup" in libcalamares.job.configuration: - enable_basic_setup = libcalamares.job.configuration["basicSetup"] - else: - enable_basic_setup = False - - username = libcalamares.globalstorage.value("autoLoginUser") - if username is not None: - do_autologin = True - libcalamares.utils.debug("Setting up autologin for user {!s}.".format(username)) - else: - do_autologin = False - libcalamares.utils.debug("Unsetting autologin.") - - libcalamares.globalstorage.insert("displayManagers", displaymanagers) - - # Do the actual configuration and collect messages - dm_setup_message = [] - for dm in dm_impl: - dm_specific_configuration = libcalamares.job.configuration.get(dm.name, None) - if dm_specific_configuration and isinstance(dm_specific_configuration, dict): - for k, v in dm_specific_configuration.items(): - if hasattr(dm, k): - setattr(dm, k, v) - dm_message = None - if enable_basic_setup: - dm_message = dm.basic_setup() - if default_desktop_environment is not None and dm_message is None: - dm_message = dm.desktop_environment_setup(default_desktop_environment) - if dm_message is None: - dm_message = dm.greeter_setup() - if dm_message is None: - dm_message = dm.set_autologin(username, do_autologin, default_desktop_environment) - - if dm_message is not None: - dm_setup_message.append("{!s}: {!s}".format(*dm_message)) - - if dm_setup_message: - return ( - _("Display manager configuration was incomplete"), - "\n".join(dm_setup_message) - ) diff --git a/src/modules/displaymanager/module.desc b/src/modules/displaymanager/module.desc deleted file mode 100644 index a589418792..0000000000 --- a/src/modules/displaymanager/module.desc +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -type: "job" -name: "displaymanager" -interface: "python" -script: "main.py" diff --git a/src/modules/displaymanager/tests/1.global b/src/modules/displaymanager/tests/1.global deleted file mode 100644 index ee06ccfe1e..0000000000 --- a/src/modules/displaymanager/tests/1.global +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -rootMountPoint: /tmp diff --git a/src/modules/displaymanager/tests/CMakeTests.txt b/src/modules/displaymanager/tests/CMakeTests.txt deleted file mode 100644 index 70e3d580d5..0000000000 --- a/src/modules/displaymanager/tests/CMakeTests.txt +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# We have tests to load (some) of the DMs specifically, to test their -# configuration code. Those tests conventionally live in Python -# files here in the tests/ directory. Add them. -foreach(_dmname greetd sddm) - add_test( - NAME configure-displaymanager-${_dmname} - COMMAND env PYTHONPATH=.: python3 ${CMAKE_CURRENT_LIST_DIR}/test-dm-${_dmname}.py - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - ) -endforeach() diff --git a/src/modules/displaymanager/tests/test-dm-greetd.py b/src/modules/displaymanager/tests/test-dm-greetd.py deleted file mode 100644 index e2682afc7c..0000000000 --- a/src/modules/displaymanager/tests/test-dm-greetd.py +++ /dev/null @@ -1,33 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Calamares Boilerplate -import libcalamares -libcalamares.globalstorage = libcalamares.GlobalStorage(None) -libcalamares.globalstorage.insert("testing", True) - -# Module prep-work -from src.modules.displaymanager import main -default_desktop_environment = main.DesktopEnvironment("startplasma-x11", "kde-plasma.desktop") - -import os -os.makedirs("/tmp/etc/greetd/", exist_ok=True) -try: - os.remove("/tmp/etc/greetd/config.toml") -except FileNotFoundError as e: - pass - -try: - import toml -except ImportError: - # This is a failure of the test-environment. - import sys - print("Can't find module toml.", file=sys.stderr) - sys.exit(0) - -# Specific DM test -d = main.DMgreetd("/tmp") -d.set_autologin("d", True, default_desktop_environment) -# .. and again (this time checks load/save) -d.set_autologin("d", True, default_desktop_environment) -d.set_autologin("d", True, default_desktop_environment) diff --git a/src/modules/displaymanager/tests/test-dm-sddm.py b/src/modules/displaymanager/tests/test-dm-sddm.py deleted file mode 100644 index b5c334948e..0000000000 --- a/src/modules/displaymanager/tests/test-dm-sddm.py +++ /dev/null @@ -1,18 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Calamares Boilerplate -import libcalamares -libcalamares.globalstorage = libcalamares.GlobalStorage(None) -libcalamares.globalstorage.insert("testing", True) - -# Module prep-work -from src.modules.displaymanager import main -default_desktop_environment = main.DesktopEnvironment("startplasma-x11", "kde-plasma.desktop") - -# Specific DM test -d = main.DMsddm("/tmp") -d.set_autologin("d", True, default_desktop_environment) -# .. and again (this time checks load/save) -d.set_autologin("d", True, default_desktop_environment) -d.set_autologin("d", True, default_desktop_environment) diff --git a/src/modules/dracut/dracut.conf b/src/modules/dracut/dracut.conf deleted file mode 100644 index ba1a7b08cb..0000000000 --- a/src/modules/dracut/dracut.conf +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Run dracut(8) with an optional kernel name ---- -# Dracut defaults to setting initramfs-.img -# If you want to specify another filename for the resulting image, -# set a custom name, including the path -# -initramfsName: /boot/initramfs-freebsd.img diff --git a/src/modules/dracut/dracut.schema.yaml b/src/modules/dracut/dracut.schema.yaml deleted file mode 100644 index d6008e1bf5..0000000000 --- a/src/modules/dracut/dracut.schema.yaml +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-FileCopyrightText: 2022 Anke Boersma -# SPDX-License-Identifier: GPL-3.0-or-later ---- -$schema: https://json-schema.org/schema# -$id: https://calamares.io/schemas/dracut -additionalProperties: false -type: object -properties: - initramfsName: { type: string } diff --git a/src/modules/dracut/main.py b/src/modules/dracut/main.py deleted file mode 100644 index 85e6f3e7ff..0000000000 --- a/src/modules/dracut/main.py +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2014-2015 Philip Müller -# SPDX-FileCopyrightText: 2014 Teo Mrnjavac -# SPDX-FileCopyrightText: 2017 Alf Gaida -# SPDX-FileCopyrightText: 2019 Adriaan de Groot -# SPDX-FileCopyrightText: 2022 Anke Boersma -# SPDX-License-Identifier: GPL-3.0-or-later -# -# Calamares is Free Software: see the License-Identifier above. -# -import subprocess - -import libcalamares -from libcalamares.utils import target_env_process_output - - -import gettext -_ = gettext.translation("calamares-python", - localedir=libcalamares.utils.gettext_path(), - languages=libcalamares.utils.gettext_languages(), - fallback=True).gettext - - -def pretty_name(): - return _("Creating initramfs with dracut.") - - -def run_dracut(): - """ - Creates initramfs, even when initramfs already exists. - - :return: - """ - try: - initramfs_name = libcalamares.job.configuration['initramfsName'] - target_env_process_output(['dracut', '-f', initramfs_name]) - except KeyError: - try: - target_env_process_output(['dracut', '-f']) - except subprocess.CalledProcessError as cpe: - libcalamares.utils.warning(f"Dracut failed with output: {cpe.output}") - return cpe.returncode - except subprocess.CalledProcessError as cpe: - libcalamares.utils.warning(f"Dracut failed with output: {cpe.output}") - return cpe.returncode - - return 0 - - -def run(): - """ - Starts routine to create initramfs. It passes back the exit code - if it fails. - - :return: - """ - return_code = run_dracut() - if return_code != 0: - return (_("Failed to run dracut"), - _(f"Dracut failed to run on the target with return code: {return_code}")) diff --git a/src/modules/dracut/module.desc b/src/modules/dracut/module.desc deleted file mode 100644 index 9029bf66b1..0000000000 --- a/src/modules/dracut/module.desc +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -type: "job" -name: "dracut" -interface: "python" -script: "main.py" diff --git a/src/modules/dracutlukscfg/CMakeLists.txt b/src/modules/dracutlukscfg/CMakeLists.txt deleted file mode 100644 index 85efccc0ce..0000000000 --- a/src/modules/dracutlukscfg/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# -calamares_add_plugin(dracutlukscfg - TYPE job - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - DracutLuksCfgJob.cpp - SHARED_LIB - NO_CONFIG -) diff --git a/src/modules/dracutlukscfg/DracutLuksCfgJob.cpp b/src/modules/dracutlukscfg/DracutLuksCfgJob.cpp deleted file mode 100644 index 6bc87e2c46..0000000000 --- a/src/modules/dracutlukscfg/DracutLuksCfgJob.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2016 Kevin Kofler - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "DracutLuksCfgJob.h" - -#include -#include -#include -#include - -#include "CalamaresVersion.h" -#include "GlobalStorage.h" -#include "JobQueue.h" - -#include "utils/Logger.h" - -static const QLatin1String CONFIG_FILE( "/etc/dracut.conf.d/calamares-luks.conf" ); - -static const char CONFIG_FILE_HEADER[] - = "# Configuration file automatically written by the Calamares system installer\n" - "# (This file is written once at install time and should be safe to edit.)\n" - "# Enables support for LUKS full disk encryption with single sign on from GRUB.\n" - "\n"; - -static const char CONFIG_FILE_CRYPTTAB_KEYFILE_LINE[] - = "# force installing /etc/crypttab even if hostonly=\"no\", install the keyfile\n" - "install_items+=\" /etc/crypttab /crypto_keyfile.bin \"\n"; - -static const char CONFIG_FILE_CRYPTTAB_LINE[] = "# force installing /etc/crypttab even if hostonly=\"no\"\n" - "install_items+=\" /etc/crypttab \"\n"; - -static const QLatin1String - CONFIG_FILE_SWAPLINE( "# enable automatic resume from swap\nadd_device+=\" /dev/disk/by-uuid/%1 \"\n" ); - -static QString -rootMountPoint() -{ - Calamares::GlobalStorage* globalStorage = Calamares::JobQueue::instance()->globalStorage(); - return globalStorage->value( QStringLiteral( "rootMountPoint" ) ).toString(); -} - -static QVariantList -partitions() -{ - Calamares::GlobalStorage* globalStorage = Calamares::JobQueue::instance()->globalStorage(); - return globalStorage->value( QStringLiteral( "partitions" ) ).toList(); -} - -static bool -isRootEncrypted() -{ - const QVariantList partitions = ::partitions(); - for ( const QVariant& partition : partitions ) - { - QVariantMap partitionMap = partition.toMap(); - QString mountPoint = partitionMap.value( QStringLiteral( "mountPoint" ) ).toString(); - if ( mountPoint == QStringLiteral( "/" ) ) - { - return partitionMap.contains( QStringLiteral( "luksMapperName" ) ); - } - } - return false; -} - -static bool -hasUnencryptedSeparateBoot() -{ - const QVariantList partitions = ::partitions(); - for ( const QVariant& partition : partitions ) - { - QVariantMap partitionMap = partition.toMap(); - QString mountPoint = partitionMap.value( QStringLiteral( "mountPoint" ) ).toString(); - if ( mountPoint == QStringLiteral( "/boot" ) ) - { - return !partitionMap.contains( QStringLiteral( "luksMapperName" ) ); - } - } - return false; -} - -static QString -swapOuterUuid() -{ - const QVariantList partitions = ::partitions(); - for ( const QVariant& partition : partitions ) - { - QVariantMap partitionMap = partition.toMap(); - QString fsType = partitionMap.value( QStringLiteral( "fs" ) ).toString(); - if ( fsType == QStringLiteral( "linuxswap" ) && partitionMap.contains( QStringLiteral( "luksMapperName" ) ) ) - { - return partitionMap.value( QStringLiteral( "luksUuid" ) ).toString(); - } - } - return QString(); -} - -DracutLuksCfgJob::DracutLuksCfgJob( QObject* parent ) - : Calamares::CppJob( parent ) -{ -} - - -DracutLuksCfgJob::~DracutLuksCfgJob() {} - - -QString -DracutLuksCfgJob::prettyName() const -{ - if ( isRootEncrypted() ) - { - return tr( "Writing LUKS configuration for Dracut to %1…", "@status" ).arg( CONFIG_FILE ); - } - else - { - return tr( "Skipping writing LUKS configuration for Dracut: \"/\" partition is not encrypted", "@info" ); - } -} - - -Calamares::JobResult -DracutLuksCfgJob::exec() -{ - if ( isRootEncrypted() ) - { - const QString realConfigFilePath = rootMountPoint() + CONFIG_FILE; - cDebug() << "[DRACUTLUKSCFG]: Writing" << realConfigFilePath; - QDir( QStringLiteral( "/" ) ).mkpath( QFileInfo( realConfigFilePath ).absolutePath() ); - QFile configFile( realConfigFilePath ); - if ( !configFile.open( QIODevice::WriteOnly | QIODevice::Text ) ) - { - cDebug() << "[DRACUTLUKSCFG]: Failed to open" << realConfigFilePath; - return Calamares::JobResult::error( tr( "Failed to open %1", "@error" ).arg( realConfigFilePath ) ); - } - QTextStream outStream( &configFile ); - outStream << CONFIG_FILE_HEADER - << ( hasUnencryptedSeparateBoot() ? CONFIG_FILE_CRYPTTAB_LINE : CONFIG_FILE_CRYPTTAB_KEYFILE_LINE ); - const QString swapOuterUuid = ::swapOuterUuid(); - if ( !swapOuterUuid.isEmpty() ) - { - cDebug() << "[DRACUTLUKSCFG]: Swap outer UUID" << swapOuterUuid; - outStream << QString( CONFIG_FILE_SWAPLINE ).arg( swapOuterUuid ).toLatin1(); - } - cDebug() << "[DRACUTLUKSCFG]: Wrote config to" << realConfigFilePath; - } - else - { - cDebug() << "[DRACUTLUKSCFG]: / not encrypted, skipping"; - } - - return Calamares::JobResult::ok(); -} - -CALAMARES_PLUGIN_FACTORY_DEFINITION( DracutLuksCfgJobFactory, registerPlugin< DracutLuksCfgJob >(); ) diff --git a/src/modules/dracutlukscfg/DracutLuksCfgJob.h b/src/modules/dracutlukscfg/DracutLuksCfgJob.h deleted file mode 100644 index 33029f93a0..0000000000 --- a/src/modules/dracutlukscfg/DracutLuksCfgJob.h +++ /dev/null @@ -1,40 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2016 Kevin Kofler - * SPDX-FileCopyrightText: 2017 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef DRACUTLUKSCFGJOB_H -#define DRACUTLUKSCFGJOB_H - -#include -#include - -#include "CppJob.h" - -#include "utils/PluginFactory.h" - -#include "DllMacro.h" - -class PLUGINDLLEXPORT DracutLuksCfgJob : public Calamares::CppJob -{ - Q_OBJECT - -public: - explicit DracutLuksCfgJob( QObject* parent = nullptr ); - ~DracutLuksCfgJob() override; - - QString prettyName() const override; - - Calamares::JobResult exec() override; - -private: -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( DracutLuksCfgJobFactory ) - -#endif // DRACUTLUKSCFGJOB_H diff --git a/src/modules/dummycpp/CMakeLists.txt b/src/modules/dummycpp/CMakeLists.txt deleted file mode 100644 index b822a03be1..0000000000 --- a/src/modules/dummycpp/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# -calamares_add_plugin(dummycpp - TYPE job - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - DummyCppJob.cpp - SHARED_LIB -) diff --git a/src/modules/dummycpp/DummyCppJob.cpp b/src/modules/dummycpp/DummyCppJob.cpp deleted file mode 100644 index ba8e6ce523..0000000000 --- a/src/modules/dummycpp/DummyCppJob.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Teo Mrnjavac (original dummypython code) - * SPDX-FileCopyrightText: 2016 Kevin Kofler - * SPDX-FileCopyrightText: 2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "DummyCppJob.h" - -#include -#include - -#include "CalamaresVersion.h" -#include "GlobalStorage.h" -#include "JobQueue.h" - -#include "compat/Variant.h" -#include "utils/Logger.h" -#include "utils/System.h" - -DummyCppJob::DummyCppJob( QObject* parent ) - : Calamares::CppJob( parent ) -{ -} - -DummyCppJob::~DummyCppJob() {} - -QString -DummyCppJob::prettyName() const -{ - return tr( "Performing dummy C++ job…", "@status" ); -} - -static QString variantListToString( const QVariantList& variantList ); -static QString variantMapToString( const QVariantMap& variantMap ); -static QString variantHashToString( const QVariantHash& variantHash ); - -static QString -variantToString( const QVariant& variant ) -{ - if ( Calamares::typeOf( variant ) == Calamares::MapVariantType ) - { - return variantMapToString( variant.toMap() ); - } - else if ( Calamares::typeOf( variant ) == Calamares::HashVariantType ) - { - return variantHashToString( variant.toHash() ); - } - else if ( ( Calamares::typeOf( variant ) == Calamares::ListVariantType ) - || ( Calamares::typeOf( variant ) == Calamares::StringListVariantType ) ) - { - return variantListToString( variant.toList() ); - } - else - { - return variant.toString(); - } -} - -static QString -variantListToString( const QVariantList& variantList ) -{ - QStringList result; - for ( const QVariant& variant : variantList ) - { - result.append( variantToString( variant ) ); - } - return '{' + result.join( ',' ) + '}'; -} - -static QString -variantMapToString( const QVariantMap& variantMap ) -{ - QStringList result; - for ( auto it = variantMap.constBegin(); it != variantMap.constEnd(); ++it ) - { - result.append( it.key() + '=' + variantToString( it.value() ) ); - } - return '[' + result.join( ',' ) + ']'; -} - -static QString -variantHashToString( const QVariantHash& variantHash ) -{ - QStringList result; - for ( auto it = variantHash.constBegin(); it != variantHash.constEnd(); ++it ) - { - result.append( it.key() + '=' + variantToString( it.value() ) ); - } - return '<' + result.join( ',' ) + '>'; -} - -Calamares::JobResult -DummyCppJob::exec() -{ - // Ported from dummypython - Calamares::System::runCommand( Calamares::System::RunLocation::RunInHost, - QStringList() << "/bin/sh" - << "-c" - << "touch ~/calamares-dummycpp" ); - QString accumulator = QDateTime::currentDateTimeUtc().toString( Qt::ISODate ) + '\n'; - accumulator += QStringLiteral( "Calamares version: " ) + CALAMARES_VERSION_SHORT + '\n'; - accumulator += QStringLiteral( "This job's name: " ) + prettyName() + '\n'; - accumulator += QStringLiteral( "Configuration map: %1\n" ).arg( variantMapToString( m_configurationMap ) ); - accumulator += QStringLiteral( " *** globalstorage test ***\n" ); - Calamares::GlobalStorage* globalStorage = Calamares::JobQueue::instance()->globalStorage(); - accumulator += QStringLiteral( "lala: " ) - + ( globalStorage->contains( "lala" ) ? QStringLiteral( "true" ) : QStringLiteral( "false" ) ) + '\n'; - accumulator += QStringLiteral( "foo: " ) - + ( globalStorage->contains( "foo" ) ? QStringLiteral( "true" ) : QStringLiteral( "false" ) ) + '\n'; - accumulator += QStringLiteral( "count: " ) + QString::number( globalStorage->count() ) + '\n'; - globalStorage->insert( "item2", "value2" ); - globalStorage->insert( "item3", 3 ); - accumulator += QStringLiteral( "keys: %1\n" ).arg( globalStorage->keys().join( ',' ) ); - accumulator += QStringLiteral( "remove: %1\n" ).arg( QString::number( globalStorage->remove( "item2" ) ) ); - accumulator += QStringLiteral( "values: %1 %2 %3\n" ) - .arg( globalStorage->value( "foo" ).toString(), - globalStorage->value( "item2" ).toString(), - globalStorage->value( "item3" ).toString() ); - - emit progress( 0.1 ); - cDebug() << "[DUMMYCPP]: " << accumulator; - - globalStorage->debugDump(); - emit progress( 0.5 ); - - QThread::sleep( 3 ); - - return Calamares::JobResult::ok(); -} - -void -DummyCppJob::setConfigurationMap( const QVariantMap& configurationMap ) -{ - m_configurationMap = configurationMap; -} - -CALAMARES_PLUGIN_FACTORY_DEFINITION( DummyCppJobFactory, registerPlugin< DummyCppJob >(); ) diff --git a/src/modules/dummycpp/DummyCppJob.h b/src/modules/dummycpp/DummyCppJob.h deleted file mode 100644 index 5271a73a50..0000000000 --- a/src/modules/dummycpp/DummyCppJob.h +++ /dev/null @@ -1,43 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2016 Kevin Kofler - * SPDX-FileCopyrightText: 2017 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef DUMMYCPPJOB_H -#define DUMMYCPPJOB_H - -#include -#include - -#include "CppJob.h" - -#include "utils/PluginFactory.h" - -#include "DllMacro.h" - -class PLUGINDLLEXPORT DummyCppJob : public Calamares::CppJob -{ - Q_OBJECT - -public: - explicit DummyCppJob( QObject* parent = nullptr ); - ~DummyCppJob() override; - - QString prettyName() const override; - - Calamares::JobResult exec() override; - - void setConfigurationMap( const QVariantMap& configurationMap ) override; - -private: - QVariantMap m_configurationMap; -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( DummyCppJobFactory ) - -#endif // DUMMYCPPJOB_H diff --git a/src/modules/dummycpp/dummycpp.conf b/src/modules/dummycpp/dummycpp.conf deleted file mode 100644 index b00a428253..0000000000 --- a/src/modules/dummycpp/dummycpp.conf +++ /dev/null @@ -1,24 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# This is a dummy (example) module for C++ Jobs. -# -# The code is the documentation for the configuration file. ---- -syntax: "YAML map of anything" -example: - whats_this: "module-specific configuration" - from_where: "dummycpp.conf" -a_list: - - "item1" - - "item2" - - "item3" - - "item4" -a_list_of_maps: - - name: "an Item" - contents: - - "an element" - - "another element" - - name: "another item" - contents: - - "not much" diff --git a/src/modules/dummycpp/module.desc b/src/modules/dummycpp/module.desc deleted file mode 100644 index bc768a17ad..0000000000 --- a/src/modules/dummycpp/module.desc +++ /dev/null @@ -1,22 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# Module metadata file for dummycpp job -# -# The metadata for C++ (qtplugin) plugins is almost never interesting: -# the CMakeLists.txt should be using calamares_add_plugin() which will -# generate the metadata file during the build. Only C++ plugins that -# have strange settings should have a module.desc (non-C++ plugins, -# on the other hand, must have one, since they don't have CMakeLists.txt). -# -# Syntax is YAML 1.2 -# -# All four keys are mandatory. For C++ (qtplugin) modules, the interface -# value must be "qtplugin"; type is one of "job" or "view"; the name -# is the machine-identifier for the module and the load value should -# be the filename of the library that contains the implementation. -# ---- -type: "job" -name: "dummycpp" -interface: "qtplugin" -load: "libcalamares_job_dummycpp.so" diff --git a/src/modules/dummyprocess/module.desc b/src/modules/dummyprocess/module.desc deleted file mode 100644 index a329b77256..0000000000 --- a/src/modules/dummyprocess/module.desc +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# Module metadata file for dummy process jobmodule -# Syntax is YAML 1.2 ---- -type: "job" -name: "dummyprocess" -interface: "process" -chroot: false -command: "/bin/sh -c \"sleep 5 ; touch ~/calamares-dummyprocess\"" -timeout: 8 diff --git a/src/modules/dummypython/dummypython.conf b/src/modules/dummypython/dummypython.conf deleted file mode 100644 index 6ea50c5d12..0000000000 --- a/src/modules/dummypython/dummypython.conf +++ /dev/null @@ -1,24 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# This is a dummy (example) module for a Python Job Module. -# -# The code is the documentation for the configuration file. ---- -syntax: "YAML map of anything" -example: - whats_this: "module-specific configuration" - from_where: "dummypython.conf" -a_list: - - "item1" - - "item2" - - "item3" - - "item4" -a_list_of_maps: - - name: "an Item" - contents: - - "an element" - - "another element" - - name: "another item" - contents: - - "not much" diff --git a/src/modules/dummypython/main.py b/src/modules/dummypython/main.py deleted file mode 100644 index 65621dd1d1..0000000000 --- a/src/modules/dummypython/main.py +++ /dev/null @@ -1,114 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2014 Teo Mrnjavac -# SPDX-FileCopyrightText: 2017 Alf Gaida -# SPDX-FileCopyrightText: 2017 Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later -# -# Calamares is Free Software: see the License-Identifier above. -# - -""" -=== Example Python jobmodule. - -A Python jobmodule is a Python program which imports libcalamares and -has a function run() as entry point. run() must return None if everything -went well, or a tuple (str,str) with an error message and description -if something went wrong. -""" - -import libcalamares -import os -from time import gmtime, strftime, sleep - -import gettext -_ = gettext.translation("calamares-python", - localedir=libcalamares.utils.gettext_path(), - languages=libcalamares.utils.gettext_languages(), - fallback=True).gettext - - -def pretty_name(): - return _("Dummy python job.") - -status = _("Dummy python step {}").format(0) - -def pretty_status_message(): - return status - -def run(): - """Dummy python job.""" - libcalamares.utils.debug(f"Calamares version: {libcalamares.VERSION} date: {strftime('%Y-%m-%d %H:%M:%S', gmtime())}") - libcalamares.utils.debug(f"Job name : {libcalamares.job.pretty_name}") - libcalamares.utils.debug(f"Job path : {libcalamares.job.working_path}") - - libcalamares.utils.debug(f"LocaleDir : {libcalamares.utils.gettext_path()}") - libcalamares.utils.debug(f"Languages : {libcalamares.utils.gettext_languages()}") - - os.system("/bin/sh -c \"touch ~/calamares-dummypython\"") - - libcalamares.utils.debug("*** JOB CONFIGURATION ***") - for k, v in libcalamares.job.configuration.items(): - libcalamares.utils.debug(f" {k}={v}") - - libcalamares.utils.debug("*** GLOBAL STORAGE ***") - for k in libcalamares.globalstorage.keys(): - libcalamares.utils.debug(f" {k}={libcalamares.globalstorage.value(k)}") - - libcalamares.utils.debug("*** GLOBAL STORAGE BOGUS KEYS ***") - # - # This is a demonstration of issue #2237, load this module - # with the dummypython/tests/1.global configuration, e.g. - # ./loadmodule -g ../src/modules/dummypython/tests/1.global dummypython - # in the build directory. - # - for k in ("nonexistent", "empty", "numeric", "boolvalue"): - if libcalamares.globalstorage.value(k) is None: - libcalamares.utils.debug(f"NONE {k}={libcalamares.globalstorage.value(k)}") - else: - libcalamares.utils.debug(f" {k}={libcalamares.globalstorage.value(k)}") - - libcalamares.utils.debug("*** GLOBAL STORAGE MODIFICATION ***") - libcalamares.globalstorage.insert("item2", "value2") - libcalamares.globalstorage.insert("item3", 3) - accumulator = "keys: {}\n".format(str(libcalamares.globalstorage.keys())) - libcalamares.utils.debug(accumulator) - - accumulator = "remove: {}\n".format( - str(libcalamares.globalstorage.remove("item2"))) - accumulator += "values: {} {} {}\n".format( - str(libcalamares.globalstorage.value("foo")), - str(libcalamares.globalstorage.value("item2")), - str(libcalamares.globalstorage.value("item3"))) - libcalamares.utils.debug(accumulator) - - libcalamares.utils.debug("*** ACTIVITY ***") - - sleep(1) - - million = 1000000 - for i in range(million): - libcalamares.job.setprogress(i / million) - - try: - configlist = list(libcalamares.job.configuration["a_list"]) - except KeyError: - configlist = ["no list"] - - global status - c = 1 - for k in configlist: - status = _("Dummy python step {}").format(str(c) + ":" + repr(k)) - libcalamares.utils.debug(_("Dummy python step {}").format(str(k))) - sleep(1) - libcalamares.job.setprogress(c * 1.0 / (len(configlist)+1)) - c += 1 - - sleep(3) - - # To indicate an error, return a tuple of: - # (message, detailed-error-message) - return None diff --git a/src/modules/dummypython/module.desc b/src/modules/dummypython/module.desc deleted file mode 100644 index 52c1d09d28..0000000000 --- a/src/modules/dummypython/module.desc +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# Module metadata file for dummy python jobmodule -# Syntax is YAML 1.2 ---- -type: "job" -name: "dummypython" -interface: "python" -script: "main.py" diff --git a/src/modules/dummypython/tests/1.global b/src/modules/dummypython/tests/1.global deleted file mode 100644 index d0d194e6b8..0000000000 --- a/src/modules/dummypython/tests/1.global +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -firmwareType: bios -bootLoader: grub -empty: diff --git a/src/modules/finishedq/CMakeLists.txt b/src/modules/finishedq/CMakeLists.txt deleted file mode 100644 index 278feb5cfe..0000000000 --- a/src/modules/finishedq/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2021 Anke Boersma -# SPDX-License-Identifier: BSD-2-Clause -# -if(NOT WITH_QML) - calamares_skip_module( "finishedq (QML is not supported in this build)" ) - return() -endif() - -find_package(${qtname} ${QT_VERSION} CONFIG COMPONENTS DBus Network) -if(NOT TARGET ${qtname}::DBus OR NOT TARGET ${qtname}::Network) - calamares_skip_module( "finishedq (missing DBus or Network)" ) - return() -endif() - -set(_finished ${CMAKE_CURRENT_SOURCE_DIR}/../finished) -include_directories(${_finished}) - -calamares_add_plugin(finishedq - TYPE viewmodule - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - FinishedQmlViewStep.cpp - ${_finished}/Config.cpp - RESOURCES - finishedq${QT_VERSION_SUFFIX}.qrc - LINK_PRIVATE_LIBRARIES - ${qtname}::DBus - SHARED_LIB -) diff --git a/src/modules/finishedq/FinishedQmlViewStep.cpp b/src/modules/finishedq/FinishedQmlViewStep.cpp deleted file mode 100644 index bf605acf7e..0000000000 --- a/src/modules/finishedq/FinishedQmlViewStep.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017 2019, Adriaan de Groot - * SPDX-FileCopyrightText: 2019 Collabora Ltd - * SPDX-FileCopyrightText: 2021 Anke Boersma - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "FinishedQmlViewStep.h" - -#include "Config.h" - -#include "JobQueue.h" -#include - -CALAMARES_PLUGIN_FACTORY_DEFINITION( FinishedQmlViewStepFactory, registerPlugin< FinishedQmlViewStep >(); ) - -FinishedQmlViewStep::FinishedQmlViewStep( QObject* parent ) - : Calamares::QmlViewStep( parent ) - , m_config( new Config( this ) ) -{ - auto jq = Calamares::JobQueue::instance(); - connect( jq, &Calamares::JobQueue::failed, m_config, &Config::onInstallationFailed ); - - emit nextStatusChanged( true ); -} - -QString -FinishedQmlViewStep::prettyName() const -{ - return tr( "Finish", "@label" ); -} - -bool -FinishedQmlViewStep::isNextEnabled() const -{ - return false; -} - - -bool -FinishedQmlViewStep::isBackEnabled() const -{ - return false; -} - - -bool -FinishedQmlViewStep::isAtBeginning() const -{ - return true; -} - - -bool -FinishedQmlViewStep::isAtEnd() const -{ - return true; -} - - -void -FinishedQmlViewStep::onActivate() -{ - m_config->doNotify(); - connect( qApp, &QApplication::aboutToQuit, m_config, qOverload<>( &Config::doRestart ) ); - QmlViewStep::onActivate(); -} - - -Calamares::JobList -FinishedQmlViewStep::jobs() const -{ - return Calamares::JobList(); -} - -QObject* -FinishedQmlViewStep::getConfig() -{ - return m_config; -} - -void -FinishedQmlViewStep::setConfigurationMap( const QVariantMap& configurationMap ) -{ - m_config->setConfigurationMap( configurationMap ); - Calamares::QmlViewStep::setConfigurationMap( configurationMap ); -} diff --git a/src/modules/finishedq/FinishedQmlViewStep.h b/src/modules/finishedq/FinishedQmlViewStep.h deleted file mode 100644 index 7bcf0e67f1..0000000000 --- a/src/modules/finishedq/FinishedQmlViewStep.h +++ /dev/null @@ -1,57 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-FileCopyrightText: 2021 Anke Boersma - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef FINISHEDQMLVIEWSTEP_H -#define FINISHEDQMLVIEWSTEP_H - -#include - -#include "Config.h" - -#include "DllMacro.h" -#include "utils/PluginFactory.h" -#include "viewpages/QmlViewStep.h" - -#include - -class Config; - -class PLUGINDLLEXPORT FinishedQmlViewStep : public Calamares::QmlViewStep -{ - Q_OBJECT - -public: - explicit FinishedQmlViewStep( QObject* parent = nullptr ); - - QString prettyName() const override; - - bool isNextEnabled() const override; - bool isBackEnabled() const override; - - bool isAtBeginning() const override; - bool isAtEnd() const override; - - void onActivate() override; - - Calamares::JobList jobs() const override; - - void setConfigurationMap( const QVariantMap& configurationMap ) override; - QObject* getConfig() override; - -private: - Config* m_config; - - bool m_installFailed; // Track if onInstallationFailed() was called -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( FinishedQmlViewStepFactory ) - -#endif diff --git a/src/modules/finishedq/finishedq-qt6.qml b/src/modules/finishedq/finishedq-qt6.qml deleted file mode 100644 index 885a66f0d5..0000000000 --- a/src/modules/finishedq/finishedq-qt6.qml +++ /dev/null @@ -1,99 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2021 - 2023 Anke Boersma - * SPDX-License-Identifier: GPL-3.0-or-later - * License-Filename: LICENSE - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -import io.calamares.core 1.0 -import io.calamares.ui 1.0 - -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import org.kde.kirigami as Kirigami -import QtQuick.Window - -Page { - - id: finished - - width: parent.width - height: parent.height - - header: Kirigami.Heading { - width: parent.width - height: 100 - id: header - Layout.fillWidth: true - horizontalAlignment: Qt.AlignHCenter - color: Kirigami.Theme.textColor - level: 1 - text: qsTr("Installation Completed", "@title") - - Text { - anchors.top: header.bottom - anchors.horizontalCenter: parent.horizontalCenter - horizontalAlignment: Text.AlignHCenter - font.pointSize: 12 - text: qsTr("%1 has been installed on your computer.
- You may now restart into your new system, or continue using the Live environment.", "@info, %1 is the product name") - .arg(Branding.string(Branding.ProductName)) - } - - Image { - source: "seedling.svg" - anchors.top: header.bottom - anchors.topMargin: 80 - anchors.horizontalCenter: parent.horizontalCenter - width: 64 - height: 64 - mipmap: true - } - } - - RowLayout { - Layout.alignment: Qt.AlignRight|Qt.AlignVCenter - anchors.centerIn: parent - spacing: 6 - - Button { - id: button - text: qsTr("Close Installer", "@button") - icon.name: "application-exit" - onClicked: { ViewManager.quit(); } - } - - Button { - text: qsTr("Restart System", "@button") - icon.name: "system-reboot" - onClicked: { config.doRestart(true); } - } - } - - Item { - - Layout.fillHeight: true - Layout.fillWidth: true - anchors.bottom: parent.bottom - anchors.bottomMargin : 100 - anchors.horizontalCenter: parent.horizontalCenter - - Text { - anchors.centerIn: parent - anchors.top: parent.top - horizontalAlignment: Text.AlignHCenter - text: qsTr("

A full log of the install is available as installation.log in the home directory of the Live user.
- This log is copied to /var/log/installation.log of the target system.

", "@info") - } - } - - function onActivate() { - } - - function onLeave() { - } -} diff --git a/src/modules/finishedq/finishedq-qt6.qrc b/src/modules/finishedq/finishedq-qt6.qrc deleted file mode 100644 index c0daf36ff5..0000000000 --- a/src/modules/finishedq/finishedq-qt6.qrc +++ /dev/null @@ -1,6 +0,0 @@ - - - finishedq-qt6.qml - seedling.svg - - diff --git a/src/modules/finishedq/finishedq.conf b/src/modules/finishedq/finishedq.conf deleted file mode 100644 index ee226c3565..0000000000 --- a/src/modules/finishedq/finishedq.conf +++ /dev/null @@ -1,36 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Configuration for the "finishedq" page, which is usually shown only at -# the end of the installation (successful or not). -# -# See the documentation for the "finished" module for a full explanation -# of the configuration options; the description here applies primarily -# to the use that the QML makes of them. ---- -# Behavior of the "restart system now" button. -# -# The example QML for this module offers a "Restart Now" button, -# which the user can click on. It calls directly to the restart -# function. If the user closes the installer in some other way, -# (the "Done" button or close-window) a restart **might** happen: -# -# - never -# Do not restart (this will also block the "Restart Now" button, -# so it is not very useful) -# - user-unchecked -# Do not restart on other ways of closing the window. No checkbox -# is shown in the example QML, so there is no way for the user to -# express a choice -- except by clicking the "Restart Now" button. -# - user-checked -# Do restart on other ways of closing the window. This makes close -# and "Restart Now" do the same thing. No checkbox is shown by the QML, -# so the machine will **always** restart. -# - always -# Same as above. -# -# For the **specific** example QML included with this module, only -# *user-unchecked* really makes sense. -restartNowMode: user-unchecked -restartNowCommand: "systemctl -i reboot" -notifyOnFinished: false diff --git a/src/modules/finishedq/finishedq.qml b/src/modules/finishedq/finishedq.qml deleted file mode 100644 index 789ac4cfbd..0000000000 --- a/src/modules/finishedq/finishedq.qml +++ /dev/null @@ -1,101 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2021 Anke Boersma - * SPDX-License-Identifier: GPL-3.0-or-later - * License-Filename: LICENSE - * - * 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.Layouts 1.3 -import org.kde.kirigami 2.7 as Kirigami -import QtGraphicalEffects 1.0 -import QtQuick.Window 2.3 - -Page { - - id: finished - - width: parent.width - height: parent.height - - header: Kirigami.Heading { - width: parent.width - height: 100 - id: header - Layout.fillWidth: true - horizontalAlignment: Qt.AlignHCenter - color: Kirigami.Theme.textColor - level: 1 - text: qsTr("Installation Completed") - - Text { - anchors.top: header.bottom - anchors.horizontalCenter: parent.horizontalCenter - horizontalAlignment: Text.AlignHCenter - font.pointSize: 12 - text: qsTr("%1 has been installed on your computer.
- You may now restart into your new system, or continue using the Live environment.").arg(Branding.string(Branding.ProductName)) - } - - Image { - source: "seedling.svg" - anchors.top: header.bottom - anchors.topMargin: 80 - anchors.horizontalCenter: parent.horizontalCenter - width: 64 - height: 64 - mipmap: true - } - } - - RowLayout { - Layout.alignment: Qt.AlignRight|Qt.AlignVCenter - anchors.centerIn: parent - spacing: 6 - - Button { - id: button - text: qsTr("Close Installer") - icon.name: "application-exit" - onClicked: { ViewManager.quit(); } - } - - Button { - text: qsTr("Restart System") - icon.name: "system-reboot" - onClicked: { config.doRestart(true); } - } - } - - Item { - - Layout.fillHeight: true - Layout.fillWidth: true - anchors.bottom: parent.bottom - anchors.bottomMargin : 100 - anchors.horizontalCenter: parent.horizontalCenter - - Text { - anchors.centerIn: parent - anchors.top: parent.top - horizontalAlignment: Text.AlignHCenter - text: qsTr("

A full log of the install is available as installation.log in the home directory of the Live user.
- This log is copied to /var/log/installation.log of the target system.

") - } - } - - function onActivate() - { - } - - function onLeave() - { - } -} diff --git a/src/modules/finishedq/finishedq.qrc b/src/modules/finishedq/finishedq.qrc deleted file mode 100644 index e0918eb7f3..0000000000 --- a/src/modules/finishedq/finishedq.qrc +++ /dev/null @@ -1,6 +0,0 @@ - - - finishedq.qml - seedling.svg - - diff --git a/src/modules/finishedq/finishedq@mobile.qml b/src/modules/finishedq/finishedq@mobile.qml deleted file mode 100644 index 2e6fe04921..0000000000 --- a/src/modules/finishedq/finishedq@mobile.qml +++ /dev/null @@ -1,122 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2021 Anke Boersma - * SPDX-License-Identifier: GPL-3.0-or-later - * License-Filename: LICENSE - * - * 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.Layouts 1.3 -import org.kde.kirigami 2.7 as Kirigami -import QtGraphicalEffects 1.0 -import QtQuick.Window 2.3 - -Page { - - id: finished - - width: parent.width - height: parent.height - - header: Kirigami.Heading { - width: parent.width - height: 100 - id: header - Layout.fillWidth: true - horizontalAlignment: Qt.AlignHCenter - color: Kirigami.Theme.textColor - level: 1 - text: qsTr("Installation Completed", "@title") - - Text { - anchors.top: header.bottom - anchors.horizontalCenter: parent.horizontalCenter - horizontalAlignment: Text.AlignHCenter - font.pointSize: 12 - text: qsTr("%1 has been installed on your computer.
- You may now restart your device.", "@info, %1 is the product name") - .arg(Branding.string(Branding.ProductName)) - } - - Image { - source: "seedling.svg" - anchors.top: header.bottom - anchors.topMargin: 80 - anchors.horizontalCenter: parent.horizontalCenter - width: 64 - height: 64 - mipmap: true - } - } - - RowLayout { - Layout.alignment: Qt.AlignRight|Qt.AlignVCenter - anchors.centerIn: parent - spacing: 6 - - Button { - id: button - text: qsTr("Close", "@button") - icon.name: "application-exit" - onClicked: { ViewManager.quit(); } - } - - Button { - text: qsTr("Restart", "@button") - icon.name: "system-reboot" - onClicked: { config.doRestart(true); } - } - } - - Item { - - Layout.fillHeight: true - Layout.fillWidth: true - anchors.bottom: parent.bottom - anchors.bottomMargin : 100 - anchors.horizontalCenter: parent.horizontalCenter - - ProgressBar { - id: autoRestartBar - value: 1.0 - anchors.horizontalCenter: parent.horizontalCenter - - } - - Timer { - id: autoRestartTimer - // This is in milliseconds and should be less than 1000 (because of logic in onTriggered) - interval: 100 - repeat: true - running: false - // Whenever the timer fires (1000 / interval times a second) count the progress bar down - // by 1%. When the bar is empty, try to restart normally; as a backup, when the bar - // is empty change settings and schedule it to quit 1000 milliseconds (1s) later. - onTriggered: { - autoRestartBar.value -= 0.01; - if (autoRestartBar.value <= 0.0) { - // First time through here, set the interval to 1000 so that the - // second time (1 second later) goes to quit(). - if ( interval > 999) { ViewManager.quit(); } - else { config.doRestart(true); running = false; interval = 1000; repeat = false; start(); } - } - } - } - } - - function onActivate() - { - autoRestartTimer.running = true - } - - function onLeave() - { - } -} diff --git a/src/modules/finishedq/seedling.svg b/src/modules/finishedq/seedling.svg deleted file mode 100644 index 8f3501b170..0000000000 --- a/src/modules/finishedq/seedling.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/modules/finishedq/seedling.svg.license b/src/modules/finishedq/seedling.svg.license deleted file mode 100644 index 0604e8da9c..0000000000 --- a/src/modules/finishedq/seedling.svg.license +++ /dev/null @@ -1,2 +0,0 @@ -SPDX-FileCopyrightText: 2021 FontAwesome -SPDX-License-Identifier: CC-BY-4.0 diff --git a/src/modules/fsresizer/CMakeLists.txt b/src/modules/fsresizer/CMakeLists.txt deleted file mode 100644 index 43ba6d6d47..0000000000 --- a/src/modules/fsresizer/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# -include(KPMcoreHelper) - -if(KPMcore_FOUND) - include_directories(${KPMCORE_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/src/modules/partition) - - # The PartitionIterator is a small class, and it's easiest -- but also a - # gross hack -- to just compile it again from the partition module tree. - calamares_add_plugin(fsresizer - TYPE job - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - ResizeFSJob.cpp - LINK_PRIVATE_LIBRARIES - calamares::kpmcore - COMPILE_DEFINITIONS ${KPMcore_API_DEFINITIONS} - SHARED_LIB - ) - - calamares_add_test( - fsresizertest - SOURCES Tests.cpp - LIBRARIES - calamares_job_fsresizer # From above - yamlcpp::yamlcpp - DEFINITIONS ${KPMcore_API_DEFINITIONS} - ) -else() - if(NOT KPMcore_FOUND) - calamares_skip_module( "fsresizer (missing suitable KPMcore)" ) - else() - calamares_skip_module( "fsresizer (missing dependencies for KPMcore)" ) - endif() -endif() diff --git a/src/modules/fsresizer/ResizeFSJob.cpp b/src/modules/fsresizer/ResizeFSJob.cpp deleted file mode 100644 index e3f2fef307..0000000000 --- a/src/modules/fsresizer/ResizeFSJob.cpp +++ /dev/null @@ -1,256 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "ResizeFSJob.h" - -#include "CalamaresVersion.h" -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "partition/PartitionIterator.h" -#include "utils/Logger.h" -#include "utils/Units.h" -#include "utils/Variant.h" - -#include -#include - -#include -#include -#include -#include -#include -#include - -using Calamares::Partition::PartitionIterator; - -ResizeFSJob::ResizeFSJob( QObject* parent ) - : Calamares::CppJob( parent ) - , m_required( false ) -{ -} - -ResizeFSJob::~ResizeFSJob() {} - -QString -ResizeFSJob::prettyName() const -{ - return tr( "Performing file system resize…", "@status" ); -} - -ResizeFSJob::PartitionMatch -ResizeFSJob::findPartition() -{ - using DeviceList = QList< Device* >; - DeviceList devices - = m_kpmcore.backend()->scanDevices( /* not includeReadOnly, not includeLoopback */ ScanFlag( 0 ) ); - - cDebug() << "ResizeFSJob found" << devices.count() << "devices."; - for ( DeviceList::iterator dev_it = devices.begin(); dev_it != devices.end(); ++dev_it ) - { - if ( !( *dev_it ) ) - { - continue; - } - cDebug() << "ResizeFSJob found" << ( *dev_it )->deviceNode(); - for ( auto part_it = PartitionIterator::begin( *dev_it ); part_it != PartitionIterator::end( *dev_it ); - ++part_it ) - { - cDebug() << Logger::SubEntry << ( *part_it )->mountPoint() << "on" << ( *part_it )->deviceNode(); - if ( ( !m_fsname.isEmpty() && ( *part_it )->mountPoint() == m_fsname ) - || ( !m_devicename.isEmpty() && ( *part_it )->deviceNode() == m_devicename ) ) - { - cDebug() << Logger::SubEntry << "matched configuration dev=" << m_devicename << "fs=" << m_fsname; - return PartitionMatch( *dev_it, *part_it ); - } - } - } - - cDebug() << "No match for configuration dev=" << m_devicename << "fs=" << m_fsname; - return PartitionMatch( nullptr, nullptr ); -} - -/** @brief Returns the last sector the matched partition should occupy. - * - * Returns a sector number. Returns -1 if something is wrong (e.g. - * can't resize at all, or missing data). Returns 0 if the resize - * won't fit because it doesn't satisfy the settings for atleast - * and size (or won't grow at all because the partition is blocked - * by occupied space after it). - */ -qint64 -ResizeFSJob::findGrownEnd( ResizeFSJob::PartitionMatch m ) -{ - if ( !m.first || !m.second ) - { - return -1; // Missing device data - } - if ( !ResizeOperation::canGrow( m.second ) ) - { - return -1; // Operation is doomed - } - if ( !m_size.isValid() ) - { - return -1; // Must have a grow-size - } - - cDebug() << "Containing device size" << m.first->totalLogical(); - qint64 last_available = m.first->totalLogical() - 1; // Numbered from 0 - qint64 last_currently = m.second->lastSector(); - cDebug() << "Growing partition" << m.second->firstSector() << '-' << last_currently; - - for ( auto part_it = PartitionIterator::begin( m.first ); part_it != PartitionIterator::end( m.first ); ++part_it ) - { - qint64 next_start = ( *part_it )->firstSector(); - qint64 next_end = ( *part_it )->lastSector(); - if ( next_start > next_end ) - { - cWarning() << "Corrupt partition has end" << next_end << " < start" << next_start; - std::swap( next_start, next_end ); - } - if ( ( *part_it )->roles().has( PartitionRole::Unallocated ) ) - { - cDebug() << Logger::SubEntry << "ignoring unallocated" << next_start << '-' << next_end; - continue; - } - cDebug() << Logger::SubEntry << "comparing" << next_start << '-' << next_end; - if ( ( next_start > last_currently ) && ( next_start < last_available ) ) - { - cDebug() << Logger::SubEntry << "shrunk last available to" << next_start; - last_available = next_start - 1; // Before that one starts - } - } - - if ( !( last_available > last_currently ) ) - { - cDebug() << "Partition cannot grow larger."; - return 0; - } - - qint64 expand = last_available - last_currently; // number of sectors - if ( m_atleast.isValid() ) - { - qint64 required = m_atleast.toSectors( m.first->totalLogical(), m.first->logicalSize() ); - if ( expand < required ) - { - cDebug() << Logger::SubEntry << "need to expand by" << required << "but only" << expand << "is available."; - return 0; - } - } - - qint64 wanted = m_size.toSectors( expand, m.first->logicalSize() ); - if ( wanted < expand ) - { - cDebug() << Logger::SubEntry << "only growing by" << wanted << "instead of full" << expand; - last_available -= ( expand - wanted ); - } - - return last_available; -} - -Calamares::JobResult -ResizeFSJob::exec() -{ - if ( !isValid() ) - { - return Calamares::JobResult::error( - tr( "Invalid configuration", "@error" ), - tr( "The file-system resize job has an invalid configuration and will not run.", "@error" ) ); - } - - if ( !m_kpmcore ) - { - cWarning() << "Could not load KPMCore backend (2)."; - return Calamares::JobResult::error( tr( "KPMCore not available", "@error" ), - tr( "Calamares cannot start KPMCore for the file system resize job.", "@error" ) ); - } - m_kpmcore.backend()->initFSSupport(); // Might not be enough, see below - - // Now get the partition and FS we want to work on - PartitionMatch m = findPartition(); - if ( !m.first || !m.second ) - { - return Calamares::JobResult::error( - tr( "Resize failed.", "@error" ), - !m_fsname.isEmpty() - ? tr( "The filesystem %1 could not be found in this system, and cannot be resized.", "@info" ).arg( m_fsname ) - : tr( "The device %1 could not be found in this system, and cannot be resized.", "@info" ).arg( m_devicename ) ); - } - - m.second->fileSystem().init(); // Initialize support for specific FS - if ( !ResizeOperation::canGrow( m.second ) ) - { - cDebug() << "canGrow() returned false."; - return Calamares::JobResult::error( tr( "Resize Failed", "@error" ), - !m_fsname.isEmpty() - ? tr( "The filesystem %1 cannot be resized.", "@error" ).arg( m_fsname ) - : tr( "The device %1 cannot be resized.", "@error" ).arg( m_devicename ) ); - } - - qint64 new_end = findGrownEnd( m ); - cDebug() << "Resize from" << m.second->firstSector() << '-' << m.second->lastSector() << '(' << m.second->length() - << ')' << "to -" << new_end; - - if ( new_end < 0 ) - { - return Calamares::JobResult::error( tr( "Resize Failed", "@error" ), - !m_fsname.isEmpty() - ? tr( "The filesystem %1 cannot be resized.", "@error" ).arg( m_fsname ) - : tr( "The device %1 cannot be resized.", "@error" ).arg( m_devicename ) ); - } - if ( new_end == 0 ) - { - cWarning() << "Resize operation on" << m_fsname << m_devicename << "skipped as not-useful."; - if ( m_required ) - { - return Calamares::JobResult::error( - tr( "Resize Failed", "@error" ), - !m_fsname.isEmpty() ? tr( "The file system %1 must be resized, but cannot.", "@info" ).arg( m_fsname ) - : tr( "The device %1 must be resized, but cannot", "@info" ).arg( m_fsname ) ); - } - - return Calamares::JobResult::ok(); - } - - if ( ( new_end > 0 ) && ( new_end > m.second->lastSector() ) ) - { - ResizeOperation op( *m.first, *m.second, m.second->firstSector(), new_end ); - Report op_report( nullptr ); - if ( op.execute( op_report ) ) - { - cDebug() << "Resize operation OK."; - } - else - { - cDebug() << "Resize failed." << op_report.output(); - return Calamares::JobResult::error( tr( "Resize Failed", "@error" ), op_report.toText() ); - } - } - - return Calamares::JobResult::ok(); -} - -void -ResizeFSJob::setConfigurationMap( const QVariantMap& configurationMap ) -{ - m_fsname = configurationMap[ "fs" ].toString(); - m_devicename = configurationMap[ "dev" ].toString(); - - if ( m_fsname.isEmpty() && m_devicename.isEmpty() ) - { - cWarning() << "No fs or dev configured for resize."; - return; - } - - m_size = PartitionSize( configurationMap[ "size" ].toString() ); - m_atleast = PartitionSize( configurationMap[ "atleast" ].toString() ); - - m_required = Calamares::getBool( configurationMap, "required", false ); -} - -CALAMARES_PLUGIN_FACTORY_DEFINITION( ResizeFSJobFactory, registerPlugin< ResizeFSJob >(); ) diff --git a/src/modules/fsresizer/ResizeFSJob.h b/src/modules/fsresizer/ResizeFSJob.h deleted file mode 100644 index e31c0b911a..0000000000 --- a/src/modules/fsresizer/ResizeFSJob.h +++ /dev/null @@ -1,71 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef RESIZEFSJOB_H -#define RESIZEFSJOB_H - -#include -#include - -#include "CppJob.h" - -#include "partition/KPMManager.h" -#include "partition/PartitionSize.h" -#include "utils/PluginFactory.h" - -#include "DllMacro.h" - -class CoreBackend; // From KPMCore -class Device; // From KPMCore -class Partition; - -using PartitionSize = Calamares::Partition::PartitionSize; - -class PLUGINDLLEXPORT ResizeFSJob : public Calamares::CppJob -{ - Q_OBJECT - -public: - explicit ResizeFSJob( QObject* parent = nullptr ); - ~ResizeFSJob() override; - - QString prettyName() const override; - - Calamares::JobResult exec() override; - - void setConfigurationMap( const QVariantMap& configurationMap ) override; - - /** @brief Is the configuration of this job valid? */ - bool isValid() const { return ( !m_fsname.isEmpty() || !m_devicename.isEmpty() ) && m_size.isValid(); } - - QString name() const { return m_fsname.isEmpty() ? m_devicename : m_fsname; } - - PartitionSize size() const { return m_size; } - - PartitionSize minimumSize() const { return m_atleast; } - -private: - Calamares::Partition::KPMManager m_kpmcore; - PartitionSize m_size; - PartitionSize m_atleast; - QString m_fsname; // Either this, or devicename, is set, not both - QString m_devicename; - bool m_required; - - using PartitionMatch = QPair< Device*, Partition* >; - /** @brief Find the configured FS */ - PartitionMatch findPartition(); - - /** @brief Return a new end-sector for the given dev-part pair. */ - qint64 findGrownEnd( PartitionMatch ); -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( ResizeFSJobFactory ) - -#endif // RESIZEFSJOB_H diff --git a/src/modules/fsresizer/Tests.cpp b/src/modules/fsresizer/Tests.cpp deleted file mode 100644 index ff12310d9f..0000000000 --- a/src/modules/fsresizer/Tests.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2017-2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "Tests.h" - -#include "ResizeFSJob.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "Settings.h" - -#include "utils/Logger.h" -#include "utils/Yaml.h" - -#include - -#include -#include - -using SizeUnit = Calamares::Partition::SizeUnit; - -QTEST_GUILESS_MAIN( FSResizerTests ) - -FSResizerTests::FSResizerTests() {} - -FSResizerTests::~FSResizerTests() {} - -void -FSResizerTests::initTestCase() -{ -} - -void -FSResizerTests::testConfigurationRobust() -{ - ResizeFSJob j; - - // Empty config - j.setConfigurationMap( QVariantMap() ); - QVERIFY( j.name().isEmpty() ); - QCOMPARE( j.size().unit(), SizeUnit::None ); - QCOMPARE( j.minimumSize().unit(), SizeUnit::None ); - - // Config is missing fs and dev, so it isn't valid - YAML::Node doc0 = YAML::Load( R"(--- - size: 100% - atleast: 600MiB - )" ); - j.setConfigurationMap( Calamares::YAML::mapToVariant( doc0 ) ); - QVERIFY( j.name().isEmpty() ); - QCOMPARE( j.size().unit(), SizeUnit::None ); - QCOMPARE( j.minimumSize().unit(), SizeUnit::None ); - QCOMPARE( j.size().value(), 0 ); - QCOMPARE( j.minimumSize().value(), 0 ); -} - -void -FSResizerTests::testConfigurationValues() -{ - ResizeFSJob j; - - // Check both - YAML::Node doc0 = YAML::Load( R"(--- - fs: / - size: 100% - atleast: 600MiB - )" ); - j.setConfigurationMap( Calamares::YAML::mapToVariant( doc0 ) ); - QVERIFY( !j.name().isEmpty() ); - QCOMPARE( j.name(), QString( "/" ) ); - QCOMPARE( j.size().unit(), SizeUnit::Percent ); - QCOMPARE( j.minimumSize().unit(), SizeUnit::MiB ); - QCOMPARE( j.size().value(), 100 ); - QCOMPARE( j.minimumSize().value(), 600 ); - - // Silly config has bad atleast value - doc0 = YAML::Load( R"(--- - fs: / - dev: /dev/m00 - size: 72 MiB - atleast: 127 % - )" ); - j.setConfigurationMap( Calamares::YAML::mapToVariant( doc0 ) ); - QVERIFY( !j.name().isEmpty() ); - QCOMPARE( j.name(), QString( "/" ) ); - QCOMPARE( j.size().unit(), SizeUnit::MiB ); - QCOMPARE( j.minimumSize().unit(), SizeUnit::None ); - QCOMPARE( j.size().value(), 72 ); - QCOMPARE( j.minimumSize().value(), 0 ); - - // Silly config has bad atleast value - doc0 = YAML::Load( R"(--- - dev: /dev/m00 - size: 72 MiB - atleast: 127 % - )" ); - j.setConfigurationMap( Calamares::YAML::mapToVariant( doc0 ) ); - QVERIFY( !j.name().isEmpty() ); - QCOMPARE( j.name(), QString( "/dev/m00" ) ); - QCOMPARE( j.size().unit(), SizeUnit::MiB ); - QCOMPARE( j.minimumSize().unit(), SizeUnit::None ); - QCOMPARE( j.size().value(), 72 ); - QCOMPARE( j.minimumSize().value(), 0 ); - - // Normal config - doc0 = YAML::Load( R"(--- - fs: / -# dev: /dev/m00 - size: 71MiB -# atleast: 127% - )" ); - j.setConfigurationMap( Calamares::YAML::mapToVariant( doc0 ) ); - QVERIFY( !j.name().isEmpty() ); - QCOMPARE( j.name(), QString( "/" ) ); - QCOMPARE( j.size().unit(), SizeUnit::MiB ); - QCOMPARE( j.minimumSize().unit(), SizeUnit::None ); - QCOMPARE( j.size().value(), 71 ); - QCOMPARE( j.minimumSize().value(), 0 ); -} diff --git a/src/modules/fsresizer/Tests.h b/src/modules/fsresizer/Tests.h deleted file mode 100644 index f3d2308ec9..0000000000 --- a/src/modules/fsresizer/Tests.h +++ /dev/null @@ -1,30 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef TESTS_H -#define TESTS_H - -#include - -class FSResizerTests : public QObject -{ - Q_OBJECT -public: - FSResizerTests(); - ~FSResizerTests() override; - -private Q_SLOTS: - void initTestCase(); - // Can handle missing values - void testConfigurationRobust(); - // Can parse % and MiB values - void testConfigurationValues(); -}; - -#endif diff --git a/src/modules/fsresizer/fsresizer.conf b/src/modules/fsresizer/fsresizer.conf deleted file mode 100644 index e58c39822f..0000000000 --- a/src/modules/fsresizer/fsresizer.conf +++ /dev/null @@ -1,52 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Module that resizes a single FS to fill the entire (rest) of -# a device. This is used in OEM situations where an image is -# flashed onto an SD card (or similar) and used to boot a device, -# after which the FS should expand to fill the SD card. -# -# Example: a distro produces a 6GiB large image that is -# written to an 8GiB SD card; the FS should expand to take -# advantage of the unused 2GiB. The FS should expand much -# more if the same image is written to a 16GiB card. ---- - -# Which FS needs to be grown? Choose one way to identify it: -# - *fs* names a mount point which should already be mounted -# in the system. -# - *dev* names a device -fs: / -# dev: /dev/mmcblk0p1 - -# How much of the total remaining space should the FS use? -# The only sensible amount is "all of it". The value is -# in percent, so set it to 100. Perhaps a fixed size is -# needed (that would be weird though, since you don't know -# how big the card is), use MiB as suffix in that case. -# If missing, then it's assumed to be 0, and no resizing -# will happen. -# -# Percentages apply to **available space**. -size: 100% - -# Resizing might not be worth it, though. Set the minimum -# that it must grow; if it cannot grow that much, the -# resizing is skipped. Can be in percentage or absolute -# size, as above. If missing, then it's assumed to be 0, -# which means resizing is always worthwhile. -# -# If *atleast* is not zero, then the setting *required*, -# below, becomes relevant. -# -# Percentages apply to **total device size**. -#atleast: 1000MiB - -# When *atleast* is not zero, then the resize may be -# recommended (the default) or **required**. If the -# resize is required and cannot be carried out (because -# there's not enough space), then that is a fatal -# error for the installer. By default, resize is only -# recommended and it is not an error for no resize to be -# carried out. -required: false diff --git a/src/modules/fstab/fstab.conf b/src/modules/fstab/fstab.conf deleted file mode 100644 index 5c5c5662dc..0000000000 --- a/src/modules/fstab/fstab.conf +++ /dev/null @@ -1,37 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Creates /etc/fstab and /etc/crypttab in the target system. -# Also creates mount points for all the filesystems. -# -# When creating fstab entries for a filesystem, this module -# uses the options previously defined in the mount module ---- - -# Additional options added to each line in /etc/crypttab -crypttabOptions: luks -# For Debian and Debian-based distributions, change the above line to: -# crypttabOptions: luks,keyscript=/bin/cat - -# Options for handling /tmp in /etc/fstab -# Currently default (required) and ssd are supported -# The corresponding string can contain the following variables: -# tmpfs: true or tmpfs: false to either mount /tmp as tmpfs or not -# options: "" -# -# Example: -#tmpOptions: -# default: -# tmpfs: false -# options: "" -# ssd: -# tmpfs: true -# options: "defaults,noatime,mode=1777" -# -tmpOptions: - default: - tmpfs: false - options: "" - ssd: - tmpfs: true - options: "defaults,noatime,mode=1777" diff --git a/src/modules/fstab/fstab.schema.yaml b/src/modules/fstab/fstab.schema.yaml deleted file mode 100644 index e298a9d040..0000000000 --- a/src/modules/fstab/fstab.schema.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later ---- -$schema: https://json-schema.org/schema# -$id: https://calamares.io/schemas/fstab -additionalProperties: false -type: object -properties: - crypttabOptions: { type: string } - tmpOptions: - type: object - additionalProperties: false - properties: - "default": - type: object - additionalProperties: false - properties: - tmpfs: { type: boolean } - options: { type: string } - ssd: - type: object - additionalProperties: false - properties: - tmpfs: { type: boolean } - options: { type: string } - required: [ "default" ] -required: - - tmpOptions diff --git a/src/modules/fstab/main.py b/src/modules/fstab/main.py deleted file mode 100755 index 78cae63494..0000000000 --- a/src/modules/fstab/main.py +++ /dev/null @@ -1,432 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2014 Aurélien Gâteau -# SPDX-FileCopyrightText: 2016 Teo Mrnjavac -# SPDX-FileCopyrightText: 2017 Alf Gaida -# SPDX-FileCopyrightText: 2019 Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later -# -# Calamares is Free Software: see the License-Identifier above. -# - -import os -import re -import copy - -import libcalamares - -import gettext -_ = gettext.translation("calamares-python", - localedir=libcalamares.utils.gettext_path(), - languages=libcalamares.utils.gettext_languages(), - fallback=True).gettext - - -def pretty_name(): - return _("Writing fstab.") - - -FSTAB_HEADER = """# /etc/fstab: static file system information. -# -# Use 'blkid' to print the universally unique identifier for a device; this may -# be used with UUID= as a more robust way to name devices that works even if -# disks are added and removed. See fstab(5). -# -# """ - -CRYPTTAB_HEADER = """# /etc/crypttab: mappings for encrypted partitions. -# -# Each mapped device will be created in /dev/mapper, so your /etc/fstab -# should use the /dev/mapper/ paths for encrypted devices. -# -# See crypttab(5) for the supported syntax. -# -# NOTE: You need not list your root (/) partition here, but it must be set up -# beforehand by the initramfs (/etc/mkinitcpio.conf). The same applies -# to encrypted swap, which should be set up with mkinitcpio-openswap -# for resume support. -# -# """ - -# Turn Parted filesystem names into fstab names -FS_MAP = { - "fat16": "vfat", - "fat32": "vfat", - "linuxswap": "swap", -} - - -def mkdir_p(path): - """ Create directory. - - :param path: - """ - if not os.path.exists(path): - os.makedirs(path) - - -def is_ssd_disk(disk_name): - """ Checks if given disk is actually a ssd disk. - - :param disk_name: - :return: - """ - filename = os.path.join("/sys/block", disk_name, "queue/rotational") - - if not os.path.exists(filename): - # Should not happen unless sysfs changes, but better safe than sorry - return False - - with open(filename) as sysfile: - return sysfile.read() == "0\n" - - -def disk_name_for_partition(partition): - """ Returns disk name for each found partition. - - :param partition: - :return: - """ - name = os.path.basename(partition["device"]) - - if name.startswith("mmcblk") or name.startswith("nvme"): - # Typical mmc device is mmcblk0p1, nvme looks like nvme0n1p2 - return re.sub("p[0-9]+$", "", name) - - return re.sub("[0-9]+$", "", name) - - -class FstabGenerator(object): - def __init__(self, partitions, root_mount_point, mount_options_list, - crypttab_options, tmp_options): - self.partitions = partitions - self.root_mount_point = root_mount_point - self.mount_options_list = mount_options_list - self.crypttab_options = crypttab_options - self.tmp_options = tmp_options - self.ssd_disks = set() - self.root_is_ssd = False - - def run(self): - """ Calls needed sub routines. - - :return: - """ - self.find_ssd_disks() - self.generate_fstab() - self.generate_crypttab() - self.create_mount_points() - - return None - - def find_ssd_disks(self): - """ Checks for ssd disks """ - disks = {disk_name_for_partition(x) for x in self.partitions} - self.ssd_disks = {x for x in disks if is_ssd_disk(x)} - - def generate_crypttab(self): - """ Create crypttab. """ - mkdir_p(os.path.join(self.root_mount_point, "etc")) - crypttab_path = os.path.join(self.root_mount_point, "etc", "crypttab") - - with open(crypttab_path, "w") as crypttab_file: - print(CRYPTTAB_HEADER, file=crypttab_file) - - for partition in self.partitions: - dct = self.generate_crypttab_line_info(partition) - - if dct: - self.print_crypttab_line(dct, file=crypttab_file) - - def generate_crypttab_line_info(self, partition): - """ Generates information for each crypttab entry. """ - if "luksMapperName" not in partition or "luksUuid" not in partition: - return None - - mapper_name = partition["luksMapperName"] - luks_uuid = partition["luksUuid"] - if not mapper_name or not luks_uuid: - return None - - password = "/crypto_keyfile.bin" - crypttab_options = self.crypttab_options - - # Set crypttab password for partition to none and remove crypttab options - # if root partition was not encrypted - if any([p["mountPoint"] == "/" - and "luksMapperName" not in p - for p in self.partitions]): - password = "none" - crypttab_options = "" - # on root partition when /boot is unencrypted - 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, - device="UUID=" + luks_uuid, - password=password, - options=crypttab_options, - ) - - def print_crypttab_line(self, dct, file=None): - """ Prints line to '/etc/crypttab' file. """ - line = "{:21} {:<45} {} {}".format(dct["name"], - dct["device"], - dct["password"], - dct["options"], - ) - - print(line, file=file) - - def generate_fstab(self): - """ Create fstab. """ - mkdir_p(os.path.join(self.root_mount_point, "etc")) - fstab_path = os.path.join(self.root_mount_point, "etc", "fstab") - - with open(fstab_path, "w") as fstab_file: - print(FSTAB_HEADER, file=fstab_file) - - for partition in self.partitions: - # Special treatment for a btrfs subvolumes - if (partition["fs"] == "btrfs" - and partition["mountPoint"] == "/"): - # Subvolume list has been created in mount.conf and curated in mount module, - # so all subvolumes here should be safe to add to fstab - btrfs_subvolumes = libcalamares.globalstorage.value("btrfsSubvolumes") - for s in btrfs_subvolumes: - mount_entry = copy.deepcopy(partition) - mount_entry["mountPoint"] = s["mountPoint"] - mount_entry["subvol"] = s["subvolume"] - dct = self.generate_fstab_line_info(mount_entry) - if dct: - self.print_fstab_line(dct, file=fstab_file) - elif partition["fs"] != "zfs": # zfs partitions don't need an entry in fstab - dct = self.generate_fstab_line_info(partition) - if dct: - self.print_fstab_line(dct, file=fstab_file) - - if self.root_is_ssd: - # Old behavior was to mount /tmp as tmpfs - # New behavior is to use tmpOptions to decide - # if mounting /tmp as tmpfs and which options to use - ssd = self.tmp_options.get("ssd", {}) - if not ssd: - ssd = self.tmp_options.get("default", {}) - # Default to True to mimic old behavior - tmpfs = ssd.get("tmpfs", True) - - if tmpfs: - options = ssd.get("options", "defaults,noatime,mode=1777") - # Mount /tmp on a tmpfs - dct = dict(device="tmpfs", - mount_point="/tmp", - fs="tmpfs", - options=options, - check=0, - ) - self.print_fstab_line(dct, file=fstab_file) - - def generate_fstab_line_info(self, partition): - """ - Generates information (a dictionary of fstab-fields) - for the given @p partition. - """ - # Some "fs" names need special handling in /etc/fstab, so remap them. - filesystem = partition["fs"].lower() - filesystem = FS_MAP.get(filesystem, filesystem) - luks_mapper_name = partition.get("luksMapperName", None) - mount_point = partition["mountPoint"] - disk_name = disk_name_for_partition(partition) - is_ssd = disk_name in self.ssd_disks - - # Swap partitions are called "linuxswap" by parted. - # That "fs" is visible in GS, but that gets mapped - # to "swap", above, because that's the spelling needed in /etc/fstab - if not mount_point and not filesystem == "swap": - return None - if not mount_point: - mount_point = "swap" - - if filesystem == "swap" and not partition.get("claimed", None): - libcalamares.utils.debug("Ignoring foreign swap {!s} {!s}".format(disk_name, partition.get("uuid", None))) - return None - - options = self.get_mount_options(mount_point) - - if mount_point == "/" and filesystem != "btrfs": - check = 1 - elif mount_point and mount_point != "swap" and filesystem != "btrfs": - check = 2 - else: - check = 0 - - if mount_point == "/": - self.root_is_ssd = is_ssd - - # If there's a set-and-not-empty subvolume set, add it - if filesystem == "btrfs" and partition.get("subvol",None): - options = "subvol={},".format(partition["subvol"]) + options - - device = None - if luks_mapper_name: - device = "/dev/mapper/" + luks_mapper_name - elif partition["uuid"]: - device = "UUID=" + partition["uuid"] - else: - device = partition["device"] - - if not device: - # TODO: we get here when the user mounted a previously encrypted partition - # This should be catched early in the process - return None - - return dict(device=device, - mount_point=mount_point, - fs=filesystem, - options=options, - check=check, - ) - - def print_fstab_line(self, dct, file=None): - """ Prints line to '/etc/fstab' file. """ - line = "{:41} {:<14} {:<7} {:<10} 0 {}".format(dct["device"], - dct["mount_point"], - dct["fs"], - dct["options"], - dct["check"], - ) - print(line, file=file) - - def create_mount_points(self): - """ Creates mount points """ - for partition in self.partitions: - if partition["mountPoint"]: - mkdir_p(self.root_mount_point + partition["mountPoint"]) - - def get_mount_options(self, mountpoint): - """ - Returns the mount options for a given mountpoint - - :param mountpoint: A string containing the mountpoint for the fstab entry - :return: A string containing the mount options for the entry or "defaults" if nothing is found - """ - mount_options_item = next((x for x in self.mount_options_list if x.get("mountpoint") == mountpoint), None) - if mount_options_item: - return mount_options_item.get("option_string", "defaults") - else: - return "defaults" - - -def create_swapfile(root_mount_point, root_btrfs): - """ - Creates /swapfile in @p root_mount_point ; if the root filesystem - is on btrfs, then handle some btrfs specific features as well, - as documented in - https://wiki.archlinux.org/index.php/Swap#Swap_file - - The swapfile-creation covers progress from 0.2 to 0.5 - """ - libcalamares.job.setprogress(0.2) - if root_btrfs: - # btrfs swapfiles must reside on a subvolume that is not snapshotted to prevent file system corruption - swapfile_path = os.path.join(root_mount_point, "swap/swapfile") - with open(swapfile_path, "wb") as f: - pass - libcalamares.utils.host_env_process_output(["chattr", "+C", "+m", swapfile_path]) # No Copy-on-Write, no compression - else: - swapfile_path = os.path.join(root_mount_point, "swapfile") - with open(swapfile_path, "wb") as f: - pass - # Create the swapfile; swapfiles are small-ish - zeroes = bytes(16384) - with open(swapfile_path, "wb") as f: - total = 0 - desired_size = 512 * 1024 * 1024 # 512MiB - while total < desired_size: - chunk = f.write(zeroes) - if chunk < 1: - libcalamares.utils.debug("Short write on {!s}, cancelling.".format(swapfile_path)) - break - libcalamares.job.setprogress(0.2 + 0.3 * ( total / desired_size ) ) - total += chunk - os.chmod(swapfile_path, 0o600) - libcalamares.utils.host_env_process_output(["mkswap", swapfile_path]) - libcalamares.job.setprogress(0.5) - - -def run(): - """ Configures fstab. - - :return: - """ - global_storage = libcalamares.globalstorage - conf = libcalamares.job.configuration - partitions = global_storage.value("partitions") - root_mount_point = global_storage.value("rootMountPoint") - - if not partitions: - libcalamares.utils.warning("partitions is empty, {!s}" - .format(partitions)) - return (_("Configuration Error"), - _("No partitions are defined for
{!s}
to use.") - .format("fstab")) - if not root_mount_point: - libcalamares.utils.warning("rootMountPoint is empty, {!s}" - .format(root_mount_point)) - return (_("Configuration Error"), - _("No root mount point is given for
{!s}
to use.") - .format("fstab")) - - # This follows the GS settings from the partition module's Config object - swap_choice = global_storage.value( "partitionChoices" ) - if swap_choice: - swap_choice = swap_choice.get( "swap", None ) - if swap_choice and swap_choice == "file": - # There's no formatted partition for it, so we'll sneak in an entry - root_partitions = [ p["fs"].lower() for p in partitions if p["mountPoint"] == "/" ] - root_btrfs = (root_partitions[0] == "btrfs") if root_partitions else False - if root_btrfs: - partitions.append( dict(fs="swap", mountPoint=None, claimed=True, device="/swap/swapfile", uuid=None) ) - else: - partitions.append( dict(fs="swap", mountPoint=None, claimed=True, device="/swapfile", uuid=None) ) - else: - swap_choice = None - - libcalamares.job.setprogress(0.1) - mount_options_list = global_storage.value("mountOptionsList") - crypttab_options = conf.get("crypttabOptions", "luks") - tmp_options = conf.get("tmpOptions", {}) - - # We rely on mount_options having a default; if there wasn't one, - # bail out with a meaningful error. - if not mount_options_list: - libcalamares.utils.warning("No mount options defined, {!s} partitions".format(len(partitions))) - return (_("Configuration Error"), - _("No
{!s}
configuration is given for
{!s}
to use.") - .format("mountOptions", "fstab")) - - generator = FstabGenerator(partitions, - root_mount_point, - mount_options_list, - crypttab_options, - tmp_options) - - if swap_choice is not None: - libcalamares.job.setprogress(0.2) - root_partitions = [ p["fs"].lower() for p in partitions if p["mountPoint"] == "/" ] - root_btrfs = (root_partitions[0] == "btrfs") if root_partitions else False - create_swapfile(root_mount_point, root_btrfs) - - try: - libcalamares.job.setprogress(0.5) - return generator.run() - finally: - libcalamares.job.setprogress(1.0) diff --git a/src/modules/fstab/module.desc b/src/modules/fstab/module.desc deleted file mode 100644 index 77cb7adbca..0000000000 --- a/src/modules/fstab/module.desc +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -type: "job" -name: "fstab" -interface: "python" -script: "main.py" diff --git a/src/modules/fstab/test.yaml b/src/modules/fstab/test.yaml deleted file mode 100644 index cd20345713..0000000000 --- a/src/modules/fstab/test.yaml +++ /dev/null @@ -1,16 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -rootMountPoint: /tmp/mount -partitions: - - device: /dev/sda1 - fs: ext4 - mountPoint: / - uuid: 2a00f1d5-1217-49a7-bedd-b55c85764732 - - device: /dev/sda2 - fs: swap - uuid: 59406569-446f-4730-a874-9f6b4b44fee3 - mountPoint: - - device: /dev/sdb1 - fs: btrfs - mountPoint: /home - uuid: 59406569-abcd-1234-a874-9f6b4b44fee3 diff --git a/src/modules/fstab/test2.yaml b/src/modules/fstab/test2.yaml deleted file mode 100644 index 0e91bf6491..0000000000 --- a/src/modules/fstab/test2.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# This test shows how btrfs root would work -rootMountPoint: /tmp/mount -partitions: - - device: /dev/sda1 - fs: btrfs - mountPoint: / - uuid: 2a00f1d5-1217-49a7-bedd-b55c85764732 - - device: /dev/sda2 - fs: swap - uuid: 59406569-446f-4730-a874-9f6b4b44fee3 - mountPoint: - - device: /dev/sdb1 - fs: btrfs - mountPoint: /home - uuid: 59406569-abcd-1234-a874-9f6b4b44fee3 -btrfsSubvolumes: - - mountPoint: / - subvolume: "@ROOT" - - mountPoint: /var - subvolume: "@var" - - mountPoint: /usr/local - subvolume: "@local" diff --git a/src/modules/grubcfg/grubcfg.conf b/src/modules/grubcfg/grubcfg.conf deleted file mode 100644 index 189d4c2a9c..0000000000 --- a/src/modules/grubcfg/grubcfg.conf +++ /dev/null @@ -1,51 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Create, overwrite or update /etc/default/grub in the target system. -# -# Write lines to /etc/default/grub (in the target system) based -# on calculated values and the values set in the *defaults* key -# in this configuration file. -# -# Calculated values are: -# - GRUB_DISTRIBUTOR, branding module, *bootloaderEntryName* (this -# string is sanitized, and see also setting *keep_distributor*) -# - GRUB_ENABLE_CRYPTODISK, based on the presence of filesystems -# that use LUKS -# - GRUB_CMDLINE_LINUX_DEFAULT, adding LUKS setup and plymouth -# support to the kernel. - ---- -# If set to true, always creates /etc/default/grub from scratch even if the file -# already existed. If set to false, edits the existing file instead. -overwrite: false - -# If set to true, prefer to write files in /etc/default/grub.d/ -# rather than the single file /etc/default/grub. If this is set, -# Calamares will write /etc/default/grub.d/00Calamares instead. -prefer_grub_d: false - -# If set to true, an **existing** setting for GRUB_DISTRIBUTOR is -# kept, not updated to the *bootloaderEntryName* from the branding file. -# Use this if the GRUB_DISTRIBUTOR setting in the file is "smart" in -# some way (e.g. uses shell-command substitution). -keep_distributor: false - -# The default kernel params that should always be applied. -# This is an array of strings. If it is unset, the default is -# `["quiet"]`. To avoid the default, explicitly set this key -# to an empty list, `[]`. -kernel_params: [ "quiet" ] - -# Default entries to write to /etc/default/grub if it does not exist yet or if -# we are overwriting it. -# -defaults: - GRUB_TIMEOUT: 5 - GRUB_DEFAULT: "saved" - GRUB_DISABLE_SUBMENU: true - GRUB_TERMINAL_OUTPUT: "console" - GRUB_DISABLE_RECOVERY: true - -# Set to true to force defaults to be used even when not overwriting -always_use_defaults: false diff --git a/src/modules/grubcfg/grubcfg.schema.yaml b/src/modules/grubcfg/grubcfg.schema.yaml deleted file mode 100644 index c04c0b79f5..0000000000 --- a/src/modules/grubcfg/grubcfg.schema.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later ---- -$schema: https://json-schema.org/schema# -$id: https://calamares.io/schemas/grubcfg -additionalProperties: false -type: object -properties: - overwrite: { type: boolean, default: false } - keep_distributor: { type: boolean, default: false } - prefer_grub_d: { type: boolean, default: false } - kernel_params: { type: array, items: { type: string } } - defaults: - type: object - additionalProperties: true # Other fields are acceptable - properties: - GRUB_TIMEOUT: { type: integer } - GRUB_DEFAULT: { type: string } - GRUB_DISABLE_SUBMENU: { type: boolean, default: true } - GRUB_TERMINAL_OUTPUT: { type: string } - GRUB_DISABLE_RECOVERY: { type: boolean, default: true } - required: [ GRUB_TIMEOUT, GRUB_DEFAULT ] - always_use_defaults: { type: boolean, default: false } diff --git a/src/modules/grubcfg/main.py b/src/modules/grubcfg/main.py deleted file mode 100644 index 47944640d9..0000000000 --- a/src/modules/grubcfg/main.py +++ /dev/null @@ -1,329 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2014-2015 Philip Müller -# SPDX-FileCopyrightText: 2015-2017 Teo Mrnjavac -# SPDX-FileCopyrightText: 2017 Alf Gaida -# SPDX-FileCopyrightText: 2017 2019, Adriaan de Groot -# SPDX-FileCopyrightText: 2017-2018 Gabriel Craciunescu -# SPDX-License-Identifier: GPL-3.0-or-later -# -# Calamares is Free Software: see the License-Identifier above. -# - -import libcalamares -import fileinput -import os -import re -import shutil - -import gettext -_ = gettext.translation("calamares-python", - localedir=libcalamares.utils.gettext_path(), - languages=libcalamares.utils.gettext_languages(), - fallback=True).gettext - - -def pretty_name(): - return _("Configure GRUB.") - - -def get_grub_config_path(root_mount_point): - """ - Figures out where to put the grub config files. Returns - a the full path of a file inside that - directory, as "the config file". - - Returns a path into @p root_mount_point. - """ - default_dir = os.path.join(root_mount_point, "etc/default") - default_config_file = "grub" - - if "prefer_grub_d" in libcalamares.job.configuration and libcalamares.job.configuration["prefer_grub_d"]: - possible_dir = os.path.join(root_mount_point, "etc/default/grub.d") - if os.path.exists(possible_dir) and os.path.isdir(possible_dir): - default_dir = possible_dir - default_config_file = "00calamares" - - if not os.path.exists(default_dir): - try: - os.mkdir(default_dir) - except Exception as error: - # exception as error is still redundant, but it print out the error - # identify a solution for each exception and - # if possible and code it within. - libcalamares.utils.debug(f"Failed to create {default_dir}") - libcalamares.utils.debug(f"{error}") - raise - - return os.path.join(default_dir, default_config_file) - - -def get_zfs_root(): - """ - Looks in global storage to find the zfs root - - :return: A string containing the path to the zfs root or None if it is not found - """ - - zfs = libcalamares.globalstorage.value("zfsDatasets") - - if not zfs: - libcalamares.utils.warning("Failed to locate zfs dataset list") - return None - - # Find the root dataset - for dataset in zfs: - try: - if dataset["mountpoint"] == "/": - return dataset["zpool"] + "/" + dataset["dsName"] - except KeyError: - # This should be impossible - libcalamares.utils.warning("Internal error handling zfs dataset") - raise - - return None - - -def update_existing_config(default_grub, grub_config_items): - """ - Updates the existing grub configuration file with any items present in @p grub_config_items - - Items that exist in the file will be updated and new items will be appended to the end - - :param default_grub: The absolute path to the grub config file - :param grub_config_items: A dict holding the key value pairs representing the items - """ - - default_grub_orig = default_grub + ".calamares" - shutil.move(default_grub, default_grub_orig) - - with open(default_grub, "w") as grub_file: - with open(default_grub_orig, "r") as grub_orig_file: - for line in grub_orig_file.readlines(): - line = line.strip() - if "=" in line: - # This may be a key, strip the leading comment if it has one - key = line.lstrip("#").split("=")[0].strip() - - # check if this is noe of the keys we care about - if key in grub_config_items.keys(): - print(f"{key}={grub_config_items[key]}", file=grub_file) - del grub_config_items[key] - else: - print(line, file=grub_file) - else: - print(line, file=grub_file) - - if len(grub_config_items) != 0: - for dict_key, dict_val in grub_config_items.items(): - print(f"{dict_key}={dict_val}", file=grub_file) - - os.remove(default_grub_orig) - - -def modify_grub_default(partitions, root_mount_point, distributor): - """ - Configures '/etc/default/grub' for hibernation and plymouth. - - @see bootloader/main.py, for similar handling of kernel parameters - - :param partitions: - :param root_mount_point: - :param distributor: name of the distributor to fill in for - GRUB_DISTRIBUTOR. Must be a string. If the job setting - *keep_distributor* is set, then this is only used if no - GRUB_DISTRIBUTOR is found at all (otherwise, when *keep_distributor* - is set, the GRUB_DISTRIBUTOR lines are left unchanged). - If *keep_distributor* is unset or false, then GRUB_DISTRIBUTOR - is always updated to set this value. - :return: - """ - default_grub = get_grub_config_path(root_mount_point) - distributor = distributor.replace("'", "'\\''") - dracut_bin = libcalamares.utils.target_env_call( - ["sh", "-c", "which dracut"] - ) - plymouth_bin = libcalamares.utils.target_env_call( - ["sh", "-c", "which plymouth"] - ) - uses_systemd_hook = libcalamares.utils.target_env_call( - ["sh", "-c", "grep -q \"^HOOKS.*systemd\" /etc/mkinitcpio.conf"] - ) == 0 - # Shell exit value 0 means success - have_plymouth = plymouth_bin == 0 - use_systemd_naming = dracut_bin == 0 or uses_systemd_hook - - use_splash = "" - swap_uuid = "" - swap_outer_uuid = "" - swap_outer_mappername = None - no_save_default = False - unencrypted_separate_boot = any(p["mountPoint"] == "/boot" and "luksMapperName" not in p for p in partitions) - # If there is no dracut, and the root partition is ZFS, this gets set below - zfs_root_path = None - - for partition in partitions: - if partition["mountPoint"] in ("/", "/boot") and partition["fs"] in ("btrfs", "f2fs", "zfs"): - no_save_default = True - break - - if have_plymouth: - use_splash = "splash" - - cryptdevice_params = [] - - if use_systemd_naming: - for partition in partitions: - if partition["fs"] == "linuxswap" and not partition.get("claimed", None): - # Skip foreign swap - continue - has_luks = "luksMapperName" in partition - if partition["fs"] == "linuxswap" and not has_luks: - swap_uuid = partition["uuid"] - - if partition["fs"] == "linuxswap" and has_luks: - swap_outer_uuid = partition["luksUuid"] - swap_outer_mappername = partition["luksMapperName"] - - if partition["mountPoint"] == "/" and has_luks: - cryptdevice_params = [f"rd.luks.uuid={partition['luksUuid']}"] - if not unencrypted_separate_boot and uses_systemd_hook: - cryptdevice_params.append("rd.luks.key=/crypto_keyfile.bin") - else: - for partition in partitions: - if partition["fs"] == "linuxswap" and not partition.get("claimed", None): - # Skip foreign swap - continue - has_luks = "luksMapperName" in partition - if partition["fs"] == "linuxswap" and not has_luks: - swap_uuid = partition["uuid"] - - if partition["fs"] == "linuxswap" and has_luks: - swap_outer_mappername = partition["luksMapperName"] - - if partition["mountPoint"] == "/" and has_luks: - cryptdevice_params = [ - f"cryptdevice=UUID={partition['luksUuid']}:{partition['luksMapperName']}", - f"root=/dev/mapper/{partition['luksMapperName']}" - ] - - if partition["fs"] == "zfs" and partition["mountPoint"] == "/": - zfs_root_path = get_zfs_root() - - kernel_params = libcalamares.job.configuration.get("kernel_params", ["quiet"]) - - # Currently, grub doesn't detect this properly so it must be set manually - if zfs_root_path: - kernel_params.insert(0, "zfs=" + zfs_root_path) - - if cryptdevice_params: - kernel_params.extend(cryptdevice_params) - - if use_splash: - kernel_params.append(use_splash) - - if swap_uuid: - kernel_params.append(f"resume=UUID={swap_uuid}") - - if use_systemd_naming and swap_outer_uuid: - kernel_params.append(f"rd.luks.uuid={swap_outer_uuid}") - if swap_outer_mappername: - kernel_params.append(f"resume=/dev/mapper/{swap_outer_mappername}") - - overwrite = libcalamares.job.configuration.get("overwrite", False) - - grub_config_items = {} - # read the lines we need from the existing config - if os.path.exists(default_grub) and not overwrite: - with open(default_grub, 'r') as grub_file: - lines = [x.strip() for x in grub_file.readlines()] - - for line in lines: - if line.startswith("GRUB_CMDLINE_LINUX_DEFAULT"): - existing_params = re.sub(r"^GRUB_CMDLINE_LINUX_DEFAULT\s*=\s*", "", line).strip("\"'").split() - - for existing_param in existing_params: - existing_param_name = existing_param.split("=")[0].strip() - - # Ensure we aren't adding duplicated params - param_exists = False - for param in kernel_params: - if param.split("=")[0].strip() == existing_param_name: - param_exists = True - break - if not param_exists and existing_param_name not in ["quiet", "resume", "splash"]: - kernel_params.append(existing_param) - - elif line.startswith("GRUB_DISTRIBUTOR") and libcalamares.job.configuration.get("keep_distributor", False): - distributor_parts = line.split("=") - if len(distributor_parts) > 1: - distributor = distributor_parts[1].strip("'\"") - - # If a filesystem grub can't write to is used, disable save default - if no_save_default and line.strip().startswith("GRUB_SAVEDEFAULT"): - grub_config_items["GRUB_SAVEDEFAULT"] = "false" - - always_use_defaults = libcalamares.job.configuration.get("always_use_defaults", False) - - # If applicable add the items from defaults to the dict containing the grub config to wirte/modify - if always_use_defaults or overwrite or not os.path.exists(default_grub): - if "defaults" in libcalamares.job.configuration: - for key, value in libcalamares.job.configuration["defaults"].items(): - if isinstance(value, bool): - if value: - escaped_value = "true" - else: - escaped_value = "false" - else: - escaped_value = str(value).replace("'", "'\\''") - - grub_config_items[key] = f"'{escaped_value}'" - - grub_config_items['GRUB_CMDLINE_LINUX_DEFAULT'] = f"'{' '.join(kernel_params)}'" - grub_config_items["GRUB_DISTRIBUTOR"] = f"'{distributor}'" - - if cryptdevice_params and not unencrypted_separate_boot: - grub_config_items["GRUB_ENABLE_CRYPTODISK"] = "y" - - if overwrite or not os.path.exists(default_grub) or libcalamares.job.configuration.get("prefer_grub_d", False): - with open(default_grub, 'w') as grub_file: - for key, value in grub_config_items.items(): - grub_file.write(f"{key}={value}\n") - else: - update_existing_config(default_grub, grub_config_items) - - return None - - -def run(): - """ - Calls routine with given parameters to modify '/etc/default/grub'. - - :return: - """ - fw_type = libcalamares.globalstorage.value("firmwareType") - partitions = libcalamares.globalstorage.value("partitions") - root_mount_point = libcalamares.globalstorage.value("rootMountPoint") - branding = libcalamares.globalstorage.value("branding") - if branding is None: - distributor = None - else: - distributor = branding["bootloaderEntryName"] - - if libcalamares.globalstorage.value("bootLoader") is None and fw_type != "efi": - return None - - if fw_type == "efi": - esp_found = False - - for partition in partitions: - if partition["mountPoint"] == libcalamares.globalstorage.value("efiSystemPartition"): - esp_found = True - - if not esp_found: - return None - - return modify_grub_default(partitions, root_mount_point, distributor) diff --git a/src/modules/grubcfg/module.desc b/src/modules/grubcfg/module.desc deleted file mode 100644 index 293e75ba7d..0000000000 --- a/src/modules/grubcfg/module.desc +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -type: "job" -name: "grubcfg" -interface: "python" -script: "main.py" diff --git a/src/modules/grubcfg/tests/1.global b/src/modules/grubcfg/tests/1.global deleted file mode 100644 index 504931063d..0000000000 --- a/src/modules/grubcfg/tests/1.global +++ /dev/null @@ -1,5 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -branding: - bootloaderEntryName: generic diff --git a/src/modules/grubcfg/tests/2.global b/src/modules/grubcfg/tests/2.global deleted file mode 100644 index 1e01c6b955..0000000000 --- a/src/modules/grubcfg/tests/2.global +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -firmwareType: bios -bootLoader: grub -rootMountPoint: /tmp/calamares/grubcfg-test-2 - -branding: - bootloaderEntryName: generic -partitions: [] - diff --git a/src/modules/grubcfg/tests/2.job b/src/modules/grubcfg/tests/2.job deleted file mode 100644 index 5265ef5c86..0000000000 --- a/src/modules/grubcfg/tests/2.job +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -overwrite: true -keep_distributor: false -defaults: - GRUB_TIMEOUT: 5 - GRUB_DEFAULT: "saved" - GRUB_DISABLE_SUBMENU: true - GRUB_TERMINAL_OUTPUT: "console" - GRUB_DISABLE_RECOVERY: true diff --git a/src/modules/grubcfg/tests/3.global b/src/modules/grubcfg/tests/3.global deleted file mode 100644 index 3eda6d5a18..0000000000 --- a/src/modules/grubcfg/tests/3.global +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -firmwareType: bios -bootLoader: grub -rootMountPoint: /tmp/calamares/grubcfg-test-3 - -branding: - bootloaderEntryName: generic -partitions: [] - diff --git a/src/modules/grubcfg/tests/3.job b/src/modules/grubcfg/tests/3.job deleted file mode 100644 index 94f3943730..0000000000 --- a/src/modules/grubcfg/tests/3.job +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -overwrite: true -prefer_grub_d: true # But it doesn't exist -keep_distributor: false -defaults: - GRUB_TIMEOUT: 5 - GRUB_DEFAULT: "saved" - GRUB_DISABLE_SUBMENU: true - GRUB_TERMINAL_OUTPUT: "console" - GRUB_DISABLE_RECOVERY: true diff --git a/src/modules/grubcfg/tests/4.global b/src/modules/grubcfg/tests/4.global deleted file mode 100644 index 7d4579543b..0000000000 --- a/src/modules/grubcfg/tests/4.global +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -firmwareType: bios -bootLoader: grub -rootMountPoint: /tmp/calamares/grubcfg-test-4 - -branding: - bootloaderEntryName: generic -partitions: [] - diff --git a/src/modules/grubcfg/tests/4.job b/src/modules/grubcfg/tests/4.job deleted file mode 100644 index 4fdc2e25cc..0000000000 --- a/src/modules/grubcfg/tests/4.job +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -overwrite: true -prefer_grub_d: true -keep_distributor: false -defaults: - GRUB_TIMEOUT: 5 - GRUB_DEFAULT: "saved" - GRUB_DISABLE_SUBMENU: true - GRUB_TERMINAL_OUTPUT: "console" - GRUB_DISABLE_RECOVERY: true diff --git a/src/modules/grubcfg/tests/CMakeTests.txt b/src/modules/grubcfg/tests/CMakeTests.txt deleted file mode 100644 index 7ecfffcebb..0000000000 --- a/src/modules/grubcfg/tests/CMakeTests.txt +++ /dev/null @@ -1,17 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Special cases for grubcfg configuration tests: -# - 2.global specifies /tmp/calamares as the rootMountPath, -# so we end up editing files there. Create the directory -# beforehand, so the test doesn't blow up. - -add_test( - NAME make-grubcfg-dirs - COMMAND - ${CMAKE_COMMAND} -E make_directory /tmp/calamares/grubcfg-test-2/etc/default - /tmp/calamares/grubcfg-test-3/etc/default /tmp/calamares/grubcfg-test-4/etc/default/grub.d -) -set_tests_properties(load-grubcfg-2 PROPERTIES DEPENDS make-grubcfg-dirs) -set_tests_properties(load-grubcfg-3 PROPERTIES DEPENDS make-grubcfg-dirs) -set_tests_properties(load-grubcfg-4 PROPERTIES DEPENDS make-grubcfg-dirs) diff --git a/src/modules/hostinfo/CMakeLists.txt b/src/modules/hostinfo/CMakeLists.txt deleted file mode 100644 index d432bd91dd..0000000000 --- a/src/modules/hostinfo/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# - -# Configuration for hostinfo -# -# There isn't anything to configure for the hostinfo module. -# -# Hostinfo puts information about the host system into Calamares -# GlobalStorage. This information is generally unchanging. Put -# this module somewhere early in the exec: section to pick up -# the variables. Use a contextualprocess module later to -# react to the values, if needed. -# -# GlobalStorage keys: -# -# - *hostOS* the OS this module was built under; value is "Linux" or -# "FreeBSD" or blank. -# - *hostOSName* the NAME value from /etc/os-release if it exists, -# otherwise the same as *hostOS*. -# - *hostCPU* the make (brand) of the CPU, if it can be determined. -# Values are "Intel" or "AMD" or blank. - -calamares_add_plugin(hostinfo - TYPE job - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - HostInfoJob.cpp - SHARED_LIB - NO_CONFIG -) - -target_link_libraries(calamares_job_hostinfo PRIVATE ${kfname}::CoreAddons) - -calamares_add_test(hostinfotest SOURCES Tests.cpp HostInfoJob.cpp LIBRARIES yamlcpp::yamlcpp) diff --git a/src/modules/hostinfo/HostInfoJob.cpp b/src/modules/hostinfo/HostInfoJob.cpp deleted file mode 100644 index d09de3ae21..0000000000 --- a/src/modules/hostinfo/HostInfoJob.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "HostInfoJob.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "utils/Logger.h" -#include "utils/System.h" -#include "utils/Units.h" - -#include -#include - -#include - -#ifdef Q_OS_FREEBSD -#include - -#include -#endif - -HostInfoJob::HostInfoJob( QObject* parent ) - : Calamares::CppJob( parent ) -{ -} - -HostInfoJob::~HostInfoJob() {} - -QString -HostInfoJob::prettyName() const -{ - return tr( "Collecting information about your machine…", "@status" ); -} - -QString -hostOS() -{ -#if defined( Q_OS_FREEBSD ) - return QStringLiteral( "FreeBSD" ); -#elif defined( Q_OS_LINUX ) - return QStringLiteral( "Linux" ); -#else - return QStringLiteral( "" ); -#endif -} - -QString -hostOSName() -{ - KOSRelease r; - if ( !r.name().isEmpty() ) - { - return r.name(); - } - return hostOS(); -} - -static QString -hostCPUmatch( const QString& s ) -{ - const QString line = s.toLower(); - if ( line.contains( "intel" ) ) - { - return QStringLiteral( "Intel" ); - } - else if ( line.contains( "amd" ) ) - { - return QStringLiteral( "AMD" ); - } - return QString(); -} - -#if defined( Q_OS_FREEBSD ) -QString -hostCPU_FreeBSD() -{ - constexpr const size_t sysctl_buffer_size = 128; - char sysctl_buffer[ sysctl_buffer_size ]; - size_t s = sysctl_buffer_size; - - memset( sysctl_buffer, 0, sizeof( sysctl_buffer ) ); - int r = sysctlbyname( "hw.model", &sysctl_buffer, &s, NULL, 0 ); - if ( r ) - { - return QString(); - } - - sysctl_buffer[ sysctl_buffer_size - 1 ] = 0; - QString model( sysctl_buffer ); - return hostCPUmatch( model ); -} -#endif - -#if defined( Q_OS_LINUX ) -static QString -hostCPUmatchARM( const QString& s ) -{ - /* The "CPU implementer" line is for ARM CPUs in general. - * - * The specific value given distinguishes *which designer* - * (or architecture licensee, who cares) produced the current - * silicon. For instance, a list from lscpu-arm.c (Linux kernel) - * shows this: - * - static const struct hw_impl hw_implementer[] = { - { 0x41, arm_part, "ARM" }, - { 0x42, brcm_part, "Broadcom" }, - { 0x43, cavium_part, "Cavium" }, - { 0x44, dec_part, "DEC" }, - { 0x48, hisi_part, "HiSilicon" }, - { 0x4e, nvidia_part, "Nvidia" }, - { 0x50, apm_part, "APM" }, - { 0x51, qcom_part, "Qualcomm" }, - { 0x53, samsung_part, "Samsung" }, - { 0x56, marvell_part, "Marvell" }, - { 0x66, faraday_part, "Faraday" }, - { 0x69, intel_part, "Intel" }, - { -1, unknown_part, "unknown" }, - }; - * - * Since the specific implementor isn't interesting, just - * map everything to "ARM". - */ - return QStringLiteral( "ARM" ); -} - -QString -hostCPU_Linux() -{ - QFile cpuinfo( "/proc/cpuinfo" ); - if ( cpuinfo.open( QIODevice::ReadOnly ) ) - { - QTextStream in( &cpuinfo ); - QString line; - while ( in.readLineInto( &line ) ) - { - if ( line.startsWith( "vendor_id" ) ) - { - return hostCPUmatch( line ); - } - if ( line.startsWith( "CPU implementer" ) ) - { - return hostCPUmatchARM( line ); - } - } - } - return QString(); // Not open, or not found -} -#endif - -QString -hostCPU() -{ -#if defined( Q_OS_FREEBSD ) - return hostCPU_FreeBSD(); -#elif defined( Q_OS_LINUX ) - return hostCPU_Linux(); -#else - return QString(); -#endif -} - -Calamares::JobResult -HostInfoJob::exec() -{ - cDebug() << "Collecting host information..."; - - auto* gs = Calamares::JobQueue::instance()->globalStorage(); - gs->insert( "hostOS", hostOS() ); - gs->insert( "hostOSName", hostOSName() ); - gs->insert( "hostCPU", hostCPU() ); - - // Memory can't be negative, so it's reported as unsigned long. - auto ram = Calamares::BytesToMiB( qint64( Calamares::System::instance()->getTotalMemoryB().first ) ); - if ( ram ) - { - gs->insert( "hostRAMMiB", ram ); - } - - return Calamares::JobResult::ok(); -} - -CALAMARES_PLUGIN_FACTORY_DEFINITION( HostInfoJobFactory, registerPlugin< HostInfoJob >(); ) diff --git a/src/modules/hostinfo/HostInfoJob.h b/src/modules/hostinfo/HostInfoJob.h deleted file mode 100644 index b252da7e05..0000000000 --- a/src/modules/hostinfo/HostInfoJob.h +++ /dev/null @@ -1,55 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef HOSTINFOJOB_H -#define HOSTINFOJOB_H - -#include "CppJob.h" -#include "DllMacro.h" -#include "utils/PluginFactory.h" - -#include -#include - -/** @brief the compile-time host OS - * - * Returns "FreeBSD" or "Linux" or empty. - */ -QString hostOS(); - -/** @brief the run-time host OS - * - * Returns os-release NAME information, or if that is blank or not available, - * the same as hostOS(). - */ -QString hostOSName(); - -/** @brief the run-time CPU architecture - * - * Returns "Intel" or "AMD" or blank, if Calamares can determine what - * CPU is currently in use (based on /proc/cpuinfo or hw.model). - */ -QString hostCPU(); - -class PLUGINDLLEXPORT HostInfoJob : public Calamares::CppJob -{ - Q_OBJECT - -public: - explicit HostInfoJob( QObject* parent = nullptr ); - ~HostInfoJob() override; - - QString prettyName() const override; - - Calamares::JobResult exec() override; -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( HostInfoJobFactory ) - -#endif // HOSTINFOJOB_H diff --git a/src/modules/hostinfo/Tests.cpp b/src/modules/hostinfo/Tests.cpp deleted file mode 100644 index 7635b424f7..0000000000 --- a/src/modules/hostinfo/Tests.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ -#include "HostInfoJob.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "Settings.h" - -#include "utils/Logger.h" -#include "utils/Yaml.h" - -#include - -class HostInfoTests : public QObject -{ - Q_OBJECT -public: - HostInfoTests() {} - ~HostInfoTests() override {} - -private Q_SLOTS: - void initTestCase(); - - void testHostOS(); -}; - -void -HostInfoTests::initTestCase() -{ - Logger::setupLogLevel( Logger::LOGDEBUG ); - cDebug() << "HostInfo test started."; -} - -void -HostInfoTests::testHostOS() -{ -#if defined( Q_OS_FREEBSD ) - QString expect( "FreeBSD" ); -#elif defined( Q_OS_LINUX ) - QString expect( "Linux" ); -#else - QString expect( "Plan8" ); // Expect failure -#endif - - QCOMPARE( expect, hostOS() ); - // QCOMPARE( expect, hostOSName() ); // With KOSRelease, returns what the distro calls itself - - // This is a lousy test, too: the implementation reads /proc/cpuinfo - // and that's the only way we could use, too, to find what the "right" - // answer is. - QStringList x86cpunames { QStringLiteral( "Intel" ), QStringLiteral( "AMD" ) }; - QStringList armcpunames { QStringLiteral( "ARM" ) }; - const QString cpu = hostCPU(); - QVERIFY( x86cpunames.contains( cpu ) || armcpunames.contains( cpu ) ); - - // Try to detect family in a different way - QFile modalias( "/sys/devices/system/cpu/modalias" ); - if ( modalias.open( QIODevice::ReadOnly ) ) - { - QString cpumodalias = modalias.readLine(); - if ( cpumodalias.contains( "type:x86" ) ) - { - QVERIFY( x86cpunames.contains( cpu ) ); - } - else if ( cpumodalias.contains( "type:aarch64" ) ) - { - QVERIFY( armcpunames.contains( cpu ) ); - } - else - { - QCOMPARE( cpu, QString( "Unknown CPU modalias '%1'" ).arg( cpumodalias ) ); - } - } -} - - -QTEST_GUILESS_MAIN( HostInfoTests ) - -#include "utils/moc-warnings.h" - -#include "Tests.moc" diff --git a/src/modules/hwclock/main.py b/src/modules/hwclock/main.py deleted file mode 100644 index be9fabf5f0..0000000000 --- a/src/modules/hwclock/main.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2014-2015 Philip Müller -# SPDX-FileCopyrightText: 2014 Teo Mrnjavac -# SPDX-FileCopyrightText: 2017 Alf Gaida -# SPDX-FileCopyrightText: 2017-2018 Gabriel Craciunescu -# SPDX-FileCopyrightText: 2019 Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later -# -# Calamares is Free Software: see the License-Identifier above. -# - -import libcalamares - -import gettext -_ = gettext.translation("calamares-python", - localedir=libcalamares.utils.gettext_path(), - languages=libcalamares.utils.gettext_languages(), - fallback=True).gettext - - -def pretty_name(): - return _("Setting hardware clock.") - - -def run(): - """ - Set hardware clock. - """ - hwclock_rtc = ["hwclock", "--systohc", "--utc"] - hwclock_isa = ["hwclock", "--systohc", "--utc", "--directisa"] - is_broken_rtc = False - is_broken_isa = False - - ret = libcalamares.utils.target_env_call(hwclock_rtc) - if ret != 0: - is_broken_rtc = True - libcalamares.utils.debug("Hwclock returned error code {}".format(ret)) - libcalamares.utils.debug(" .. RTC method failed, trying ISA bus method.") - else: - libcalamares.utils.debug("Hwclock set using RTC method.") - if is_broken_rtc: - ret = libcalamares.utils.target_env_call(hwclock_isa) - if ret != 0: - is_broken_isa = True - libcalamares.utils.debug("Hwclock returned error code {}".format(ret)) - libcalamares.utils.debug(" .. ISA bus method failed.") - else: - libcalamares.utils.debug("Hwclock set using ISA bus method.") - if is_broken_rtc and is_broken_isa: - libcalamares.utils.debug("BIOS or Kernel BUG: Setting hwclock failed.") - - return None diff --git a/src/modules/hwclock/module.desc b/src/modules/hwclock/module.desc deleted file mode 100644 index d13435b3c7..0000000000 --- a/src/modules/hwclock/module.desc +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -type: "job" -name: "hwclock" -interface: "python" -script: "main.py" -noconfig: true diff --git a/src/modules/initcpio/CMakeLists.txt b/src/modules/initcpio/CMakeLists.txt deleted file mode 100644 index 1bbb9fdd96..0000000000 --- a/src/modules/initcpio/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# -calamares_add_plugin(initcpio - TYPE job - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - InitcpioJob.cpp - SHARED_LIB -) - -calamares_add_test( - initcpiotest - SOURCES Tests.cpp - LIBRARIES - calamares_job_initcpio # From above - yamlcpp::yamlcpp -) diff --git a/src/modules/initcpio/InitcpioJob.cpp b/src/modules/initcpio/InitcpioJob.cpp deleted file mode 100644 index ad569fa5ad..0000000000 --- a/src/modules/initcpio/InitcpioJob.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-FileCopyrightText: 2022 Evan James - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "InitcpioJob.h" - -#include "utils/Logger.h" -#include "utils/System.h" -#include "utils/UMask.h" -#include "utils/Variant.h" - -#include -#include - -InitcpioJob::InitcpioJob( QObject* parent ) - : Calamares::CppJob( parent ) -{ -} - -InitcpioJob::~InitcpioJob() {} - -QString -InitcpioJob::prettyName() const -{ - return tr( "Creating initramfs with mkinitcpio…", "@status" ); -} - -/** @brief Sets secure permissions on each initramfs - * - * Iterates over each initramfs contained directly in the directory @p d. - * For each initramfs found, the permissions are set to owner read/write only. - * - */ -void -fixPermissions( const QDir& d ) -{ - const auto initramList = d.entryInfoList( { "initramfs*" }, QDir::Files ); - for ( const auto& fi : initramList ) - { - QFile f( fi.absoluteFilePath() ); - if ( f.exists() ) - { - cDebug() << "initcpio setting permissions for" << f.fileName(); - f.setPermissions( QFileDevice::ReadOwner | QFileDevice::WriteOwner ); - } - } -} - -Calamares::JobResult -InitcpioJob::exec() -{ - Calamares::UMask m( Calamares::UMask::Safe ); - - if ( m_unsafe ) - { - cDebug() << "Skipping mitigations for unsafe initramfs permissions."; - } - else - { - QDir d( Calamares::System::instance()->targetPath( "/boot" ) ); - if ( d.exists() ) - { - fixPermissions( d ); - } - } - - // If the kernel option isn't set to a specific kernel, run mkinitcpio on all kernels - QStringList command = { "mkinitcpio" }; - if ( m_kernel.isEmpty() || m_kernel == "all" ) - { - command.append( "-P" ); - } - else - { - command.append( { "-p", m_kernel } ); - } - - cDebug() << "Updating initramfs with kernel" << m_kernel; - auto r = Calamares::System::instance()->targetEnvCommand( command, QString(), QString() /* no timeout , 0 */ ); - return r.explainProcess( "mkinitcpio", std::chrono::seconds( 10 ) /* fake timeout */ ); -} - -void -InitcpioJob::setConfigurationMap( const QVariantMap& configurationMap ) -{ - m_kernel = Calamares::getString( configurationMap, "kernel" ); - - m_unsafe = Calamares::getBool( configurationMap, "be_unsafe", false ); -} - -CALAMARES_PLUGIN_FACTORY_DEFINITION( InitcpioJobFactory, registerPlugin< InitcpioJob >(); ) diff --git a/src/modules/initcpio/InitcpioJob.h b/src/modules/initcpio/InitcpioJob.h deleted file mode 100644 index 6e7f2b5857..0000000000 --- a/src/modules/initcpio/InitcpioJob.h +++ /dev/null @@ -1,41 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef INITCPIOJOB_H -#define INITCPIOJOB_H - -#include "CppJob.h" -#include "DllMacro.h" -#include "utils/PluginFactory.h" - -#include -#include - -class PLUGINDLLEXPORT InitcpioJob : public Calamares::CppJob -{ - Q_OBJECT - -public: - explicit InitcpioJob( QObject* parent = nullptr ); - ~InitcpioJob() override; - - QString prettyName() const override; - - Calamares::JobResult exec() override; - - void setConfigurationMap( const QVariantMap& configurationMap ) override; - -private: - QString m_kernel; - bool m_unsafe = false; -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( InitcpioJobFactory ) - -#endif // INITCPIOJOB_H diff --git a/src/modules/initcpio/Tests.cpp b/src/modules/initcpio/Tests.cpp deleted file mode 100644 index bff163b5f8..0000000000 --- a/src/modules/initcpio/Tests.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "Tests.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "Settings.h" - -#include "utils/Logger.h" -#include "utils/Yaml.h" - -#include - -#include -#include - -extern void fixPermissions( const QDir& d ); - -QTEST_GUILESS_MAIN( InitcpioTests ) - -InitcpioTests::InitcpioTests() {} - -InitcpioTests::~InitcpioTests() {} - -void -InitcpioTests::initTestCase() -{ -} - -void -InitcpioTests::testFixPermissions() -{ - Logger::setupLogLevel( Logger::LOGDEBUG ); - cDebug() << "Fixing up /boot"; - fixPermissions( QDir( "/boot" ) ); - cDebug() << "Fixing up /nonexistent"; - fixPermissions( QDir( "/nonexistent/nonexistent" ) ); - QVERIFY( true ); -} diff --git a/src/modules/initcpio/Tests.h b/src/modules/initcpio/Tests.h deleted file mode 100644 index aac48d0c4c..0000000000 --- a/src/modules/initcpio/Tests.h +++ /dev/null @@ -1,27 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef TESTS_H -#define TESTS_H - -#include - -class InitcpioTests : public QObject -{ - Q_OBJECT -public: - InitcpioTests(); - ~InitcpioTests() override; - -private Q_SLOTS: - void initTestCase(); - void testFixPermissions(); -}; - -#endif diff --git a/src/modules/initcpio/initcpio.conf b/src/modules/initcpio/initcpio.conf deleted file mode 100644 index d2a1268647..0000000000 --- a/src/modules/initcpio/initcpio.conf +++ /dev/null @@ -1,26 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Run mkinitcpio(8) with the given preset value ---- -# This key defines the kernel to be loaded. -# It can have the following values: -# - the name of a single mkinitcpio preset -# - empty or unset -# - the literal string "all" -# -# If kernel is set to "all" or empty/unset then mkinitpio is called for all -# kernels. Otherwise it is called with a single preset with the value -# contained in kernel. -# -kernel: linux - -# Set this to true to turn off mitigations for lax file -# permissions on initramfs (which, in turn, can compromise -# your LUKS encryption keys, CVS-2019-13179). -# -# If your initramfs are stored in the EFI partition or another non-POSIX -# filesystem, this has no effect as the file permissions cannot be changed. -# In this case, ensure the partition is mounted securely. -# -be_unsafe: false diff --git a/src/modules/initcpio/initcpio.schema.yaml b/src/modules/initcpio/initcpio.schema.yaml deleted file mode 100644 index 2024182bfa..0000000000 --- a/src/modules/initcpio/initcpio.schema.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later ---- -$schema: https://json-schema.org/schema# -$id: https://calamares.io/schemas/initcpio -additionalProperties: false -type: object -properties: - kernel: { type: string } - be_unsafe: { type: boolean, default: false } -required: [ kernel ] diff --git a/src/modules/initcpiocfg/initcpiocfg.conf b/src/modules/initcpiocfg/initcpiocfg.conf deleted file mode 100644 index fc226ec845..0000000000 --- a/src/modules/initcpiocfg/initcpiocfg.conf +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# The initcpiocfg module is responsible for the configuration of mkinitcpio.conf. Typically this -# module is used in conjunction with the initcpio module to generate the boot image when using mkinitcpio ---- -# -# Determines if the systemd versions of the hooks should be used. This is false by default. -# -# Please note that using the systemd hooks result in no access to the emergency recovery shell -useSystemdHook: false diff --git a/src/modules/initcpiocfg/initcpiocfg.schema.yaml b/src/modules/initcpiocfg/initcpiocfg.schema.yaml deleted file mode 100644 index f071e79aa7..0000000000 --- a/src/modules/initcpiocfg/initcpiocfg.schema.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-FileCopyrightText: 2023 Evan James -# SPDX-License-Identifier: GPL-3.0-or-later ---- -$schema: https://json-schema.org/schema# -$id: https://calamares.io/schemas/initcpiocfg -additionalProperties: false -type: object -properties: - useSystemdHook: { type: boolean } - - diff --git a/src/modules/initcpiocfg/main.py b/src/modules/initcpiocfg/main.py deleted file mode 100644 index 0939054fb8..0000000000 --- a/src/modules/initcpiocfg/main.py +++ /dev/null @@ -1,266 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2014 Rohan Garg -# SPDX-FileCopyrightText: 2015 2019-2020, Philip Müller -# SPDX-FileCopyrightText: 2017 Alf Gaida -# SPDX-FileCopyrightText: 2019 Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later -# -# Calamares is Free Software: see the License-Identifier above. -# -import libcalamares -from libcalamares.utils import debug, target_env_call -import os -from collections import OrderedDict - -import gettext -_ = gettext.translation("calamares-python", - localedir=libcalamares.utils.gettext_path(), - languages=libcalamares.utils.gettext_languages(), - fallback=True).gettext - - -def pretty_name(): - return _("Configuring mkinitcpio.") - - -def detect_plymouth(): - """ - Checks existence (runnability) of plymouth in the target system. - - @return True if plymouth exists in the target, False otherwise - """ - # Used to only check existence of path /usr/bin/plymouth in target - return target_env_call(["sh", "-c", "which plymouth"]) == 0 - - -class cpuinfo(object): - """ - Object describing the current CPU's characteristics. It may be - be considered a named tuple, there's no behavior here. - - Fields in the object: - - is_intel (if it's definitely an Intel CPU) - - is_amd (if it's definitely an AMD CPU) - - number_of_cores - It is possible for both is_* fields to be False. - """ - def __init__(self): - self.is_intel = False - self.is_amd = False - self.number_of_cores = 0 - - cpu = self._cpuinfo() - if 'vendor_id' in cpu['proc0']: - self.is_intel = cpu['proc0']['vendor_id'].lower() == "genuineintel" - self.is_amd = cpu['proc0']['vendor_id'].lower() == "authenticamd" - self.number_of_cores = len(cpu) - - @staticmethod - def _cpuinfo(): - """ - Return the information in /proc/cpuinfo as a dictionary in the following - format: - - cpu_info['proc0']={...} - cpu_info['proc1']={...} - """ - cpu_info = OrderedDict() - procinfo = OrderedDict() - - nprocs = 0 - - with open('/proc/cpuinfo') as cpuinfo_file: - for line in cpuinfo_file: - if not line.strip(): - # end of one processor - cpu_info["proc{!s}".format(nprocs)] = procinfo - nprocs += 1 - # Reset - procinfo = OrderedDict() - else: - if len(line.split(':')) == 2: - splitted_line = line.split(':')[1].strip() - procinfo[line.split(':')[0].strip()] = splitted_line - else: - procinfo[line.split(':')[0].strip()] = '' - - return cpu_info - - -def get_host_initcpio(): - """ - Reads the host system mkinitcpio.conf and returns all - the lines from that file, or an empty list if it does - not exist. - """ - hostfile = "/etc/mkinitcpio.conf" - try: - with open(hostfile, "r") as mkinitcpio_file: - mklins = [x.strip() for x in mkinitcpio_file.readlines()] - except FileNotFoundError: - libcalamares.utils.debug(f"Could not open host file {hostfile}") - mklins = [] - - return mklins - - -def write_mkinitcpio_lines(hooks, modules, files, binaries, root_mount_point): - """ - Set up mkinitcpio.conf. - - :param hooks: - :param modules: - :param files: - :param root_mount_point: - """ - mklins = get_host_initcpio() - - target_path = os.path.join(root_mount_point, "etc/mkinitcpio.conf") - with open(target_path, "w") as mkinitcpio_file: - for line in mklins: - # Replace HOOKS, MODULES, BINARIES and FILES lines with what we - # have found via find_initcpio_features() - if line.startswith("HOOKS"): - line = f"HOOKS=({str.join(' ', hooks)})" - elif line.startswith("BINARIES"): - line = f"BINARIES=({str.join(' ', binaries)})" - elif line.startswith("MODULES"): - line = f"MODULES=({str.join(' ', modules)})" - elif line.startswith("FILES"): - line = f"FILES=({str.join(' ', files)})" - mkinitcpio_file.write(line + "\n") - - -def find_initcpio_features(partitions, root_mount_point): - """ - Returns a tuple (hooks, modules, files) needed to support - the given @p partitions (filesystems types, encryption, etc) - in the target. - - :param partitions: (from GS) - :param root_mount_point: (from GS) - - :return 3-tuple of lists - """ - hooks = [ - "autodetect", - "kms", - "modconf", - "block", - "keyboard", - ] - - systemd_hook_allowed = libcalamares.job.configuration.get("useSystemdHook", False) - - use_systemd = systemd_hook_allowed and target_env_call(["sh", "-c", "which systemd-cat"]) == 0 - - if use_systemd: - hooks.insert(0, "systemd") - hooks.append("sd-vconsole") - else: - hooks.insert(0, "udev") - hooks.insert(0, "base") - hooks.append("keymap") - hooks.append("consolefont") - - modules = [] - files = [] - binaries = [] - - swap_uuid = "" - uses_btrfs = False - uses_zfs = False - uses_lvm2 = False - encrypt_hook = False - openswap_hook = False - unencrypted_separate_boot = False - - # It is important that the plymouth hook comes before any encrypt hook - if detect_plymouth(): - hooks.append("plymouth") - - for partition in partitions: - if partition["fs"] == "linuxswap" and not partition.get("claimed", None): - # Skip foreign swap - continue - - if partition["fs"] == "linuxswap": - swap_uuid = partition["uuid"] - if "luksMapperName" in partition: - openswap_hook = True - - if partition["fs"] == "btrfs": - uses_btrfs = True - - # In addition to checking the filesystem, check to ensure that zfs is enabled - if partition["fs"] == "zfs" and libcalamares.globalstorage.contains("zfsPoolInfo"): - uses_zfs = True - - if "lvm2" in partition["fs"]: - uses_lvm2 = True - - if partition["mountPoint"] == "/" and "luksMapperName" in partition: - encrypt_hook = True - - if partition["mountPoint"] == "/boot" and "luksMapperName" not in partition: - unencrypted_separate_boot = True - - if partition["mountPoint"] == "/usr": - hooks.append("usr") - - if encrypt_hook: - if use_systemd: - hooks.append("sd-encrypt") - else: - hooks.append("encrypt") - crypto_file = "crypto_keyfile.bin" - if not unencrypted_separate_boot and os.path.isfile(os.path.join(root_mount_point, crypto_file)): - files.append(f"/{crypto_file}") - - if uses_lvm2: - hooks.append("lvm2") - - if uses_zfs: - hooks.append("zfs") - - if swap_uuid != "": - if encrypt_hook and openswap_hook: - hooks.extend(["openswap"]) - hooks.extend(["resume", "filesystems"]) - else: - hooks.extend(["filesystems"]) - - if uses_btrfs: - modules.append("crc32c-intel" if cpuinfo().is_intel else "crc32c") - else: - hooks.append("fsck") - - return hooks, modules, files, binaries - - -def run(): - """ - Calls routine with given parameters to modify "/etc/mkinitcpio.conf". - - :return: - """ - partitions = libcalamares.globalstorage.value("partitions") - root_mount_point = libcalamares.globalstorage.value("rootMountPoint") - - if not partitions: - libcalamares.utils.warning(f"partitions are empty, {partitions}") - return (_("Configuration Error"), - _("No partitions are defined for
initcpiocfg
.")) - if not root_mount_point: - libcalamares.utils.warning(f"rootMountPoint is empty, {root_mount_point}") - return (_("Configuration Error"), - _("No root mount point for
initcpiocfg
.")) - - hooks, modules, files, binaries = find_initcpio_features(partitions, root_mount_point) - write_mkinitcpio_lines(hooks, modules, files, binaries, root_mount_point) - - return None diff --git a/src/modules/initcpiocfg/module.desc b/src/modules/initcpiocfg/module.desc deleted file mode 100644 index 9d7bfdf309..0000000000 --- a/src/modules/initcpiocfg/module.desc +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Writes a mkinitcpio.conf into the target system. It copies -# the host system's /etc/mkinitcpio.conf, and replaces any -# HOOKS, MODULES, and FILES lines with calculated values -# based on what the installation (seems to) need. ---- -type: "job" -name: "initcpiocfg" -interface: "python" -script: "main.py" diff --git a/src/modules/initramfs/CMakeLists.txt b/src/modules/initramfs/CMakeLists.txt deleted file mode 100644 index 45f29c3875..0000000000 --- a/src/modules/initramfs/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# -calamares_add_plugin(initramfs - TYPE job - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - InitramfsJob.cpp - SHARED_LIB -) - -calamares_add_test( - initramfstest - SOURCES Tests.cpp - LIBRARIES - calamares_job_initramfs # From above - yamlcpp::yamlcpp -) diff --git a/src/modules/initramfs/InitramfsJob.cpp b/src/modules/initramfs/InitramfsJob.cpp deleted file mode 100644 index f61679fe54..0000000000 --- a/src/modules/initramfs/InitramfsJob.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "InitramfsJob.h" - -#include "utils/Logger.h" -#include "utils/System.h" -#include "utils/UMask.h" -#include "utils/Variant.h" - -InitramfsJob::InitramfsJob( QObject* parent ) - : Calamares::CppJob( parent ) -{ -} - -InitramfsJob::~InitramfsJob() {} - -QString -InitramfsJob::prettyName() const -{ - return tr( "Creating initramfs…", "@status" ); -} - -Calamares::JobResult -InitramfsJob::exec() -{ - Calamares::UMask m( Calamares::UMask::Safe ); - - cDebug() << "Updating initramfs with kernel" << m_kernel; - - if ( m_unsafe ) - { - cDebug() << "Skipping mitigations for unsafe initramfs permissions."; - } - else - { - // First make sure we generate a safe initramfs with suitable permissions. - static const char confFile[] = "/etc/initramfs-tools/conf.d/calamares-safe-initramfs.conf"; - static const char contents[] = "UMASK=0077\n"; - if ( Calamares::System::instance()->createTargetFile( confFile, QByteArray( contents ) ).failed() ) - { - cWarning() << Logger::SubEntry << "Could not configure safe UMASK for initramfs."; - // But continue anyway. - } - } - - // And then do the ACTUAL work. - auto r = Calamares::System::instance()->targetEnvCommand( - { "update-initramfs", "-k", m_kernel, "-c", "-t" }, QString(), QString() /* no timeout, 0 */ ); - return r.explainProcess( "update-initramfs", std::chrono::seconds( 10 ) /* fake timeout */ ); -} - -void -InitramfsJob::setConfigurationMap( const QVariantMap& configurationMap ) -{ - m_kernel = Calamares::getString( configurationMap, "kernel" ); - if ( m_kernel.isEmpty() ) - { - m_kernel = QStringLiteral( "all" ); - } - else if ( m_kernel == "$uname" ) - { - auto r = Calamares::System::runCommand( Calamares::System::RunLocation::RunInHost, - { "/bin/uname", "-r" }, - QString(), - QString(), - std::chrono::seconds( 3 ) ); - if ( r.getExitCode() == 0 ) - { - m_kernel = r.getOutput(); - cDebug() << "*initramfs* using running kernel" << m_kernel; - } - else - { - m_kernel = QStringLiteral( "all" ); - cWarning() << "*initramfs* could not determine running kernel, using 'all'." << Logger::Continuation - << r.getExitCode() << r.getOutput(); - } - } - - m_unsafe = Calamares::getBool( configurationMap, "be_unsafe", false ); -} - -CALAMARES_PLUGIN_FACTORY_DEFINITION( InitramfsJobFactory, registerPlugin< InitramfsJob >(); ) diff --git a/src/modules/initramfs/InitramfsJob.h b/src/modules/initramfs/InitramfsJob.h deleted file mode 100644 index c09c9eba2b..0000000000 --- a/src/modules/initramfs/InitramfsJob.h +++ /dev/null @@ -1,41 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef INITRAMFSJOB_H -#define INITRAMFSJOB_H - -#include "CppJob.h" -#include "DllMacro.h" -#include "utils/PluginFactory.h" - -#include -#include - -class PLUGINDLLEXPORT InitramfsJob : public Calamares::CppJob -{ - Q_OBJECT - -public: - explicit InitramfsJob( QObject* parent = nullptr ); - ~InitramfsJob() override; - - QString prettyName() const override; - - Calamares::JobResult exec() override; - - void setConfigurationMap( const QVariantMap& configurationMap ) override; - -private: - QString m_kernel; - bool m_unsafe = false; -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( InitramfsJobFactory ) - -#endif // INITRAMFSJOB_H diff --git a/src/modules/initramfs/Tests.cpp b/src/modules/initramfs/Tests.cpp deleted file mode 100644 index 3dd77881df..0000000000 --- a/src/modules/initramfs/Tests.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "Tests.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "Settings.h" - -#include "utils/Logger.h" -#include "utils/System.h" -#include "utils/Yaml.h" - -#include - -#include -#include - -QTEST_GUILESS_MAIN( InitramfsTests ) - -InitramfsTests::InitramfsTests() {} - -InitramfsTests::~InitramfsTests() {} - -void -InitramfsTests::initTestCase() -{ - Logger::setupLogLevel( Logger::LOGDEBUG ); - - (void)new Calamares::JobQueue(); - (void)new Calamares::System( true ); -} - -static const char contents[] = "UMASK=0077\n"; -static const char confFile[] = "/tmp/calamares-safe-umask"; - -void -InitramfsTests::cleanup() -{ - QFile::remove( confFile ); -} - -void -InitramfsTests::testCreateTargetFile() -{ - static const char short_confFile[] = "/calamares-safe-umask"; - - auto* s = Calamares::System::instance(); - auto r = s->createTargetFile( short_confFile, QByteArray( contents ) ); - QVERIFY( r.failed() ); - QVERIFY( !r ); - QString path = r.path(); - QVERIFY( path.isEmpty() ); // because no rootmountpoint is set - - Calamares::JobQueue::instance()->globalStorage()->insert( "rootMountPoint", "/tmp" ); - - path = s->createTargetFile( short_confFile, QByteArray( contents ) ).path(); - QCOMPARE( path, QString( confFile ) ); - QVERIFY( path.endsWith( short_confFile ) ); // chroot, so path create relative to - QVERIFY( path.startsWith( "/tmp/" ) ); - QVERIFY( QFile::exists( path ) ); - - QFileInfo fi( path ); - QVERIFY( fi.exists() ); - QCOMPARE( ulong( fi.size() ), sizeof( contents ) - 1 ); // don't count trailing NUL - - QFile::remove( path ); -} diff --git a/src/modules/initramfs/Tests.h b/src/modules/initramfs/Tests.h deleted file mode 100644 index 3774245899..0000000000 --- a/src/modules/initramfs/Tests.h +++ /dev/null @@ -1,30 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef TESTS_H -#define TESTS_H - -#include - -class InitramfsTests : public QObject -{ - Q_OBJECT -public: - InitramfsTests(); - ~InitramfsTests() override; - -private Q_SLOTS: - void initTestCase(); - void cleanup(); - - // TODO: this doesn't actually test any of the functionality of this job - void testCreateTargetFile(); -}; - -#endif diff --git a/src/modules/initramfs/initramfs.conf b/src/modules/initramfs/initramfs.conf deleted file mode 100644 index c9dcf16971..0000000000 --- a/src/modules/initramfs/initramfs.conf +++ /dev/null @@ -1,39 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -## initramfs module -# -# This module is specific to Debian based distros. Post installation on Debian -# the initramfs needs to be updated so as to not interrupt the boot process -# with a error about fsck.ext4 not being found. -# -## Debian specific notes -# -# If you're using live-build to build your ISO and setup the runtime env -# make sure that you purge the live-\* packages on the target system -# before running this module, since live-config dpkg-diverts update-initramfs -# and can cause all sorts of fun issues. ---- -# There is only one configuration item for this module, -# the kernel to be loaded. This can have the following -# values: -# - empty or unset, interpreted as "all" -# - the literal string "$uname" (without quotes, with dollar), -# which will use the output of `uname -r` to determine the -# running kernel, and use that. -# - any other string. -# -# Whatever is set, that string is passed as *version* argument to the -# `-k` option of *update-initramfs*. Take care that both "$uname" operates -# in the host system, and might not be correct if the target system is -# updated (to a newer kernel) as part of the installation. -# -# The default is empty/unset, leading to the behavior from Calamares -# 3.2.9 and earlier which passed "all" as version. - -kernel: "all" - -# Set this to true to turn off mitigations for lax file -# permissions on initramfs (which, in turn, can compromise -# your LUKS encryption keys, CVS-2019-13179). -be_unsafe: false diff --git a/src/modules/initramfscfg/encrypt_hook b/src/modules/initramfscfg/encrypt_hook deleted file mode 100755 index 70d661a984..0000000000 --- a/src/modules/initramfscfg/encrypt_hook +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/sh -# -# SPDX-FileCopyrightText: 2016 David McKinney -# SPDX-License-Identifier: GPL-3.0-or-later - - PREREQ="" - - prereqs() - { - echo "$PREREQ" - } - - case $1 in - # get pre-requisites - prereqs) - prereqs - exit 0 - ;; - esac - - . /usr/share/initramfs-tools/hook-functions - if [ -f /crypto_keyfile.bin ] - then - cp /crypto_keyfile.bin ${DESTDIR} - fi - if [ -f /etc/crypttab ] - then - cp /etc/crypttab ${DESTDIR}/etc/ - fi diff --git a/src/modules/initramfscfg/encrypt_hook_nokey b/src/modules/initramfscfg/encrypt_hook_nokey deleted file mode 100755 index 8ee669c300..0000000000 --- a/src/modules/initramfscfg/encrypt_hook_nokey +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh -# -# SPDX-FileCopyrightText: 2016 David McKinney -# SPDX-License-Identifier: GPL-3.0-or-later - - PREREQ="" - - prereqs() - { - echo "$PREREQ" - } - - case $1 in - # get pre-requisites - prereqs) - prereqs - exit 0 - ;; - esac - - . /usr/share/initramfs-tools/hook-functions - if [ -f /etc/crypttab ] - then - cp /etc/crypttab ${DESTDIR}/etc/ - fi diff --git a/src/modules/initramfscfg/main.py b/src/modules/initramfscfg/main.py deleted file mode 100644 index 974e2634dc..0000000000 --- a/src/modules/initramfscfg/main.py +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2014 Rohan Garg -# SPDX-FileCopyrightText: 2015 Philip Müller -# SPDX-FileCopyrightText: 2016 David McKinney -# SPDX-FileCopyrightText: 2016 Kevin Kofler -# SPDX-FileCopyrightText: 2017 Alf Gaida -# SPDX-FileCopyrightText: 2017 2019, Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later -# -# Calamares is Free Software: see the License-Identifier above. -# - -import libcalamares - -import inspect -import os -import shutil - - -import gettext -_ = gettext.translation("calamares-python", - localedir=libcalamares.utils.gettext_path(), - languages=libcalamares.utils.gettext_languages(), - fallback=True).gettext - - -def pretty_name(): - return _("Configuring initramfs.") - - -def copy_initramfs_hooks(partitions, root_mount_point): - """ - Copies initramfs hooks so they are picked up by update-initramfs - - :param partitions: - :param root_mount_point: - """ - encrypt_hook = False - unencrypted_separate_boot = False - - for partition in partitions: - if partition["mountPoint"] == "/" and "luksMapperName" in partition: - encrypt_hook = True - - if (partition["mountPoint"] == "/boot" - and "luksMapperName" not in partition): - unencrypted_separate_boot = True - - if encrypt_hook: - target = "{!s}/usr/share/initramfs-tools/hooks/encrypt_hook".format( - root_mount_point) - - # Find where this module is installed - _filename = inspect.getframeinfo(inspect.currentframe()).filename - _path = os.path.dirname(os.path.abspath(_filename)) - - if unencrypted_separate_boot: - shutil.copy2( - os.path.join(_path, "encrypt_hook_nokey"), - target - ) - else: - shutil.copy2( - os.path.join(_path, "encrypt_hook"), - target - ) - os.chmod(target, 0o755) - - -def run(): - """ - Calls routine with given parameters to configure initramfs - - :return: - """ - partitions = libcalamares.globalstorage.value("partitions") - root_mount_point = libcalamares.globalstorage.value("rootMountPoint") - - if not partitions: - libcalamares.utils.warning("partitions is empty, {!s}".format(partitions)) - return (_("Configuration Error"), - _("No partitions are defined for
{!s}
to use." ).format("initramfscfg")) - if not root_mount_point: - libcalamares.utils.warning("rootMountPoint is empty, {!s}".format(root_mount_point)) - return (_("Configuration Error"), - _("No root mount point is given for
{!s}
to use." ).format("initramfscfg")) - - copy_initramfs_hooks(partitions, root_mount_point) - - return None diff --git a/src/modules/initramfscfg/module.desc b/src/modules/initramfscfg/module.desc deleted file mode 100644 index 17db29465a..0000000000 --- a/src/modules/initramfscfg/module.desc +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -type: "job" -name: "initramfscfg" -interface: "python" -script: "main.py" -noconfig: true diff --git a/src/modules/interactiveterminal/CMakeLists.txt b/src/modules/interactiveterminal/CMakeLists.txt deleted file mode 100644 index 6d153cca36..0000000000 --- a/src/modules/interactiveterminal/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# -find_package(${kfname}Service ${KF_VERSION}) -find_package(${kfname}Parts ${KF_VERSION}) -set_package_properties(${kfname}Service PROPERTIES PURPOSE "For finding KDE services at runtime") -set_package_properties(${kfname}Parts PROPERTIES PURPOSE "For finding KDE parts at runtime") - -if(${kfname}Parts_FOUND AND ${kfname}Service_FOUND) - calamares_add_plugin(interactiveterminal - TYPE viewmodule - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - InteractiveTerminalViewStep.cpp - InteractiveTerminalPage.cpp - LINK_LIBRARIES - ${kfname}::Service - ${kfname}::Parts - SHARED_LIB - ) -else() - calamares_skip_module( "interactiveterminal (missing requirements)" ) -endif() diff --git a/src/modules/interactiveterminal/InteractiveTerminalPage.cpp b/src/modules/interactiveterminal/InteractiveTerminalPage.cpp deleted file mode 100644 index fb31f26508..0000000000 --- a/src/modules/interactiveterminal/InteractiveTerminalPage.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2024 Anke Boersma - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "InteractiveTerminalPage.h" - -#include "utils/Gui.h" -#include "utils/Logger.h" -#include "utils/Retranslator.h" -#include "viewpages/ViewStep.h" -#include "widgets/TranslationFix.h" - -#include -#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) -#include -#include -#else -#include -#include -#endif -#include - -#include -#include -#include -#include -#include - -InteractiveTerminalPage::InteractiveTerminalPage( QWidget* parent ) - : QWidget( parent ) - , m_layout( new QVBoxLayout( this ) ) - , m_termHostWidget( nullptr ) -{ - setLayout( m_layout ); - m_layout->setContentsMargins( 0, 0, 0, 0 ); - - m_headerLabel = new QLabel( this ); - m_layout->addWidget( m_headerLabel ); -} - -void -InteractiveTerminalPage::errorKonsoleNotInstalled() -{ - QMessageBox mb( QMessageBox::Critical, - tr( "Konsole not installed.", "@error" ), - tr( "Please install KDE Konsole and try again!", "@info" ), - QMessageBox::Ok ); - Calamares::fixButtonLabels( &mb ); - mb.exec(); -} - -void -InteractiveTerminalPage::onActivate() -{ - if ( m_termHostWidget ) - { - return; - } - -#if KCOREADDONS_VERSION_MAJOR > 5 || KCOREADDONS_VERSION_MINOR > 200 - auto md = KPluginMetaData::findPluginById( QString(), "kf6/parts/konsolepart" ); - if ( !md.isValid() ) - { - errorKonsoleNotInstalled(); - return; - } - auto* p = KPluginFactory::instantiatePlugin< KParts::ReadOnlyPart >( md, this ).plugin; -#elif KCOREADDONS_VERSION_MINOR >= 86 - // 5.86 deprecated a bunch of KService and PluginFactory and related methods - auto md = KPluginMetaData::findPluginById( QString(), "konsolepart" ); - if ( !md.isValid() ) - { - errorKonsoleNotInstalled(); - return; - } - auto* p = KPluginFactory::instantiatePlugin< KParts::ReadOnlyPart >( md, this ).plugin; -#else - KService::Ptr service = KService::serviceByDesktopName( "konsolepart" ); - if ( !service ) - { - errorKonsoleNotInstalled(); - return; - } - - // Create one instance of konsolepart. - KParts::ReadOnlyPart* p = service->createInstance< KParts::ReadOnlyPart >( this, this, {} ); -#endif - if ( !p ) - { - // One more opportunity for the loading operation to fail. - errorKonsoleNotInstalled(); - return; - } - - // Cast the konsolepart to the TerminalInterface... - TerminalInterface* t = qobject_cast< TerminalInterface* >( p ); - if ( !t ) - { - // This is why we can't have nice things. - errorKonsoleNotInstalled(); - return; - } - - // Make the widget persist even if the KPart goes out of scope... - p->setAutoDeleteWidget( false ); - // ... but kill the KPart if the widget goes out of scope. - p->setAutoDeletePart( true ); - - m_termHostWidget = p->widget(); - m_layout->addWidget( m_termHostWidget ); - - t->showShellInDir( QDir::home().path() ); - t->sendInput( QString( "%1\n" ).arg( m_command ) ); -} - -void -InteractiveTerminalPage::setCommand( const QString& command ) -{ - m_command = command; - CALAMARES_RETRANSLATE( - m_headerLabel->setText( tr( "Executing script:  %1", "@info" ).arg( m_command ) ); ); -} diff --git a/src/modules/interactiveterminal/InteractiveTerminalPage.h b/src/modules/interactiveterminal/InteractiveTerminalPage.h deleted file mode 100644 index 86ba075adb..0000000000 --- a/src/modules/interactiveterminal/InteractiveTerminalPage.h +++ /dev/null @@ -1,37 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef INTERACTIVETERMINALPAGE_H -#define INTERACTIVETERMINALPAGE_H - -#include - -class QLabel; -class QVBoxLayout; - -class InteractiveTerminalPage : public QWidget -{ - Q_OBJECT -public: - explicit InteractiveTerminalPage( QWidget* parent = nullptr ); - - void onActivate(); - - void setCommand( const QString& command ); - -private: - QVBoxLayout* m_layout; - QWidget* m_termHostWidget; - QString m_command; - QLabel* m_headerLabel; - - void errorKonsoleNotInstalled(); -}; - -#endif // INTERACTIVETERMINALPAGE_H diff --git a/src/modules/interactiveterminal/InteractiveTerminalViewStep.cpp b/src/modules/interactiveterminal/InteractiveTerminalViewStep.cpp deleted file mode 100644 index 6f0457f385..0000000000 --- a/src/modules/interactiveterminal/InteractiveTerminalViewStep.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "InteractiveTerminalViewStep.h" - -#include "InteractiveTerminalPage.h" - -#include "compat/Variant.h" -#include "utils/Logger.h" - -#include - -CALAMARES_PLUGIN_FACTORY_DEFINITION( InteractiveTerminalViewStepFactory, - registerPlugin< InteractiveTerminalViewStep >(); ) - -InteractiveTerminalViewStep::InteractiveTerminalViewStep( QObject* parent ) - : Calamares::ViewStep( parent ) - , m_widget( new InteractiveTerminalPage() ) -{ - emit nextStatusChanged( true ); -} - -InteractiveTerminalViewStep::~InteractiveTerminalViewStep() -{ - if ( m_widget && m_widget->parent() == nullptr ) - { - m_widget->deleteLater(); - } -} - -QString -InteractiveTerminalViewStep::prettyName() const -{ - return tr( "Script", "@label" ); -} - -QWidget* -InteractiveTerminalViewStep::widget() -{ - return m_widget; -} - -bool -InteractiveTerminalViewStep::isNextEnabled() const -{ - return true; -} - -bool -InteractiveTerminalViewStep::isBackEnabled() const -{ - return true; -} - -bool -InteractiveTerminalViewStep::isAtBeginning() const -{ - return true; -} - -bool -InteractiveTerminalViewStep::isAtEnd() const -{ - return true; -} - -QList< Calamares::job_ptr > -InteractiveTerminalViewStep::jobs() const -{ - cDebug() << "InteractiveTerminal" << prettyName() << "asked for jobs(), this is probably wrong."; - return QList< Calamares::job_ptr >(); -} - -void -InteractiveTerminalViewStep::onActivate() -{ - cDebug() << "InteractiveTerminal" << prettyName() << "activated."; - m_widget->onActivate(); -} - -void -InteractiveTerminalViewStep::setConfigurationMap( const QVariantMap& configurationMap ) -{ - if ( configurationMap.contains( "command" ) - && Calamares::typeOf( configurationMap.value( "command" ) ) == Calamares::StringVariantType ) - { - m_widget->setCommand( configurationMap.value( "command" ).toString() ); - } -} diff --git a/src/modules/interactiveterminal/InteractiveTerminalViewStep.h b/src/modules/interactiveterminal/InteractiveTerminalViewStep.h deleted file mode 100644 index 8e0e6508f4..0000000000 --- a/src/modules/interactiveterminal/InteractiveTerminalViewStep.h +++ /dev/null @@ -1,54 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef INTERACTIVETERMINALPAGEPLUGIN_H -#define INTERACTIVETERMINALPAGEPLUGIN_H - -#include - -#include "utils/PluginFactory.h" -#include "viewpages/ViewStep.h" - -#include "DllMacro.h" - -class InteractiveTerminalPage; - -class PLUGINDLLEXPORT InteractiveTerminalViewStep : public Calamares::ViewStep -{ - Q_OBJECT - -public: - explicit InteractiveTerminalViewStep( QObject* parent = nullptr ); - ~InteractiveTerminalViewStep() override; - - QString prettyName() const override; - - QWidget* widget() override; - - bool isNextEnabled() const override; - bool isBackEnabled() const override; - - bool isAtBeginning() const override; - bool isAtEnd() const override; - - QList< Calamares::job_ptr > jobs() const override; - - void onActivate() override; - -protected: - void setConfigurationMap( const QVariantMap& configurationMap ) override; - -private: - InteractiveTerminalPage* m_widget; -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( InteractiveTerminalViewStepFactory ) - -#endif // INTERACTIVETERMINALPAGEPLUGIN_H diff --git a/src/modules/interactiveterminal/interactiveterminal.conf b/src/modules/interactiveterminal/interactiveterminal.conf deleted file mode 100644 index 9354f8f4a9..0000000000 --- a/src/modules/interactiveterminal/interactiveterminal.conf +++ /dev/null @@ -1,17 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# The interactive terminal provides a konsole (terminal) window -# during the installation process. The terminal runs in the -# host system, so you will need to change directories to the -# target system to examine the state there. -# -# The one configuration key *command*, if defined, is passed -# as a command to run in the terminal window before any user -# input is accepted. The user must exit the terminal manually -# or click *next* to proceed to the next installation step. -# -# If no command is defined, no command is run and the user -# gets a plain terminal session. ---- -command: "echo Hello" diff --git a/src/modules/keyboardq/CMakeLists.txt b/src/modules/keyboardq/CMakeLists.txt deleted file mode 100644 index e14a59e8a0..0000000000 --- a/src/modules/keyboardq/CMakeLists.txt +++ /dev/null @@ -1,29 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# -if(NOT WITH_QML) - calamares_skip_module( "keyboardq (QML is not supported in this build)" ) - return() -endif() - -set(_keyboard ${CMAKE_CURRENT_SOURCE_DIR}/../keyboard) - -include_directories(${_keyboard}) - -calamares_add_plugin(keyboardq - TYPE viewmodule - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - KeyboardQmlViewStep.cpp - ${_keyboard}/Config.cpp - ${_keyboard}/KeyboardLayoutModel.cpp - ${_keyboard}/SetKeyboardLayoutJob.cpp - ${_keyboard}/keyboardwidget/keyboardglobal.cpp - RESOURCES - keyboardq${QT_VERSION_SUFFIX}.qrc - SHARED_LIB - LINK_LIBRARIES - ${qtname}::DBus -) diff --git a/src/modules/keyboardq/KeyboardQmlViewStep.cpp b/src/modules/keyboardq/KeyboardQmlViewStep.cpp deleted file mode 100644 index f63d03b81d..0000000000 --- a/src/modules/keyboardq/KeyboardQmlViewStep.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2020 Camilo Higuita - * SPDX-FileCopyrightText: 2020 Anke Boersma - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "KeyboardQmlViewStep.h" - -#include "Config.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" - -CALAMARES_PLUGIN_FACTORY_DEFINITION( KeyboardQmlViewStepFactory, registerPlugin< KeyboardQmlViewStep >(); ) - -KeyboardQmlViewStep::KeyboardQmlViewStep( QObject* parent ) - : Calamares::QmlViewStep( parent ) - , m_config( new Config( this ) ) -{ - m_config->detectCurrentKeyboardLayout(); - emit nextStatusChanged( true ); -} - -QString -KeyboardQmlViewStep::prettyName() const -{ - return tr( "Keyboard", "@label" ); -} - -QString -KeyboardQmlViewStep::prettyStatus() const -{ - return m_config->prettyStatus(); -} - -bool -KeyboardQmlViewStep::isNextEnabled() const -{ - return true; -} - -bool -KeyboardQmlViewStep::isBackEnabled() const -{ - return true; -} - -bool -KeyboardQmlViewStep::isAtBeginning() const -{ - return true; -} - -bool -KeyboardQmlViewStep::isAtEnd() const -{ - return true; -} - -Calamares::JobList -KeyboardQmlViewStep::jobs() const -{ - return m_config->createJobs(); -} - -void -KeyboardQmlViewStep::onActivate() -{ - m_config->guessLocaleKeyboardLayout(); -} - -void -KeyboardQmlViewStep::onLeave() -{ - m_config->finalize(); -} - -QObject* -KeyboardQmlViewStep::getConfig() -{ - return m_config; -} - -void -KeyboardQmlViewStep::setConfigurationMap( const QVariantMap& configurationMap ) -{ - m_config->setConfigurationMap( configurationMap ); - Calamares::QmlViewStep::setConfigurationMap( configurationMap ); -} diff --git a/src/modules/keyboardq/KeyboardQmlViewStep.h b/src/modules/keyboardq/KeyboardQmlViewStep.h deleted file mode 100644 index eb31c3d595..0000000000 --- a/src/modules/keyboardq/KeyboardQmlViewStep.h +++ /dev/null @@ -1,52 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef KEYBOARDQMLVIEWSTEP_H -#define KEYBOARDQMLVIEWSTEP_H - -#include "Config.h" - -#include "DllMacro.h" -#include "utils/PluginFactory.h" -#include "viewpages/QmlViewStep.h" - -#include - -class PLUGINDLLEXPORT KeyboardQmlViewStep : public Calamares::QmlViewStep -{ - Q_OBJECT - -public: - explicit KeyboardQmlViewStep( QObject* parent = nullptr ); - - QString prettyName() const override; - QString prettyStatus() 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; - -private: - Config* m_config; -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( KeyboardQmlViewStepFactory ) - -#endif // KEYBOARDQMLVIEWSTEP_H diff --git a/src/modules/keyboardq/data/Key-qt6.qml b/src/modules/keyboardq/data/Key-qt6.qml deleted file mode 100644 index 990f453f2e..0000000000 --- a/src/modules/keyboardq/data/Key-qt6.qml +++ /dev/null @@ -1,180 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2021 - 2023 Anke Boersma - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -import QtQuick - -Item { - id: key - - property string mainLabel: "A" - property var secondaryLabels: []; - - property var iconSource; - - property var keyImageLeft: "" - property var keyImageRight: "" - property var keyImageCenter: "" - - property color keyColor: "#404040" - property color keyPressedColor: "grey" - property int keyBounds: 2 - property var keyPressedColorOpacity: 1 - - property var mainFontFamily: "Roboto" - property color mainFontColor: "white" - property int mainFontSize: 18 - - property var secondaryFontFamily: "Roboto" - property color secondaryFontColor: "white" - property int secondaryFontSize: 10 - - property bool secondaryLabelVisible: true - - property bool isChekable; - property bool isChecked; - - property bool upperCase; - - signal clicked() - signal alternatesClicked(string symbol) - - Item { - anchors.fill: parent - anchors.margins: key.keyBounds - visible: key.keyImageLeft != "" || key.keyImageCenter != "" || key.keyImageRight != "" ? 1 : 0 - Image { - id: backgroundImage_left - anchors.left: parent.left - height: parent.height - fillMode: Image.PreserveAspectFit - source: key.keyImageLeft - } - Image { - id: backgroundImage_right - anchors.right: parent.right - height: parent.height - fillMode: Image.PreserveAspectFit - source: key.keyImageRight - } - Image { - id: backgroundImage_center - anchors.fill: parent - anchors.leftMargin: backgroundImage_left.width - 1 - anchors.rightMargin: backgroundImage_right.width - 1 - height: parent.height - fillMode: Image.Stretch - source: key.keyImageCenter - } - } - - Rectangle { - id: backgroundItem - anchors.fill: parent - anchors.margins: key.keyBounds - color: key.isChecked || mouseArea.pressed ? key.keyPressedColor : key.keyColor; - opacity: key.keyPressedColorOpacity - } - - Column - { - anchors.centerIn: backgroundItem - - Text { - id: secondaryLabelsItem - smooth: true - anchors.right: parent.right - visible: true //secondaryLabelVisible - text: secondaryLabels.length > 0 ? secondaryLabels : "" - color: secondaryFontColor - - font.pixelSize: secondaryFontSize - font.weight: Font.Light - font.family: secondaryFontFamily - font.capitalization: upperCase ? Font.AllUppercase : - Font.MixedCase - } - - Row { - anchors.horizontalCenter: parent.horizontalCenter - - Image { - id: icon - smooth: true - anchors.verticalCenter: parent.verticalCenter - source: iconSource - //sourceSize.width: key.width * 0.6 - sourceSize.height: key.height * 0.4 - } - - Text { - id: mainLabelItem - smooth: true - anchors.verticalCenter: parent.verticalCenter - text: mainLabel - color: mainFontColor - visible: iconSource ? false : true - - font.pixelSize: mainFontSize - font.weight: Font.Light - font.family: mainFontFamily - font.capitalization: upperCase ? Font.AllUppercase : - Font.MixedCase - } - } - } - - Row { - id: alternatesRow - property int selectedIndex: -1 - visible: false - anchors.bottom: backgroundItem.top - anchors.left: backgroundItem.left - - Repeater { - model: secondaryLabels.length - - Rectangle { - property bool isSelected: alternatesRow.selectedIndex === index - color: isSelected ? mainLabelItem.color : key.keyPressedColor - height: backgroundItem.height - width: backgroundItem.width - - Text { - anchors.centerIn: parent - text: secondaryLabels[ index ] - font: mainLabelItem.font - color: isSelected ? key.keyPressedColor : mainLabelItem.color - } - } - } - } - - MouseArea { - id: mouseArea - anchors.fill: parent - onPressAndHold: alternatesRow.visible = true - onClicked: { - if (key.isChekable) key.isChecked = !key.isChecked - key.clicked() - } - - onReleased: { - alternatesRow.visible = false - if (alternatesRow.selectedIndex > -1) - key.alternatesClicked(secondaryLabels[alternatesRow.selectedIndex]) - } - - onMouseXChanged: { - alternatesRow.selectedIndex = - (mouseY < 0 && mouseX > 0 && mouseY < alternatesRow.width) ? - Math.floor(mouseX / backgroundItem.width) : - -1; - } - } -} diff --git a/src/modules/keyboardq/data/Key.qml b/src/modules/keyboardq/data/Key.qml deleted file mode 100644 index e5c766e414..0000000000 --- a/src/modules/keyboardq/data/Key.qml +++ /dev/null @@ -1,180 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2021 Anke Boersma - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -import QtQuick 2.15 - -Item { - id: key - - property string mainLabel: "A" - property var secondaryLabels: []; - - property var iconSource; - - property var keyImageLeft: "" - property var keyImageRight: "" - property var keyImageCenter: "" - - property color keyColor: "#404040" - property color keyPressedColor: "grey" - property int keyBounds: 2 - property var keyPressedColorOpacity: 1 - - property var mainFontFamily: "Roboto" - property color mainFontColor: "white" - property int mainFontSize: 18 - - property var secondaryFontFamily: "Roboto" - property color secondaryFontColor: "white" - property int secondaryFontSize: 10 - - property bool secondaryLabelVisible: true - - property bool isChekable; - property bool isChecked; - - property bool upperCase; - - signal clicked() - signal alternatesClicked(string symbol) - - Item { - anchors.fill: parent - anchors.margins: key.keyBounds - visible: key.keyImageLeft != "" || key.keyImageCenter != "" || key.keyImageRight != "" ? 1 : 0 - Image { - id: backgroundImage_left - anchors.left: parent.left - height: parent.height - fillMode: Image.PreserveAspectFit - source: key.keyImageLeft - } - Image { - id: backgroundImage_right - anchors.right: parent.right - height: parent.height - fillMode: Image.PreserveAspectFit - source: key.keyImageRight - } - Image { - id: backgroundImage_center - anchors.fill: parent - anchors.leftMargin: backgroundImage_left.width - 1 - anchors.rightMargin: backgroundImage_right.width - 1 - height: parent.height - fillMode: Image.Stretch - source: key.keyImageCenter - } - } - - Rectangle { - id: backgroundItem - anchors.fill: parent - anchors.margins: key.keyBounds - color: key.isChecked || mouseArea.pressed ? key.keyPressedColor : key.keyColor; - opacity: key.keyPressedColorOpacity - } - - Column - { - anchors.centerIn: backgroundItem - - Text { - id: secondaryLabelsItem - smooth: true - anchors.right: parent.right - visible: true //secondaryLabelVisible - text: secondaryLabels.length > 0 ? secondaryLabels : "" - color: secondaryFontColor - - font.pixelSize: secondaryFontSize - font.weight: Font.Light - font.family: secondaryFontFamily - font.capitalization: upperCase ? Font.AllUppercase : - Font.MixedCase - } - - Row { - anchors.horizontalCenter: parent.horizontalCenter - - Image { - id: icon - smooth: true - anchors.verticalCenter: parent.verticalCenter - source: iconSource - //sourceSize.width: key.width * 0.6 - sourceSize.height: key.height * 0.4 - } - - Text { - id: mainLabelItem - smooth: true - anchors.verticalCenter: parent.verticalCenter - text: mainLabel - color: mainFontColor - visible: iconSource ? false : true - - font.pixelSize: mainFontSize - font.weight: Font.Light - font.family: mainFontFamily - font.capitalization: upperCase ? Font.AllUppercase : - Font.MixedCase - } - } - } - - Row { - id: alternatesRow - property int selectedIndex: -1 - visible: false - anchors.bottom: backgroundItem.top - anchors.left: backgroundItem.left - - Repeater { - model: secondaryLabels.length - - Rectangle { - property bool isSelected: alternatesRow.selectedIndex == index - color: isSelected ? mainLabelItem.color : key.keyPressedColor - height: backgroundItem.height - width: backgroundItem.width - - Text { - anchors.centerIn: parent - text: secondaryLabels[ index ] - font: mainLabelItem.font - color: isSelected ? key.keyPressedColor : mainLabelItem.color - } - } - } - } - - MouseArea { - id: mouseArea - anchors.fill: parent - onPressAndHold: alternatesRow.visible = true - onClicked: { - if (key.isChekable) key.isChecked = !key.isChecked - key.clicked() - } - - onReleased: { - alternatesRow.visible = false - if (alternatesRow.selectedIndex > -1) - key.alternatesClicked(secondaryLabels[alternatesRow.selectedIndex]) - } - - onMouseXChanged: { - alternatesRow.selectedIndex = - (mouseY < 0 && mouseX > 0 && mouseY < alternatesRow.width) ? - Math.floor(mouseX / backgroundItem.width) : - -1; - } - } -} diff --git a/src/modules/keyboardq/data/Keyboard-qt6.qml b/src/modules/keyboardq/data/Keyboard-qt6.qml deleted file mode 100644 index 01c5ae94b3..0000000000 --- a/src/modules/keyboardq/data/Keyboard-qt6.qml +++ /dev/null @@ -1,224 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2021 - 2023 Anke Boersma - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -import QtQuick -import QtQml.XmlListModel - -Item { - id: keyboard - - width: 1024 - height: 640 - - property int rows: 4; - property int columns: 10; - - property string source: "generic.xml" - property var target; - - property color backgroundColor: "black" - - property var keyImageLeft: "" - property var keyImageRight: "" - property var keyImageCenter: "" - - property color keyColor: "#404040" - property color keyPressedColor: "grey" - property int keyBounds: 2 - property var keyPressedColorOpacity: 1 - - property var mainFontFamily: "Roboto" - property color mainFontColor: "white" - property int mainFontSize: 59 - - property var secondaryFontFamily: "Roboto" - property color secondaryFontColor: "white" - property int secondaryFontSize: 30 - - property bool secondaryLabelsVisible: false - property bool doSwitchSource: true - - property bool allUpperCase: false - - signal keyClicked(string key) - signal switchSource(string source) - signal enterClicked() - - Rectangle { - id: root - anchors.fill: parent - color: backgroundColor - - property int keyWidth: keyboard.width / columns; - property int keyHeight: keyboard.height / rows; - - property int xmlIndex: 1 - - Text { - id: proxyMainTextItem - color: keyboard.mainFontColor - font.pixelSize: keyboard.mainFontSize - font.weight: Font.Light - font.family: keyboard.mainFontFamily - font.capitalization: keyboard.allUpperCase ? Font.AllUppercase : - Font.MixedCase - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - } - - Text { - id: proxySecondaryTextItem - color: keyboard.secondaryFontColor - font.pixelSize: keyboard.secondaryFontSize - font.weight: Font.Light - font.family: keyboard.secondaryFontFamily - font.capitalization: keyboard.allUpperCase ? Font.AllUppercase : - Font.MixedCase - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - } - - Column { - id: column - anchors.centerIn: parent - - Repeater { - id: rowRepeater - - model: 4 - //model: XmlListModel { - // id: keyboardModel - // source: keyboard.source - // query: "/Keyboard/Row" - - //Behavior on source { - // NumberAnimation { - // easing.type: Easing.InOutSine - // duration: 100 - // } - //} - //} - - Row { - id: keyRow - property int rowIndex: index - anchors.horizontalCenter: if(parent) parent.horizontalCenter - - Repeater { - id: keyRepeater - - model: XmlListModel { - source: keyboard.source - query: "/Keyboard/Row" + keyRow.rowIndex + "/Key" - - XmlListModelRole { name: "labels"; attributeName: "labels"; elementName: "" } - XmlListModelRole { name: "ratio"; attributeName: "ratio"; elementName: "" } - XmlListModelRole { name: "icon"; attributeName: "icon"; elementName: "" } - XmlListModelRole { name: "checkable"; attributeName: "checkable"; elementName: "" } - } - - Key { - id: key - width: root.keyWidth * ratio - height: root.keyHeight - iconSource: icon - mainFontFamily: proxyMainTextItem.font - mainFontColor: proxyMainTextItem.color - secondaryFontFamily: proxySecondaryTextItem.font - secondaryFontColor: proxySecondaryTextItem.color - secondaryLabelVisible: keyboard.secondaryLabelsVisible - keyColor: keyboard.keyColor - keyImageLeft: keyboard.keyImageLeft - keyImageRight: keyboard.keyImageRight - keyImageCenter: keyboard.keyImageCenter - keyPressedColor: keyboard.keyPressedColor - keyPressedColorOpacity: keyboard.keyPressedColorOpacity - keyBounds: keyboard.keyBounds - isChekable: checkable - isChecked: isChekable && - command && - command === "shift" && - keyboard.allUpperCase - upperCase: keyboard.allUpperCase - - property var command - property var params: labels - - onParamsChanged: { - var labelSplit; - - if(params[0] === '|') - { - mainLabel = '|' - labelSplit = params - } - else - { - labelSplit = params.split(/[|]+/) - - if (labelSplit[0] === '!') - mainLabel = '!'; - else - mainLabel = params.split(/[!|]+/)[0].toString(); - } - - if (labelSplit[1]) secondaryLabels = labelSplit[1]; - - if (labelSplit[0] === '!') - command = params.split(/[!|]+/)[1]; - else - command = params.split(/[!]+/)[1]; - } - - onClicked: { - if (command) - { - var commandList = command.split(":"); - - switch(commandList[0]) - { - case "source": - keyboard.switchSource(commandList[1]) - if(doSwitchSource) keyboard.source = commandList[1] - return; - case "shift": - keyboard.allUpperCase = !keyboard.allUpperCase - return; - case "backspace": - keyboard.keyClicked('\b'); - target.text = target.text.substring(0,target.text.length-1) - return; - case "enter": - keyboard.enterClicked() - return; - case "tab": - keyboard.keyClicked('\t'); - target.text = target.text + " " - return; - default: return; - } - } - if (mainLabel.length === 1) - root.emitKeyClicked(mainLabel); - } - onAlternatesClicked: root.emitKeyClicked(symbol); - } - } - } - } - } - - function emitKeyClicked(text) { - var emitText = keyboard.allUpperCase ? text.toUpperCase() : text; - keyClicked( emitText ); - target.text = target.text + emitText - } - } -} - diff --git a/src/modules/keyboardq/data/Keyboard.qml b/src/modules/keyboardq/data/Keyboard.qml deleted file mode 100644 index 5d1356a826..0000000000 --- a/src/modules/keyboardq/data/Keyboard.qml +++ /dev/null @@ -1,223 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2021 Anke Boersma - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -import QtQuick 2.15 -import QtQuick.XmlListModel 2.10 - -Item { - id: keyboard - - width: 1024 - height: 640 - - property int rows: 4; - property int columns: 10; - - property string source: "generic.xml" - property var target; - - property color backgroundColor: "black" - - property var keyImageLeft: "" - property var keyImageRight: "" - property var keyImageCenter: "" - - property color keyColor: "#404040" - property color keyPressedColor: "grey" - property int keyBounds: 2 - property var keyPressedColorOpacity: 1 - - property var mainFontFamily: "Roboto" - property color mainFontColor: "white" - property int mainFontSize: 59 - - property var secondaryFontFamily: "Roboto" - property color secondaryFontColor: "white" - property int secondaryFontSize: 30 - - property bool secondaryLabelsVisible: false - property bool doSwitchSource: true - - property bool allUpperCase: false - - signal keyClicked(string key) - signal switchSource(string source) - signal enterClicked() - - Rectangle { - id: root - anchors.fill: parent - color: backgroundColor - - property int keyWidth: keyboard.width / columns; - property int keyHeight: keyboard.height / rows; - - property int xmlIndex: 1 - - Text { - id: proxyMainTextItem - color: keyboard.mainFontColor - font.pixelSize: keyboard.mainFontSize - font.weight: Font.Light - font.family: keyboard.mainFontFamily - font.capitalization: keyboard.allUpperCase ? Font.AllUppercase : - Font.MixedCase - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - } - - Text { - id: proxySecondaryTextItem - color: keyboard.secondaryFontColor - font.pixelSize: keyboard.secondaryFontSize - font.weight: Font.Light - font.family: keyboard.secondaryFontFamily - font.capitalization: keyboard.allUpperCase ? Font.AllUppercase : - Font.MixedCase - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - } - - Column { - id: column - anchors.centerIn: parent - - Repeater { - id: rowRepeater - - model: XmlListModel { - id: keyboardModel - source: keyboard.source - query: "/Keyboard/Row" - - Behavior on source { - NumberAnimation { - easing.type: Easing.InOutSine - duration: 100 - } - } - } - - Row { - id: keyRow - property int rowIndex: index - anchors.horizontalCenter: if(parent) parent.horizontalCenter - - Repeater { - id: keyRepeater - - model: XmlListModel { - source: keyboard.source - query: "/Keyboard/Row[" + (rowIndex + 1) + "]/Key" - - XmlRole { name: "labels"; query: "@labels/string()" } - XmlRole { name: "ratio"; query: "@ratio/number()" } - XmlRole { name: "icon"; query: "@icon/string()" } - XmlRole { name: "checkable"; query: "@checkable/string()" } - } - - Key { - id: key - width: root.keyWidth * ratio - height: root.keyHeight - iconSource: icon - mainFontFamily: proxyMainTextItem.font - mainFontColor: proxyMainTextItem.color - secondaryFontFamily: proxySecondaryTextItem.font - secondaryFontColor: proxySecondaryTextItem.color - secondaryLabelVisible: keyboard.secondaryLabelsVisible - keyColor: keyboard.keyColor - keyImageLeft: keyboard.keyImageLeft - keyImageRight: keyboard.keyImageRight - keyImageCenter: keyboard.keyImageCenter - keyPressedColor: keyboard.keyPressedColor - keyPressedColorOpacity: keyboard.keyPressedColorOpacity - keyBounds: keyboard.keyBounds - isChekable: checkable - isChecked: isChekable && - command && - command === "shift" && - keyboard.allUpperCase - upperCase: keyboard.allUpperCase - - property var command - property var params: labels - - onParamsChanged: { - var labelSplit; - - if(params[0] === '|') - { - mainLabel = '|' - labelSplit = params - } - else - { - labelSplit = params.split(/[|]+/) - - if (labelSplit[0] === '!') - mainLabel = '!'; - else - mainLabel = params.split(/[!|]+/)[0].toString(); - } - - if (labelSplit[1]) secondaryLabels = labelSplit[1]; - - if (labelSplit[0] === '!') - command = params.split(/[!|]+/)[1]; - else - command = params.split(/[!]+/)[1]; - } - - onClicked: { - if (command) - { - var commandList = command.split(":"); - - switch(commandList[0]) - { - case "source": - keyboard.switchSource(commandList[1]) - if(doSwitchSource) keyboard.source = commandList[1] - return; - case "shift": - keyboard.allUpperCase = !keyboard.allUpperCase - return; - case "backspace": - keyboard.keyClicked('\b'); - target.text = target.text.substring(0,target.text.length-1) - return; - case "enter": - keyboard.enterClicked() - return; - case "tab": - keyboard.keyClicked('\t'); - target.text = target.text + " " - return; - default: return; - } - } - if (mainLabel.length === 1) - root.emitKeyClicked(mainLabel); - } - onAlternatesClicked: root.emitKeyClicked(symbol); - } - } - } - } - } - - function emitKeyClicked(text) { - var emitText = keyboard.allUpperCase ? text.toUpperCase() : text; - keyClicked( emitText ); - target.text = target.text + emitText - } - } -} - diff --git a/src/modules/keyboardq/data/afgani-qt6.xml b/src/modules/keyboardq/data/afgani-qt6.xml deleted file mode 100644 index 1715a50401..0000000000 --- a/src/modules/keyboardq/data/afgani-qt6.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/keyboardq/data/afgani.xml b/src/modules/keyboardq/data/afgani.xml deleted file mode 100644 index 8b445b2eb6..0000000000 --- a/src/modules/keyboardq/data/afgani.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/keyboardq/data/ar-qt6.xml b/src/modules/keyboardq/data/ar-qt6.xml deleted file mode 100644 index 9cce97297c..0000000000 --- a/src/modules/keyboardq/data/ar-qt6.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/keyboardq/data/ar.xml b/src/modules/keyboardq/data/ar.xml deleted file mode 100644 index a0e5ad0c62..0000000000 --- a/src/modules/keyboardq/data/ar.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/keyboardq/data/backspace.svg b/src/modules/keyboardq/data/backspace.svg deleted file mode 100755 index 4d29e246cd..0000000000 --- a/src/modules/keyboardq/data/backspace.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - Svg Vector Icons : http://www.onlinewebfonts.com/icon - - diff --git a/src/modules/keyboardq/data/backspace.svg.license b/src/modules/keyboardq/data/backspace.svg.license deleted file mode 100644 index 36158c6040..0000000000 --- a/src/modules/keyboardq/data/backspace.svg.license +++ /dev/null @@ -1,2 +0,0 @@ -SPDX-FileCopyrightText: 2019 https://www.onlinewebfonts.com/fonts -SPDX-License-Identifier: GPL-3.0-or-later diff --git a/src/modules/keyboardq/data/button_bkg_center.png b/src/modules/keyboardq/data/button_bkg_center.png deleted file mode 100755 index d17e1698e0b6a10ecdf25905f34ff88760536a95..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4289 zcmeHLeLRzU8=tdqj=Yq2hIQoKFfsDF$e1tNQKmqRES;_9nPaVF>7WH zPgY8FNOC%*jR=pD*GNi*wVvNLq^Ccg^Uw3&bAP`3?Y@8aZ`bd-zSsA~2q3EBKN~@b_?qF#psV0~f1eUA$Z%km|hE{0K=1 z1PbxR6EJJmtXaEut)il$l9H0Lva*VbimIxrnwpxry1IsjhNdQfCJYAC($dn_*4EJh z(1C+v9ekY->wW}>?vJ{FSOZw2P$(N402^Cd+l{t18^O2{ zV56O#oxQ!CgM+=Jql1%^qmz@9vonA*8jaqx31E|pi;Jr(fa~VXo88<1+%Oo7yE}lp zhld9i>yE{O5$oyciNj%WI56V8a5(QRTkv=s9>2v4kN5Tl@bdBT_Qm70sI02{0Y9k1V29lI0*$gGpPr0tAPI zYz++w4h3TUEjXcP7~HjilC;{iM9sZCZxkRT9pv zC@JadpDcM=GPQp&FkFFGagOGc~eZIc!HQa_NB z`({y`)3=HiaO3jxdwX~NvoC4l+CTdX98%}ssa>-8tD~Z!p`m!RNw}2 zdsmYE+=bEcXT;K6XN;G#t@go%$#7i!POWD;2RK@z*>jt`9cj&Sw)^^NV{Uo&DKkY> zrm@GBn&(EGnbQ@fW$hN9-4cVxqu@E_Ua3O`TgYlcOgr@(!P+fJ+vuz;(2D--26@EstL}|lL@E~ z@9GtIMsjt^p~Ce9rlln9FCj_i0G@`hW#Pc14ZNXaRFpS74TA(MQJ`i8vkmSC$WK4l8 zq5tPFCCLiYt@#Ed)!rRdsa9&aGk?SlJ@&iBpN)U>e!i=P+df;B+g|03l|Hkcc}$7l zp8Tn=lP|Gme$UkNXIXmfgk6yky_kPcBnSoPXSyP-Z-bBP_GIXcK)VKO3KWtnNwWjiVt-SS37SU zpxW3movNJj9j#{wGx(W{qvTy3l!e{R_ZI%5(I{nD4%@wGbiaAZ!jg5D9!I%A>}!n9N$#*h5=Dj{3ytU^@KzLGguMRL$yjDbLsMw3*5D|#mWVlJ1Rs(e9@rLgupbFfPk zF47_LUWIpvnvoI1v-u__hPEtznewgGCa~_~L~dgd*JFXIN$Q+K+_hn9%Q4;t%PNY= zSY}t0tN=ag=uzO0IF^9Ld}fz5744v`UsowF73HutzU%PbyaoJwp~`pWrjgMfL7aj z?ug|hjJjNfDiG~Tm#?H}pkA7GgUpK7eXR`wseyS#T8awmVoIwr(#`|!#7^dakwWH@ zF0*w-j%3mtyGEBn%B<}i%mYdWddQ%WE|INd8QX6o&;LEzw!wjX0$Yh~jT zP-<{%f|rwsGoj2tSRfi95A2?}&)tov{gh?*0$WksX%7XVMxtpE!ul1*CtiS|gNd@H zp5bierHB_JVvI`}RMusv@c1Ih5w(E=`vFBa*vlqX2t?OUNKu89FejotqG_RASp?|? zxke6AJzt9bk1UAXm6_Pbd<5+jSG^4NYBSsk>8H&rXhwe@Qf&ZRQTHIMBz+LzqId~n zxe8@3O0))vwV&KBkEpg^*_A|l2!Fwg{;FzJc=*L@dNVzWLbqqorFduJxQ2`R5fZtg zCjhNg98KqE+!=5B!t}~25~@7)qgs2<*pjfk@)`O!x()6y(ns7$V+7c9vW>sKIcQe*eS2xyKT$lyrvBDmHp zb5K#9(seELsE-mMv1WGsT3B5kv3**BHLfmj2~>ejL~xNT=Ris5M68)JYcpw!!Yd@N z0P1kO_Elpp#mtU%iL_e&6&85x;hgVLqY4v1s1<_>>~k6dBsG69k78!YvSdg~+2o=Y z8r|8$I^87R11PMcD47Cd4Qq89Ff^p=)`C8n1noVE>YcWY?m+Q#g5S!fC-4x>1BX$q zjdc+nNY*6D0ZuA>>2j&S6{l;gmwEY=qQ5JyEV0o4&0bEDTu*Y&EPASR%az-DM*S^U z_No2y*u%Nq@XY-#h09gL#^HLww+x(9vv6}Qw~cOX-kALS^XFev^|YBtP|hbL711zv#dW(_%e2Akjk>A$Ll zAIz7&03Q)#jU72?@AQDLUV3ovtU5gXRrSo8u}4|O=gwdX*gxecm!)1t6r90OFW16K zJ%ja(Pw=pL&P7xEStg14fdc{88KyP#1Z~T?+=<#|GW9fkWNY!k+m$I3*EGqj#2Au3 zlR_NDF(%0py_v$5sJOT(9E-WSn`KJ5MDFN?GHtKMr!=>4DBMw*z)a@do_kyk!Bpr4 z;xCmcv8siv^`R0W^+m}o^#}ja{bwyFB8tpP8dj{!F(tJoG_Y5L*W{u5tOuHVW4ce8 z2iMlifEVyXyC!x7)2<)V4|+Rbqf%l1GRIcneNF#<$*TEw`|@L>R|?a7GF8k;PRvwR zP3)f+Q_AMZy>rCA@H|BB$r+1Mhtj;O3B|L;gcq-K$t}O2Ut9DJw5E6eo-iVi-kH=K Vre~}J{&s*sJTcyGOjpX`e*=nhff)b* diff --git a/src/modules/keyboardq/data/button_bkg_center.png.license b/src/modules/keyboardq/data/button_bkg_center.png.license deleted file mode 100644 index d36c167bbd..0000000000 --- a/src/modules/keyboardq/data/button_bkg_center.png.license +++ /dev/null @@ -1,2 +0,0 @@ -SPDX-FileCopyrightText: 2019 MarcoPellin -SPDX-License-Identifier: GPL-3.0-or-later diff --git a/src/modules/keyboardq/data/button_bkg_left.png b/src/modules/keyboardq/data/button_bkg_left.png deleted file mode 100755 index 0a674af6c1a014846efe6cb3531deb7d75b5eb4d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5549 zcmYjVc|4SB*tTZNAf&8C$}(vblBFymOOr5qQ+P*N##V_I!Z1@r(kUh(TFzK!YQ|ce zFf=;qXu%AoLrIn~?U|O5`kr^D^L^hRelw4Eo_o3O>$;!ke$V=2y;PNTm8GPlRK0g> z4*;LOQc}{oic7$^y@I->;6wUofR~%pt;hO&u#k&(-RUYN#Vl0$ftLqsrNcY+9+i?p z^&o%J4-VBF1pi!_>;WYQ9*Rmnj!%k|I*cbICR-&&Ca9Czct~gSc*}V6Pl9tx3+>Oo4=$d?i>K!{ais;NLKDF- zH;uc%)wE2V zPvTeaEh+PjijKN?h0i~jDhk+`PO!MrcEb9u{gx|!*f2(TJHK+!s^;@utMWZFNmsYc zI0zQs2hTjN*!g(${qccq`=Zx7b>R=H&joT_1&-WGni@U%{{GM~?DCnJOO~51U-Av? zjxqQq@A&s;hgCH*tNuz}75${5FJ=0i!&SjNVYqgGHMaKbeoalyQ`blbSD^T&0tId* z{a36Uebhg!ywW$yYS;4^LV?zV|4c#<2GR&I^wTJ@Sn}xRg!I=-S$8_{>BFM3X6o*y zwx*(g!mfB%#ml8&4K{QK^vGN4Msm77bP2egqQ9D>7FnqmJ=$VSyfrAsXl>0EhNn2Z z9kHFlO}@vQ=9A0H?hTM$dqH`OAT*roPqn-FF6k2YJ$?Py^yN1<=#F3&)Vn>Q#kX1Z9-z9sHQ2>iu@z0c5J8uTY^kW|6qsb9X|`hL9JH1A~c?1ZGN3 zdr?jj;uvi8#>gpg&WQ4a2LvXe_igtK5RUh)Eu^pT{r%h=v;8{HKfKvS_E+Jxpr_G-TtyCEG~CA2Gfb!BU-={*w*y#wG02;iXyh;wKaoI5#u zMnn^)3ts5%Mm=Ohc}y*2uN*KU4qq;*`MQns)6n-Mu5F!8?B=Z17h~Pc`)~eCH1$5FU^Xiy^1U>}mSicWV7k{n0g-HdaF7rlt}PZez3baV@wM~6N9OOt;N@dmmtuPsN# zwq~EcRusJPS20#&I_jvuRd>KSsw6erM20$rvUfh?wyk69;Gw89NJPEhu_DM^cijqC z{=4ep{=(+9&W>r+f@TFzC}iSCeKFeVpEUn8*ru*Y>qlpEaikt@6VW!FVSZl>cY!WC zKjrUKFTs>9ZqFOki792o=6^VV(06Bl_xFjL*~jM~h<*_%Vwh$M5`kR&(7lgV{e!yd3U{ z=IU8tC#Q-goqg^JS-nH;u)q(^sOim3-T? z-(v5?4AVxNMp(&ncQuOH%LZ5^g-g|y84jbJnVHq;3tw<^wbd2MYiY+1(L#4p;(6Cp zelS>bPrfMmHeXA&e&V);rW1b3I;W_BSfkF}W|J@*At|ewSTke}?=!X5b-53}$no$? zDVazU{XB+Y>$qkV^OfwNQ{J_(R6aF%JB}Sdc8_EZ>}<%-|4h_YD|wfZXf;(GS7g3$DnE6(&#?Iz|5VNH>?uZs+~Db}w{UIOG>eQT z{K=QrlWdJlOM+Ewe7|0|c{cP{F0nxa<>8V+)HW*l;u%@3Qo6f6Kebpf$9T;iDN94l zab@L43WNXbhi*y*vLWBSH2bb(ogwpC_q%~l@f_(uvb%N!L8Pu%QpQ|>9OP|7KQQNR zXrQ#aLj0H!vV(cmJxTDpgq>#H*A;V=;bzZ0Xt*uvZsZE1N1b7(jrH>myGaK-!QG`L z_M;@~*_wSgv;4zm+1DMQN6yd@qLScs-@B^}D~fTszufCRM2=I*_*}XD5vLq#t9_#D zc_L!BkHZcLi+`apDP2}kfqmh$0F~N(gC^xZGbjPH>8_wmXj0~p#B~b8Q@YBB@k+Wr zpQ^YHv~g45gr5lMJo2yyt58~VeV-4i{v^Yd0hVOIGu~%1GF?etivwm<06kIcpXr>lNCuwU!olqX^rhz&Qon%NtaTg=TR zCN}E_gIIO4Rf;(lT_N7g2$_1)6k@0*fChDmSb%6q(ehMi;o_jkGPIA`)*&ir^3<1> z%OFe^0H=Oyus$3TVkqZ}knfWKrmqZ+hdm$%?fUZbR!Aj^d-9b0;zAquIyp;2MjHeQuYux_s9f$TKq(O`39!&U2xVypLjMYilVhxJk)y3S z^5zXX!ui*a&$%Ez5BpIkTK%&uZ9L8(6ftnolEkqonaeJgFj1pOhIXQ>scHWioKC^v z8aG;;m_zwrik5NhyV{`P2B@FJK|}>|y`QH_GXl9@SIl*zm2^!{Pm92Tq?vcvOwDpD zBg2dGpIqV@Rw1Dn?e2jG%WR~%thRAho`T;KR6e6umCJ5>cYrO`5~PGArUim`o~X^n zDfnriaCxABDwe+j@ni|kQru=A_+-R|l!bM!>2Z=#)-M znLJadEjyB=?z_z&3kpCsUe#$xGiEsPW?A#(b!1#h@?Eh^QI=~N8__xlUp0!{Xim@u z-kq+xhys;=dfLXVP#By9_Ie$3q21R1pfB!e8zpHglo&Q~*%ItGaQg)W>nzpm{{_Fq zFh{Z~kIyakidzDXl|r7re2MXz%Q-1GL-pahrS+&15d1YQgn#m4n&Z)qHTw|U`L1y| z+7Y4<9&6)Rpcot;sJU6U5-wL;1sIl;!4DK^MVClSdjPzkO1jp*YiJc{+Se7==>elv z(K*2Bc)Sdal+rG%Eeom8m&W}IJ43C99>@pFBd{+E_JdRPfp;VnutLKr3`7(td1yEZ z+DWR-kZ4(+k?0}M{S9^s@Ne8DhN+NsmIP-kz&WEU_1PI&u9}!%pljQz zR?S~)1`@!4*8GVf*JP*-Db~MPm|Fxvmd6{=3Q$OAeweYRq$gH}mLF+${JjHh4!#!y zF0(zln;{esvR*L~qs0NX4Cr#=0&EN(gzHcg(8as2%Rn-`nx$M1J%f@8pJ9pc0P&s! z1^w4&=2*OclR?y{8T09QxuOD~YHW)>aJ*Te7vZH#27m|Bkl0h~1G1H-o#rfX{@x2p zfFu#D4M<>dE^<{_+3};$&TPWEoj4?Y7TJxqv**t7UC>7&0s>HW%_?BGRn#rvyLy}r z(BnqT+dug_zT)nq4vM5ssqoPRoknZopymBoUB5DSH{|Fezn+U&*>x|iYzu8I>mg%~ zXbu?a16VZ5deON7be%ew<6(l(4|s?Jr!l~^jtmNWY+y*-T(O|hCIRhYSV7w)%@35d ztS43%03nuc3UleppNnaT{iZEsMyZSd9&06KesBTtM>6$;0^uz{O)1avfcsw6GZ2%A z`)xP`klZ}Mu?`3qInv}I5M&i=4i=Lw513_<77(+)yZmYBcBd8XS$4{^hpYwwSgk$~ z(BgRz1sRk*S6g8uRlVLyA7Q@^g0`aNLRuuiXNQ%VAPf~(0@qoUe2FQ>fA0)mjvRLm zkXisu0dY_l@%`5=G$L`~hwI28OQN1CY5>fIYS|GoyUkod@DsPZJDZ8h-my$=6oCihhw4VQxf4yCpR< zZ&9H_!+Yl;5DhX!Sg6>c(U%JYv|MZTx!<~0^egDuAtvh1frQ5XfWfw!hmbXq5Y9Ja z6cq*pn*xkH&rX4#%&}5q6nwzdI4Bc7=Lz#Hw#1^RZfbEz!d^W!4dlLUI&uf>StdS^ z?3qPs?#OvR*_-s;CBqf;uhQ;-trs8lq+S5!^ea1D29`y!2SRrlj%FPFFV0Cm2 zMLFW$_h}PkRxsRpunA9O6RFuiqwMS{H*gBKs0J^EpDWiBFmIvp;NMsEEW+0pEj{At zLRHoe($sveE*THZMp`8EfT~Q(Tgf=Jm^JodrDR_l9Qyzk-wEfkfraycD#*kn{rrgJ zxq1ojqvV?f?6_QP5x4XU94(pK^16;WNyY)WDuYL09KNd4ZX))P6v=GDCG9~>%T4i` z5fiR=kF7_3>~9tN;Fu}+rh~5y1t&Nd^Yq$*vWhJ8sq~BOy5L)!nx#6v)|uu)rhZ|_ zXi#`P%G)8{(_?c(hRZ4J0nLg{(T|hE-WUc~h0zxJzJH!^a7lwM^bE+nWanQ>gCdoD zkKccExjKzlDwn_fQS+TUPfs#Yv1*nVwl1Ih_HmM*Kh|U6z3s#6>5w$Yl%R1qY2*3) zQ}a+Pfnc4^MAeyN@Cod5LhimohkT+n?2OIqHh%R7l|U|Yvr$@0%bdNbJm2Uz?{;98 z-a5Wx+s7Tp*;UMOZA!+);;ZpE_~naChqS^a#a!e?tSaNoCI)zy(K> zdx-YBqd$7qqn8pjPo`Glxwn%q^!PxXTHNVghmJcV0}cH{Lmu~aZA%y(3F&_wnK|~U zYAj_|zL&CG{z>Jw7e^P9pshT{1UY3;^zw0k8Gn6g*#2__$AQttXa~$*THW0zy*GZS zC8tydrjDfU(i|+A2`TFOH&w^=j$(JQ{Kum&FfTI)yTI7Cm+!S?Fh6e#z3TCkC#Db1 z8~Cba3_)`_-EHj|3gP~5_@A!7zuJ*Zuvqjws$gS5i{nndJvR1f(8*78Pe0pcpef*p zXr8aN>*l)==5SKVhVeFy`RPP;ufn;~k%xE##yFw>^<+gk#nfi8ZoMz>BTa}|yimRM z3vpnb`EF5={nwp*s~jOgFcaKxx5IgQU(b$c4dLwW_Z2F`>n{E&+Y*s}Vy3rXKK!Xs z$C$~AVvi${o0lv=;f+6IOx0Q@LYc7$S--$}94Mje{< zr>Q)s%`sz8=@i`Ji4v)^WazZ@Qk<}6vr7HSI4as|gtR=o00 zVBAJti8VgQdY{Hz=fUC3jQI35n9zADHuD=+Wp`dIDgBwKLfBD^wLI4I+*r=MUbV`* z{@um*N`9KdSGNv&owI0W+0dUl`Mo!3o#*a&Zz|*xe>S`|bPJ-ZR(;vG4ZHvfxasFR z==e6|jABY0DSbSo@h9y3jGa08g`Uh#slGPB`WmR`M>y#f_dT<*g{FFnH#n2q{5$DR&66d*6$=G*(4aPZMZtO)C} z3mfp)=5HRo%M52RoAjye)5CO}?|UinTR)#emE`L0rJfbzD`N`l?d0Qhnla54+~gC) zn-AfkX!Kk9Q=d15wD5hU^?a=8eylWaR&X$IS(crF;gJ1C_06w34ienQQUv=bU+( -SPDX-License-Identifier: GPL-3.0-or-later diff --git a/src/modules/keyboardq/data/button_bkg_right.png b/src/modules/keyboardq/data/button_bkg_right.png deleted file mode 100755 index ce7c4ad7146a5fe93dffe60cd90024de6b2ff6d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5955 zcmYjVdpy(a``@t1xx$*`o;=AhlvZ-gQ$tE2=EG8(<&cReltT`4sE9m8;*lcKj6O@| z(7_Oj%9B_QNs)RSO7u*T?00{*p6~1Thu7@0`*U5_eO>SO`?~Mztm|G!1zB}j6bhxV z%W0=O_}q;`q19Jl!GGRUEP3#OKJM=L2detH<^=d66=?5bk3w;><(6m|@LlGZllO5H zO0gCBLwAH#90m{7PLQAz`@;fGMAIVtQO9UULQj~4`k(l1vx%9>#;xX|#dH)3SF>xU zy~oLepN4mZX&%w)n8hZclAJbq2W}cDdd4ZTiOM^xcTX#@=-q}dt0Ad1Qd{ejs0U@7 zj%`2296JD|I2=n+{tdehoAyCi^;yqX&^vQ0hV_XRqxtcR=V<=~>*GbAtJT#fl-|TI zp6EYLpb&f#IJWScy3+v<0^{3aLZA5@x@${QNNc5;DqOXWv-peKq2W3YF&M2k`8AH& zY25@n?T26AKl!q|`|1lv{)qfP`}q6VGf+2s2mj`VZ53Q~&EhL+jR77VSqj-0%b0)v zX|xL9OkdR7E5EPUlK7X^@qm-duN&U=+wY4<{Km4c6YQXvFyFv z`sO4_>9p#tBXRq=3BuC@8e#W2Yac8xPL+K>o)`b+ZSyo?dU|Q;%V3XtS_kgC?og`2 zXF}S)j41{`Q}ATV3t1?>G&QEEJ@G9EbI|vIX7!t<8E(B$y(g?H%=_lh9~Yq;uoErE zj<@Cbv2-PZ_Eld9|K>rYkriJ}T`$89I#f50=H>)3nbJg@fw4REUWt{FXcaVN8P?G_ z)YYZ<>GvIrWrE(t*A7W)eEXrh;#D`Wy`*cLhnhp=&u=1Mu6};Q4px+KkX_5&$nQdb zu#9-`6t%_QXVV*E0_}l+)fD?mYfJ+VN*{Q6GhJytMeTU4DW$jw_Y`^BPrTAKe0M=T z&}D~T-BOw$^$1Uj-zD81bEx5jL1D4l>WhOjK0}4c3W{3p&q?ksoU69 zwW*xlS=qFNI*Z->y++pTDone5LR{WbX`3}WV$=|BME_1aV?uv$g^XYM^R=bx*~ss3 zi%u#@JwpX&pnq9?r&q%%yz;BrJ;ER4V?Du8`lo?=|NnOERbWmS znyibkd3xb=Sa@5lB4a9<^YFm-yH!&O*f!nC7CzA;VkeS^RAOg(1c(V_B%eDrZDF_d zBe!}4>abz|-s(lYSikcb@#m~ZGGoE?c_y75%2U+*8-asD#k2lKi>UK~^G$c67E>#`mQt{$^_WI@}TC9??qHv+4~d0jBTOdzGs8q1VG(aK>@vz2cwF_p6>- z8y)AFENSzNERS`}HU#(q6{3U4&XZ&_dfyJ75quz{hg2I{^jaZR5`>|$ba)S(FIZuHDm1CyD%N_;Ea z0#);$q+JTe2JEF*^2ZwG&U{MJJxgN0{@3fk5PCN*!)UcKdo%A(o(_T0t*tnBioM+Y z=kT4A)hl*7Q+FNpK4rH4=5Loci;`gJgrq(K>?26&;Gl~%taw0(^s`sQoW^JGQmcw|h{YLT;koA8_n}G@|zxwF9CQu4EKg#fmN5mEkO6 zN?p?WggEXKco8$^!u+#M;#y{H4)xjRzV6{tqUL)q?$l;Jt#E}1J|a&gKJ14)7Q86c z)s%0Z~hjy061`U=oGh3U1IPf(K=x%a9%^UEX~uEGtz0 zR%^);Z}9OUMF^z=yl1pWj7!(&EM(8XSz2E~+>A`pf_n1L zODV2ksRJ#Sr~~q#mqobUUSjR+xzN1zS%Q2z(R_?9kjABwPF-Tnp zZ^Z}bC$q@XA7T)J?>|5^S~#YupFl2Zve)1n8Pg}W%36u<@_YOAs5=@|QDn@vS8D2H znkT0GML}{-O9_fROxZrZAGj}-r5EkNvQzr7c!O(keZaidMzc5dH&gngGF7si*EURY z7NzC0G#nCqR5I46K1d*k%>CTl%}!JW0fG8nKn_&XUtlugJ2u@E)g^!~hU}kY_C6 zJ_3Ena&AsJ*EV{{T-D6>$TeJs$XJ15r5zlEUv`uP=>#)viMMiTL+=D7CREAu5Naa;LX`JL+Ab^4r1I@lgm@iFsU|_dw-RcE; z2omHhbkm&e!7G8qII&WLH(nGSq>U#b#M3ZZES%2BCpI0eWrd-ER3+!UzMe&f6`Db8Q2QgDXcF zl^m6Vbjg>g0^qEuswG%5(~pCHFJ+|2&g8mL(;~T8aTU(B`C;}W5XC411p0B@(N?kZ zA(~=qhB#ok9U-%g?}9QY`#Lfu zNcJ2HeqPiC07X9ArwVC-^45y&5EaO>R5#K8dLB0X`)iAKOR!go_UYKCQn?TQ%ANiX z6##%pwT-B=1Diy}L{edt61jZ8by8ywRe&a^=gRhrhI@*oFZR2R?+?oqo=FIGr&A&GNTWwvcMJ%BP&0Qf^PUK*SRf?TyhiN6BL3g!l@ z)fqFLyg@io>NpGCpaMN$^|h{^HN@8~*cRh71}h@|gQSS^D!((JF; z69#JVZjM+<`!+-INu1aJ)kKv)-bHO##DJo3PW)FC?>JSyL$d0Nf+W!TP#Mk6=uH31 z@F41U3`w1_Z%e*4xtN+OW^4g<w)J2l$&wbjUr z=Pa4&@9--R#yEizf2FuK=bB3%Hbdm!jor^`JP*8^73b zXhnv-Z$pHx8f;|yKXSA{Yjkk}H15&lYPKvRd=)t77;*+trR9JoBp`zbvBIG>2dQN! zTK6kD+X#`G>pbb6)M z-jyP&Q+3(4yis@&D>>z?R=Hs_h7<`^KWsMSG)jo14d@}zmx@u2NiJM2ZB$Cc(AC6b z(eu#4N&5Ks7}5k7?%`|#h-f=-$ZBnj@ua)G`k!Jd8mS_VgDQXVGQaH=%|(gqP>2h8 zlDD4+)CvdA0B1$*L6+`oLKDceZ(2uIHUqGN*bidA9hPj25d_OHq{?3mO5F?2COi^J zuN$$sG0Fw;Bqpq5pA;adjF03m)+Faj^m|hFg66v`;w3gBSeRbJm9f6xFRw6fHrE%Fq z;pe6A9my8Pr3l`=eRNh?H=m`F)tNq*?P>C*{>b#Fy2}@(DBSTZ&hlS0F;M29&lBgf z+q%*3u1z+#1j%ObCFi+ST~_<9CJO8k_48w0u&cP&-(xZMzK(?#owkE~UA8me z%-C<5{8$Z315BbuUwsMh$2X3ke$I7C-Y7rac~z!eZ2cUnLI@qoC479&S*LPbM|EH3 zz;OScb55t&pN69QXQ!TpkV1!JD4^pbaxtFJsY%f(RW_D=q(^x+IjGKi~p=c2Xp0wz>UIeAm2N%g=WDyOn zY_+NjQy5Xxx_vt2CH*KQvzt4A)<{{A|Dc=<}i>wO;-6U}ymX5k>r1dMvP*?cY(UR28U3 zUY2%nd5&$%yYu=fx8HBx=<;4XN>aMw%%y$woOaReJr0ClVvV2LbTxCi-SQI6=H#&i zX!^~U<@ml~cI-Eg=(OmWH>c1ZduZq9t{?b+ev+#8L^Tt9iq+``cz691dUAh7$cm!q z`EPuaN?IzKwQ^c+jgjg-W^sa&hor!CYrijLWY+tO7e7>KN;N;@c8Btd?5f+6y70jy ze@d=R_;aoPY%Bew+S=xN@_bOFYK72yu$-a%++`9iFOJsNeC@VoW8?{;2I!t@{DyLo1VYz=OmMBloY^ z2sOHUg+UK69=iNVR(36scXF+twaeQ-XD?Uv40M~e_E1H`xMVSi5OrxU(dmt+6mRTp zVu$$@-(u>t`aFRTo`zre2VZM{)n|9-VPL#1_FOxpp@ehTkK8OII`g8F5AX7Q~?Z2&K@@=-2H+hf15C2v3t{;AeAzv9OVA+DX^4Odl`=CT zjks*R`JEPZT|b*g2Tw&^N$us`eA4Pn$Q-eQJKoBF3~k^pGk)?%-Oao#?2bG^-@e&A zSddM$$#efE77B_0$D_e<_ZGYxty+SwN z@~ur;@Xt?M6FOIOU<*2pzH)}2)4FzjZc|Nuk{x#*nzHO_+wwLs-{0ucPGyzR?a$QC zZ|gzExd)!Sf5Y5IiEusIhBj-8h<{{%#maNpFP{1!?B~;%?!|M0*9El?gCg%>CeoNf aNn=Hcm+F7`RDc;bY8Pqm&gws?$^QpEvgoh? diff --git a/src/modules/keyboardq/data/button_bkg_right.png.license b/src/modules/keyboardq/data/button_bkg_right.png.license deleted file mode 100644 index d36c167bbd..0000000000 --- a/src/modules/keyboardq/data/button_bkg_right.png.license +++ /dev/null @@ -1,2 +0,0 @@ -SPDX-FileCopyrightText: 2019 MarcoPellin -SPDX-License-Identifier: GPL-3.0-or-later diff --git a/src/modules/keyboardq/data/de-qt6.xml b/src/modules/keyboardq/data/de-qt6.xml deleted file mode 100644 index 16e6bc592d..0000000000 --- a/src/modules/keyboardq/data/de-qt6.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/keyboardq/data/de.xml b/src/modules/keyboardq/data/de.xml deleted file mode 100644 index 883d4dddfd..0000000000 --- a/src/modules/keyboardq/data/de.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/keyboardq/data/empty-qt6.xml b/src/modules/keyboardq/data/empty-qt6.xml deleted file mode 100644 index 94f9a1f4e2..0000000000 --- a/src/modules/keyboardq/data/empty-qt6.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/keyboardq/data/empty.xml b/src/modules/keyboardq/data/empty.xml deleted file mode 100644 index a8afccb115..0000000000 --- a/src/modules/keyboardq/data/empty.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/keyboardq/data/en-qt6.xml b/src/modules/keyboardq/data/en-qt6.xml deleted file mode 100644 index 70d7454ba3..0000000000 --- a/src/modules/keyboardq/data/en-qt6.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/keyboardq/data/en.xml b/src/modules/keyboardq/data/en.xml deleted file mode 100644 index 3602f1d94d..0000000000 --- a/src/modules/keyboardq/data/en.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/keyboardq/data/enter.svg b/src/modules/keyboardq/data/enter.svg deleted file mode 100755 index c66a749213..0000000000 --- a/src/modules/keyboardq/data/enter.svg +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/keyboardq/data/enter.svg.license b/src/modules/keyboardq/data/enter.svg.license deleted file mode 100644 index 36158c6040..0000000000 --- a/src/modules/keyboardq/data/enter.svg.license +++ /dev/null @@ -1,2 +0,0 @@ -SPDX-FileCopyrightText: 2019 https://www.onlinewebfonts.com/fonts -SPDX-License-Identifier: GPL-3.0-or-later diff --git a/src/modules/keyboardq/data/es-qt6.xml b/src/modules/keyboardq/data/es-qt6.xml deleted file mode 100644 index bc627d88e6..0000000000 --- a/src/modules/keyboardq/data/es-qt6.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/keyboardq/data/es.xml b/src/modules/keyboardq/data/es.xml deleted file mode 100644 index 3cac9be1ce..0000000000 --- a/src/modules/keyboardq/data/es.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/keyboardq/data/fr-qt6.xml b/src/modules/keyboardq/data/fr-qt6.xml deleted file mode 100644 index 27ad5a7402..0000000000 --- a/src/modules/keyboardq/data/fr-qt6.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/keyboardq/data/fr.xml b/src/modules/keyboardq/data/fr.xml deleted file mode 100644 index 5328c49a7f..0000000000 --- a/src/modules/keyboardq/data/fr.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/keyboardq/data/generic-qt6.xml b/src/modules/keyboardq/data/generic-qt6.xml deleted file mode 100644 index bcf35bbd8a..0000000000 --- a/src/modules/keyboardq/data/generic-qt6.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/keyboardq/data/generic.xml b/src/modules/keyboardq/data/generic.xml deleted file mode 100644 index 1be4ec4c89..0000000000 --- a/src/modules/keyboardq/data/generic.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/keyboardq/data/generic_qz-qt6.xml b/src/modules/keyboardq/data/generic_qz-qt6.xml deleted file mode 100644 index a5e4f5b619..0000000000 --- a/src/modules/keyboardq/data/generic_qz-qt6.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/keyboardq/data/generic_qz.xml b/src/modules/keyboardq/data/generic_qz.xml deleted file mode 100644 index b8e36cd797..0000000000 --- a/src/modules/keyboardq/data/generic_qz.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/keyboardq/data/pan-end-symbolic.svg b/src/modules/keyboardq/data/pan-end-symbolic.svg deleted file mode 100644 index 0a398fc032..0000000000 --- a/src/modules/keyboardq/data/pan-end-symbolic.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/modules/keyboardq/data/pan-end-symbolic.svg.license b/src/modules/keyboardq/data/pan-end-symbolic.svg.license deleted file mode 100644 index ab91fa292a..0000000000 --- a/src/modules/keyboardq/data/pan-end-symbolic.svg.license +++ /dev/null @@ -1,2 +0,0 @@ -SPDX-FileCopyrightText: 2022 demmm -SPDX-License-Identifier: GPL-3.0-or-later diff --git a/src/modules/keyboardq/data/pt-qt6.xml b/src/modules/keyboardq/data/pt-qt6.xml deleted file mode 100644 index a7e970d4ba..0000000000 --- a/src/modules/keyboardq/data/pt-qt6.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/keyboardq/data/pt.xml b/src/modules/keyboardq/data/pt.xml deleted file mode 100644 index fa883f04d3..0000000000 --- a/src/modules/keyboardq/data/pt.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/keyboardq/data/ru-qt6.xml b/src/modules/keyboardq/data/ru-qt6.xml deleted file mode 100644 index 472c2198ca..0000000000 --- a/src/modules/keyboardq/data/ru-qt6.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/keyboardq/data/ru.xml b/src/modules/keyboardq/data/ru.xml deleted file mode 100644 index 729ff6971a..0000000000 --- a/src/modules/keyboardq/data/ru.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/keyboardq/data/scan.xml b/src/modules/keyboardq/data/scan.xml deleted file mode 100644 index efdb01de04..0000000000 --- a/src/modules/keyboardq/data/scan.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/keyboardq/data/shift.svg b/src/modules/keyboardq/data/shift.svg deleted file mode 100755 index 825ba649b1..0000000000 --- a/src/modules/keyboardq/data/shift.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - Svg Vector Icons : http://www.onlinewebfonts.com/icon - - diff --git a/src/modules/keyboardq/data/shift.svg.license b/src/modules/keyboardq/data/shift.svg.license deleted file mode 100644 index 36158c6040..0000000000 --- a/src/modules/keyboardq/data/shift.svg.license +++ /dev/null @@ -1,2 +0,0 @@ -SPDX-FileCopyrightText: 2019 https://www.onlinewebfonts.com/fonts -SPDX-License-Identifier: GPL-3.0-or-later diff --git a/src/modules/keyboardq/keyboardq-qt6.qml b/src/modules/keyboardq/keyboardq-qt6.qml deleted file mode 100644 index d0b1f85175..0000000000 --- a/src/modules/keyboardq/keyboardq-qt6.qml +++ /dev/null @@ -1,356 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 - 2023 Anke Boersma - * 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 -import QtQuick.Controls -import QtQuick.Window -import QtQuick.Layouts - -import org.kde.kirigami as Kirigami -import "data" - -Item { - width: 800 //parent.width - height: 600 - - readonly property color backgroundColor: "#E6E9EA" //Kirigami.Theme.backgroundColor - readonly property color listBackgroundColor: "white" - readonly property color textFieldColor: "#121212" - readonly property color textFieldBackgroundColor: "#F8F8F8" - readonly property color textColor: Kirigami.Theme.textColor - readonly property color highlightedTextColor: Kirigami.Theme.highlightedTextColor - readonly property color highlightColor: Kirigami.Theme.highlightColor - - property var langXml: ["de", "en", "es", "fr", "ru",] - property var arXml: ["Arabic"] - property var ruXml: ["Azerba", "Belaru", "Kazakh", "Kyrgyz", "Mongol", - "Russia", "Tajik", "Ukrain"] - property var frXml: ["Bambar", "Belgia","French", "Wolof"] - property var enXml: ["Bikol", "Chines", "Englis", "Irish", "Lithua", "Maori"] - property var esXml: ["Spanis"] - property var deXml: ["German"] - property var ptXml: ["Portug"] - property var scanXml: ["Danish", "Finnis", "Norweg", "Swedis"] - property var afganiXml: ["Afghan"] - property var genericXml: ["Armeni", "Bulgar", "Dutch", "Estoni", "Icelan", - "Indone", "Italia", "Latvia", "Maltes", "Moldav", "Romani", "Swahil", "Turkis"] - property var genericQzXml: ["Albani", "Bosnia", "Croati", "Czech", "Hungar", - "Luxemb", "Monten", "Polish", "Serbia", "Sloven", "Slovak"] - property var genericAzXml: [] - - property var keyIndex: [] - - Rectangle { - id: backgroundItem - anchors.fill: parent - width: 800 - color: backgroundColor - - Label { - id: header - anchors.horizontalCenter: parent.horizontalCenter - text: qsTr("Select a layout to activate keyboard preview", "@label") - color: textColor - font.bold: true - } - - Drawer { - id: drawer - width: 0.4 * backgroundItem.width - height: backgroundItem.height - edge: Qt.RightEdge - - ScrollView { - id: scroll1 - anchors.fill: parent - ScrollBar.horizontal.policy: ScrollBar.AlwaysOff - - ListView { - id: models - focus: true - clip: true - boundsBehavior: Flickable.StopAtBounds - width: parent.width - - model: config.keyboardModelsModel - Component.onCompleted: positionViewAtIndex(model.currentIndex, ListView.Center) - currentIndex: model.currentIndex - delegate: ItemDelegate { - - property variant currentModel: model - hoverEnabled: true - width: 0.4 * backgroundItem.width - implicitHeight: 24 - highlighted: ListView.isCurrentItem - Label { - Layout.fillHeight: true - Layout.fillWidth: true - horizontalAlignment: Text.AlignHCenter - width: parent.width - height: 24 - color: highlighted ? "#eff0f1" : "#1F1F1F" - text: model.label - background: Rectangle { - - color: highlighted || hovered ? "#3498DB" : "#ffffff" - opacity: highlighted || hovered ? 0.5 : 0.9 - } - - MouseArea { - hoverEnabled: true - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - onClicked: { - models.currentIndex = index - drawer.close() - } - } - } - } - onCurrentItemChanged: { config.keyboardModels = model[currentIndex] } /* This works because model is a stringlist */ - } - } - } - - Rectangle { - id: modelLabel - anchors.top: header.bottom - anchors.topMargin: 10 - anchors.horizontalCenter: parent.horizontalCenter - width: parent.width / 1.5 - height: 36 - color: mouseBar.containsMouse ? "#eff0f1" : "transparent"; - - MouseArea { - id: mouseBar - anchors.fill: parent; - cursorShape: Qt.PointingHandCursor - hoverEnabled: true - - onClicked: { - drawer.open() - } - Text { - anchors.centerIn: parent - text: qsTr("Keyboard model:  ", "@label") + models.currentItem.currentModel.label - color: textColor - } - Image { - source: "data/pan-end-symbolic.svg" - anchors.centerIn: parent - anchors.horizontalCenterOffset : parent.width / 2.5 - fillMode: Image.PreserveAspectFit - height: 22 - } - } - } - - RowLayout { - id: stack - anchors.top: modelLabel.bottom - anchors.topMargin: 10 - anchors.horizontalCenter: parent.horizontalCenter - width: parent.width / 1.1 - spacing: 10 - - ListView { - id: layouts - - ScrollBar.vertical: ScrollBar { - active: true - } - - Layout.preferredWidth: parent.width / 2 - height: 220 - focus: true - clip: true - boundsBehavior: Flickable.StopAtBounds - spacing: 2 - headerPositioning: ListView.OverlayHeader - header: Rectangle{ - height: 24 - width: parent.width - z: 2 - color:backgroundColor - Text { - text: qsTr("Layout", "@label") - anchors.centerIn: parent - color: textColor - font.bold: true - } - } - - Rectangle { - z: parent.z - 1 - anchors.fill: parent - color: listBackgroundColor - opacity: 0.7 - } - - model: config.keyboardLayoutsModel - currentIndex: model.currentIndex - Component.onCompleted: positionViewAtIndex(model.currentIndex, ListView.Center) - delegate: ItemDelegate { - - hoverEnabled: true - width: parent.width - implicitHeight: 24 - highlighted: ListView.isCurrentItem - - RowLayout { - anchors.fill: parent - - Label { - id: label1 - text: model.label - horizontalAlignment: Text.AlignHCenter - Layout.fillHeight: true - Layout.fillWidth: true - width: parent.width - height: 24 - color: highlighted ? highlightedTextColor : textColor - - background: Rectangle { - color: highlighted || hovered ? highlightColor : listBackgroundColor - opacity: highlighted || hovered ? 0.5 : 0.3 - } - } - } - - onClicked: { - - layouts.model.currentIndex = index - keyIndex = label1.text.substring(0,6) - layouts.positionViewAtIndex(index, ListView.Center) - } - } - } - - ListView { - id: variants - - ScrollBar.vertical: ScrollBar { - active: true - } - - Layout.preferredWidth: parent.width / 2 - height: 220 - focus: true - clip: true - boundsBehavior: Flickable.StopAtBounds - spacing: 2 - headerPositioning: ListView.OverlayHeader - header: Rectangle{ - height: 24 - width: parent.width - z: 2 - color:backgroundColor - Text { - text: qsTr("Variant", "@label") - anchors.centerIn: parent - color: textColor - font.bold: true - } - } - - Rectangle { - z: parent.z - 1 - anchors.fill: parent - color: listBackgroundColor - opacity: 0.7 - } - - model: config.keyboardVariantsModel - currentIndex: model.currentIndex - Component.onCompleted: positionViewAtIndex(model.currentIndex, ListView.Center) - - delegate: ItemDelegate { - hoverEnabled: true - width: parent.width - implicitHeight: 24 - highlighted: ListView.isCurrentItem - - RowLayout { - anchors.fill: parent - - Label { - text: model.label - horizontalAlignment: Text.AlignHCenter - Layout.fillHeight: true - Layout.fillWidth: true - width: parent.width - height: 24 - color: highlighted ? highlightedTextColor : textColor - - background: Rectangle { - color: highlighted || hovered ? highlightColor : listBackgroundColor - opacity: highlighted || hovered ? 0.5 : 0.3 - } - } - } - - onClicked: { - variants.model.currentIndex = index - variants.positionViewAtIndex(index, ListView.Center) - } - } - } - } - - TextField { - id: textInput - placeholderText: qsTr("Type here to test your keyboard…", "@label") - height: 36 - width: parent.width / 1.6 - horizontalAlignment: TextInput.AlignHCenter - anchors.horizontalCenter: parent.horizontalCenter - anchors.bottom: keyboard.top - anchors.bottomMargin: parent.height / 25 - color: textFieldColor - - background:Rectangle { - z: parent.z - 1 - anchors.fill: parent - color: textFieldBackgroundColor - radius: 2 - } - } - - Keyboard { - id: keyboard - width: parent.width - height: parent.height / 3 - anchors.bottom: parent.bottom - source: langXml.includes(keyIndex) ? (keyIndex + ".xml") : - afganiXml.includes(keyIndex) ? "afgani.xml" : - scanXml.includes(keyIndex) ? "scan.xml" : - genericXml.includes(keyIndex) ? "generic.xml" : - genericQzXml.includes(keyIndex) ? "generic_qz.xml" : - arXml.includes(keyIndex) ? "ar.xml" : - deXml.includes(keyIndex) ? "de.xml" : - enXml.includes(keyIndex) ? "en.xml" : - esXml.includes(keyIndex) ? "es.xml" : - frXml.includes(keyIndex) ? "fr.xml" : - ptXml.includes(keyIndex) ? "pt.xml" : - ruXml.includes(keyIndex) ? "ru.xml" :"empty.xml" - rows: 4 - columns: 10 - keyColor: "transparent" - keyPressedColorOpacity: 0.2 - keyImageLeft: "button_bkg_left.png" - keyImageRight: "button_bkg_right.png" - keyImageCenter: "button_bkg_center.png" - target: textInput - onEnterClicked: console.log("Enter!") - } - } -} diff --git a/src/modules/keyboardq/keyboardq-qt6.qrc b/src/modules/keyboardq/keyboardq-qt6.qrc deleted file mode 100644 index c90b24bdcc..0000000000 --- a/src/modules/keyboardq/keyboardq-qt6.qrc +++ /dev/null @@ -1,29 +0,0 @@ - - - ../keyboard/kbd-model-map - ../keyboard/images/restore.png - ../keyboard/non-ascii-layouts - keyboardq-qt6.qml - data/Keyboard-qt6.qml - data/Key-qt6.qml - data/backspace.svg - data/enter.svg - data/shift.svg - data/afgani-qt6.xml - data/ar-qt6.xml - data/de-qt6.xml - data/en-qt6.xml - data/empty-qt6.xml - data/es-qt6.xml - data/fr-qt6.xml - data/generic_qz-qt6.xml - data/generic-qt6.xml - data/pt-qt6.xml - data/ru-qt6.xml - data/scan.xml - data/button_bkg_center.png - data/button_bkg_left.png - data/button_bkg_right.png - data/pan-end-symbolic.svg - - diff --git a/src/modules/keyboardq/keyboardq.conf b/src/modules/keyboardq/keyboardq.conf deleted file mode 100644 index d122f30d78..0000000000 --- a/src/modules/keyboardq/keyboardq.conf +++ /dev/null @@ -1,19 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# NOTE: you must have ckbcomp installed and runnable -# on the live system, for keyboard layout previews. ---- -# The name of the file to write X11 keyboard settings to -# The default value is the name used by upstream systemd-localed. -# Relative paths are assumed to be relative to /etc/X11/xorg.conf.d -xOrgConfFileName: "/etc/X11/xorg.conf.d/00-keyboard.conf" - -# The path to search for keymaps converted from X11 to kbd format -# Leave this empty if the setting does not make sense on your distribution. -convertedKeymapPath: "/lib/kbd/keymaps/xkb" - -# Write keymap configuration to /etc/default/keyboard, usually -# found on Debian-related systems. -# Defaults to true if nothing is set. -#writeEtcDefaultKeyboard: true diff --git a/src/modules/keyboardq/keyboardq.qml b/src/modules/keyboardq/keyboardq.qml deleted file mode 100644 index ad83a996f0..0000000000 --- a/src/modules/keyboardq/keyboardq.qml +++ /dev/null @@ -1,356 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 - 2022 Anke Boersma - * 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.15 -import QtQuick.Layouts 1.3 - -import org.kde.kirigami 2.7 as Kirigami -import "data" - -Item { - width: 800 //parent.width - height: 600 - - readonly property color backgroundColor: "#E6E9EA" //Kirigami.Theme.backgroundColor - readonly property color listBackgroundColor: "white" - readonly property color textFieldColor: "#121212" - readonly property color textFieldBackgroundColor: "#F8F8F8" - readonly property color textColor: Kirigami.Theme.textColor - readonly property color highlightedTextColor: Kirigami.Theme.highlightedTextColor - readonly property color highlightColor: Kirigami.Theme.highlightColor - - property var langXml: ["de", "en", "es", "fr", "ru",] - property var arXml: ["Arabic"] - property var ruXml: ["Azerba", "Belaru", "Kazakh", "Kyrgyz", "Mongol", - "Russia", "Tajik", "Ukrain"] - property var frXml: ["Bambar", "Belgia","French", "Wolof"] - property var enXml: ["Bikol", "Chines", "Englis", "Irish", "Lithua", "Maori"] - property var esXml: ["Spanis"] - property var deXml: ["German"] - property var ptXml: ["Portug"] - property var scanXml: ["Danish", "Finnis", "Norweg", "Swedis"] - property var afganiXml: ["Afghan"] - property var genericXml: ["Armeni", "Bulgar", "Dutch", "Estoni", "Icelan", - "Indone", "Italia", "Latvia", "Maltes", "Moldav", "Romani", "Swahil", "Turkis"] - property var genericQzXml: ["Albani", "Bosnia", "Croati", "Czech", "Hungar", - "Luxemb", "Monten", "Polish", "Serbia", "Sloven", "Slovak"] - property var genericAzXml: [] - - property var keyIndex: [] - - Rectangle { - id: backgroundItem - anchors.fill: parent - width: 800 - color: backgroundColor - - Label { - id: header - anchors.horizontalCenter: parent.horizontalCenter - text: qsTr("Select a layout to activate keyboard preview", "@label") - color: textColor - font.bold: true - } - - Drawer { - id: drawer - width: 0.4 * backgroundItem.width - height: backgroundItem.height - edge: Qt.RightEdge - - ScrollView { - id: scroll1 - anchors.fill: parent - ScrollBar.horizontal.policy: ScrollBar.AlwaysOff - - ListView { - id: models - focus: true - clip: true - boundsBehavior: Flickable.StopAtBounds - width: parent.width - - model: config.keyboardModelsModel - Component.onCompleted: positionViewAtIndex(model.currentIndex, ListView.Center) - currentIndex: model.currentIndex - delegate: ItemDelegate { - - property variant currentModel: model - hoverEnabled: true - width: 0.4 * backgroundItem.width - implicitHeight: 24 - highlighted: ListView.isCurrentItem - Label { - Layout.fillHeight: true - Layout.fillWidth: true - horizontalAlignment: Text.AlignHCenter - width: parent.width - height: 24 - color: highlighted ? "#eff0f1" : "#1F1F1F" - text: model.label - background: Rectangle { - - color: highlighted || hovered ? "#3498DB" : "#ffffff" - opacity: highlighted || hovered ? 0.5 : 0.9 - } - - MouseArea { - hoverEnabled: true - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - onClicked: { - models.currentIndex = index - drawer.close() - } - } - } - } - onCurrentItemChanged: { config.keyboardModels = model[currentIndex] } /* This works because model is a stringlist */ - } - } - } - - Rectangle { - id: modelLabel - anchors.top: header.bottom - anchors.topMargin: 10 - anchors.horizontalCenter: parent.horizontalCenter - width: parent.width / 1.5 - height: 36 - color: mouseBar.containsMouse ? "#eff0f1" : "transparent"; - - MouseArea { - id: mouseBar - anchors.fill: parent; - cursorShape: Qt.PointingHandCursor - hoverEnabled: true - - onClicked: { - drawer.open() - } - Text { - anchors.centerIn: parent - text: qsTr("Keyboard model:  ", "@label") + models.currentItem.currentModel.label - color: textColor - } - Image { - source: "data/pan-end-symbolic.svg" - anchors.centerIn: parent - anchors.horizontalCenterOffset : parent.width / 2.5 - fillMode: Image.PreserveAspectFit - height: 22 - } - } - } - - RowLayout { - id: stack - anchors.top: modelLabel.bottom - anchors.topMargin: 10 - anchors.horizontalCenter: parent.horizontalCenter - width: parent.width / 1.1 - spacing: 10 - - ListView { - id: layouts - - ScrollBar.vertical: ScrollBar { - active: true - } - - Layout.preferredWidth: parent.width / 2 - height: 220 - focus: true - clip: true - boundsBehavior: Flickable.StopAtBounds - spacing: 2 - headerPositioning: ListView.OverlayHeader - header: Rectangle{ - height: 24 - width: parent.width - z: 2 - color:backgroundColor - Text { - text: qsTr("Layout", "@label") - anchors.centerIn: parent - color: textColor - font.bold: true - } - } - - Rectangle { - z: parent.z - 1 - anchors.fill: parent - color: listBackgroundColor - opacity: 0.7 - } - - model: config.keyboardLayoutsModel - currentIndex: model.currentIndex - Component.onCompleted: positionViewAtIndex(model.currentIndex, ListView.Center) - delegate: ItemDelegate { - - hoverEnabled: true - width: parent.width - implicitHeight: 24 - highlighted: ListView.isCurrentItem - - RowLayout { - anchors.fill: parent - - Label { - id: label1 - text: model.label - horizontalAlignment: Text.AlignHCenter - Layout.fillHeight: true - Layout.fillWidth: true - width: parent.width - height: 24 - color: highlighted ? highlightedTextColor : textColor - - background: Rectangle { - color: highlighted || hovered ? highlightColor : listBackgroundColor - opacity: highlighted || hovered ? 0.5 : 0.3 - } - } - } - - onClicked: { - - layouts.model.currentIndex = index - keyIndex = label1.text.substring(0,6) - layouts.positionViewAtIndex(index, ListView.Center) - } - } - } - - ListView { - id: variants - - ScrollBar.vertical: ScrollBar { - active: true - } - - Layout.preferredWidth: parent.width / 2 - height: 220 - focus: true - clip: true - boundsBehavior: Flickable.StopAtBounds - spacing: 2 - headerPositioning: ListView.OverlayHeader - header: Rectangle{ - height: 24 - width: parent.width - z: 2 - color:backgroundColor - Text { - text: qsTr("Variant", "@label") - anchors.centerIn: parent - color: textColor - font.bold: true - } - } - - Rectangle { - z: parent.z - 1 - anchors.fill: parent - color: listBackgroundColor - opacity: 0.7 - } - - model: config.keyboardVariantsModel - currentIndex: model.currentIndex - Component.onCompleted: positionViewAtIndex(model.currentIndex, ListView.Center) - - delegate: ItemDelegate { - hoverEnabled: true - width: parent.width - implicitHeight: 24 - highlighted: ListView.isCurrentItem - - RowLayout { - anchors.fill: parent - - Label { - text: model.label - horizontalAlignment: Text.AlignHCenter - Layout.fillHeight: true - Layout.fillWidth: true - width: parent.width - height: 24 - color: highlighted ? highlightedTextColor : textColor - - background: Rectangle { - color: highlighted || hovered ? highlightColor : listBackgroundColor - opacity: highlighted || hovered ? 0.5 : 0.3 - } - } - } - - onClicked: { - variants.model.currentIndex = index - variants.positionViewAtIndex(index, ListView.Center) - } - } - } - } - - TextField { - id: textInput - placeholderText: qsTr("Type here to test your keyboard…", "@label") - height: 36 - width: parent.width / 1.6 - horizontalAlignment: TextInput.AlignHCenter - anchors.horizontalCenter: parent.horizontalCenter - anchors.bottom: keyboard.top - anchors.bottomMargin: parent.height / 25 - color: textFieldColor - - background:Rectangle { - z: parent.z - 1 - anchors.fill: parent - color: textFieldBackgroundColor - radius: 2 - } - } - - Keyboard { - id: keyboard - width: parent.width - height: parent.height / 3 - anchors.bottom: parent.bottom - source: langXml.includes(keyIndex) ? (keyIndex + ".xml") : - afganiXml.includes(keyIndex) ? "afgani.xml" : - scanXml.includes(keyIndex) ? "scan.xml" : - genericXml.includes(keyIndex) ? "generic.xml" : - genericQzXml.includes(keyIndex) ? "generic_qz.xml" : - arXml.includes(keyIndex) ? "ar.xml" : - deXml.includes(keyIndex) ? "de.xml" : - enXml.includes(keyIndex) ? "en.xml" : - esXml.includes(keyIndex) ? "es.xml" : - frXml.includes(keyIndex) ? "fr.xml" : - ptXml.includes(keyIndex) ? "pt.xml" : - ruXml.includes(keyIndex) ? "ru.xml" :"empty.xml" - rows: 4 - columns: 10 - keyColor: "transparent" - keyPressedColorOpacity: 0.2 - keyImageLeft: "button_bkg_left.png" - keyImageRight: "button_bkg_right.png" - keyImageCenter: "button_bkg_center.png" - target: textInput - onEnterClicked: console.log("Enter!") - } - } -} diff --git a/src/modules/keyboardq/keyboardq.qrc b/src/modules/keyboardq/keyboardq.qrc deleted file mode 100644 index ad777fd1c2..0000000000 --- a/src/modules/keyboardq/keyboardq.qrc +++ /dev/null @@ -1,29 +0,0 @@ - - - ../keyboard/kbd-model-map - ../keyboard/images/restore.png - ../keyboard/non-ascii-layouts - keyboardq.qml - data/Keyboard.qml - data/Key.qml - data/backspace.svg - data/enter.svg - data/shift.svg - data/afgani.xml - data/ar.xml - data/de.xml - data/en.xml - data/empty.xml - data/es.xml - data/fr.xml - data/generic_qz.xml - data/generic.xml - data/pt.xml - data/ru.xml - data/scan.xml - data/button_bkg_center.png - data/button_bkg_left.png - data/button_bkg_right.png - data/pan-end-symbolic.svg - - diff --git a/src/modules/license/CMakeLists.txt b/src/modules/license/CMakeLists.txt deleted file mode 100644 index d214d6ca74..0000000000 --- a/src/modules/license/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# -include_directories(${PROJECT_BINARY_DIR}/src/libcalamaresui) - -calamares_add_plugin(license - TYPE viewmodule - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - LicensePage.cpp - LicenseViewStep.cpp - LicenseWidget.cpp - UI - LicensePage.ui - SHARED_LIB -) diff --git a/src/modules/license/LicensePage.cpp b/src/modules/license/LicensePage.cpp deleted file mode 100644 index 185ed615dd..0000000000 --- a/src/modules/license/LicensePage.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2015 Anke Boersma - * SPDX-FileCopyrightText: 2015 Alexandre Arnt - * SPDX-FileCopyrightText: 2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "LicensePage.h" - -#include "LicenseWidget.h" -#include "ui_LicensePage.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "ViewManager.h" - -#include "utils/Gui.h" -#include "utils/Logger.h" -#include "utils/NamedEnum.h" -#include "utils/Retranslator.h" -#include "utils/Variant.h" - -#include -#include -#include -#include -#include -#include - -#include - -static const char mustAccept[] = "#acceptFrame { border: 1px solid red;" - "background-color: #fff6f6;" - "border-radius: 4px;" - "padding: 2px; }"; -static const char okAccept[] = "#acceptFrame { padding: 3px }"; - -const NamedEnumTable< LicenseEntry::Type >& -LicenseEntry::typeNames() -{ - static const NamedEnumTable< LicenseEntry::Type > names { - { QStringLiteral( "software" ), LicenseEntry::Type::Software }, - { QStringLiteral( "driver" ), LicenseEntry::Type::Driver }, - { QStringLiteral( "gpudriver" ), LicenseEntry::Type::GpuDriver }, - { QStringLiteral( "browserplugin" ), LicenseEntry::Type::BrowserPlugin }, - { QStringLiteral( "codec" ), LicenseEntry::Type::Codec }, - { QStringLiteral( "package" ), LicenseEntry::Type::Package } - }; - - return names; -} - -LicenseEntry::LicenseEntry( const QVariantMap& conf ) -{ - if ( !conf.contains( "id" ) || !conf.contains( "name" ) || !conf.contains( "url" ) ) - { - return; - } - - m_id = conf[ "id" ].toString(); - m_prettyName = conf[ "name" ].toString(); - m_prettyVendor = conf.value( "vendor" ).toString(); - m_url = QUrl( conf[ "url" ].toString() ); - - m_required = Calamares::getBool( conf, "required", false ); - m_expand = Calamares::getBool( conf, "expand", false ); - - bool ok = false; - QString typeString = conf.value( "type", "software" ).toString(); - m_type = typeNames().find( typeString, ok ); - if ( !ok ) - { - cWarning() << "License entry" << m_id << "has unknown type" << typeString << "(using 'software')"; - } -} - -bool -LicenseEntry::isLocal() const -{ - return m_url.isLocalFile(); -} - -LicensePage::LicensePage( QWidget* parent ) - : QWidget( parent ) - , m_isNextEnabled( false ) - , m_allLicensesOptional( false ) - , ui( new Ui::LicensePage ) -{ - ui->setupUi( this ); - - // ui->verticalLayout->insertSpacing( 1, Calamares::defaultFontHeight() ); - Calamares::unmarginLayout( ui->verticalLayout ); - - ui->acceptFrame->setStyleSheet( mustAccept ); - { - // The inner frame was unmargined (above), reinstate margins so all are - // the same *x* (an x-height, approximately). - const auto x = Calamares::defaultFontHeight() / 2; - ui->acceptFrame->layout()->setContentsMargins( x, x, x, x ); - } - - updateGlobalStorage( false ); // Have not agreed yet - - connect( ui->acceptCheckBox, &QCheckBox::toggled, this, &LicensePage::checkAcceptance ); - - CALAMARES_RETRANSLATE_SLOT( &LicensePage::retranslate ); -} - -void -LicensePage::setEntries( const QList< LicenseEntry >& entriesList ) -{ - for ( QWidget* w : m_entries ) - { - ui->licenseEntriesLayout->removeWidget( w ); - w->deleteLater(); - } - - m_allLicensesOptional = true; - - m_entries.clear(); - m_entries.reserve( entriesList.count() ); - for ( const LicenseEntry& entry : entriesList ) - { - LicenseWidget* w = new LicenseWidget( entry ); - ui->licenseEntriesLayout->addWidget( w ); - m_entries.append( w ); - m_allLicensesOptional &= !entry.isRequired(); - } - - ui->acceptCheckBox->setChecked( false ); - checkAcceptance( false ); -} - -void -LicensePage::retranslate() -{ - ui->acceptCheckBox->setText( tr( "I accept the terms and conditions above.", "@info" ) ); - - QString review = tr( "Please review the End User License Agreements (EULAs).", "@info" ); - const auto br = QStringLiteral( "
" ); - - if ( !m_allLicensesOptional ) - { - ui->mainText->setText( tr( "This setup procedure will install proprietary " - "software that is subject to licensing terms.", "@info" ) - + br + review ); - QString mustAcceptText( tr( "If you do not agree with the terms, the setup procedure cannot continue.", "@info" ) ); - ui->acceptCheckBox->setToolTip( mustAcceptText ); - } - else - { - ui->mainText->setText( tr( "This setup procedure can install proprietary " - "software that is subject to licensing terms " - "in order to provide additional features and enhance the user " - "experience.", "@info" ) - + br + review ); - QString okAcceptText( tr( "If you do not agree with the terms, proprietary software will not " - "be installed, and open source alternatives will be used instead.", "@info" ) ); - ui->acceptCheckBox->setToolTip( okAcceptText ); - } - ui->retranslateUi( this ); - - for ( const auto& w : m_entries ) - { - w->retranslateUi(); - } -} - -bool -LicensePage::isNextEnabled() const -{ - return m_isNextEnabled; -} - -void -LicensePage::updateGlobalStorage( bool v ) -{ - Calamares::JobQueue::instance()->globalStorage()->insert( "licenseAgree", v ); -} - -void -LicensePage::checkAcceptance( bool checked ) -{ - updateGlobalStorage( checked ); - - m_isNextEnabled = checked || m_allLicensesOptional; - if ( !m_isNextEnabled ) - { - ui->acceptFrame->setStyleSheet( mustAccept ); - } - else - { - ui->acceptFrame->setStyleSheet( okAccept ); - } - emit nextStatusChanged( m_isNextEnabled ); -} diff --git a/src/modules/license/LicensePage.h b/src/modules/license/LicensePage.h deleted file mode 100644 index cfd991e738..0000000000 --- a/src/modules/license/LicensePage.h +++ /dev/null @@ -1,100 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2015 Anke Boersma - * SPDX-FileCopyrightText: 2015 Alexandre Arnt - * SPDX-FileCopyrightText: 2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef LICENSEPAGE_H -#define LICENSEPAGE_H - -#include "utils/NamedEnum.h" - -#include -#include - -namespace Ui -{ -class LicensePage; -} // namespace Ui - -class LicenseWidget; - -struct LicenseEntry -{ - enum class Type - { - Software = 0, - Driver, - GpuDriver, - BrowserPlugin, - Codec, - Package - }; - - /// @brief Lookup table for the enums - const NamedEnumTable< Type >& typeNames(); - - LicenseEntry( const QVariantMap& conf ); - LicenseEntry( const LicenseEntry& ) = default; - LicenseEntry& operator=( const LicenseEntry& ) = default; - - bool isValid() const { return !m_id.isEmpty(); } - bool isRequired() const { return m_required; } - bool isLocal() const; - bool expandByDefault() const { return m_expand; } - - QString m_id; - QString m_prettyName; - QString m_prettyVendor; - Type m_type = Type::Software; - QUrl m_url; - bool m_required = false; - bool m_expand = false; -}; - -class LicensePage : public QWidget -{ - Q_OBJECT -public: - explicit LicensePage( QWidget* parent = nullptr ); - - void setEntries( const QList< LicenseEntry >& entriesList ); - - bool isNextEnabled() const; - -public slots: - /** @brief Check if the user can continue - * - * The user can continue if - * - none of the licenses are required, or - * - the user has ticked the "OK" box. - * This function calls updateGlobalStorage() as needed, and updates - * the appearance of the page as needed. @p checked indicates whether - * the checkbox has been ticked or not. (e.g. when @p checked is true, - * you can continue regardless) - */ - void checkAcceptance( bool checked ); - - void retranslate(); - -signals: - void nextStatusChanged( bool status ); - -private: - /** @brief Update the global storage "licenseAgree" key. */ - void updateGlobalStorage( bool v ); - - bool m_isNextEnabled; - bool m_allLicensesOptional; ///< @brief all the licenses passed to setEntries are not-required - - Ui::LicensePage* ui; - QList< LicenseWidget* > m_entries; -}; - -#endif //LICENSEPAGE_H diff --git a/src/modules/license/LicensePage.ui b/src/modules/license/LicensePage.ui deleted file mode 100644 index 124e65f7c4..0000000000 --- a/src/modules/license/LicensePage.ui +++ /dev/null @@ -1,172 +0,0 @@ - - - -SPDX-FileCopyrightText: 2015 demmm <anke62@gmail.com> -SPDX-License-Identifier: GPL-3.0-or-later - - LicensePage - - - - 0 - 0 - 799 - 400 - - - - Form - - - - - - - - <h1>License Agreement</h1> - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - - - <Calamares license text> - - - Qt::AlignCenter - - - true - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - 0 - 0 - - - - QFrame::NoFrame - - - Qt::ScrollBarAlwaysOn - - - Qt::ScrollBarAlwaysOff - - - true - - - - - 0 - 0 - 765 - 89 - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - 0 - - - - - Qt::Horizontal - - - - 1 - 20 - - - - - - - - - - - - 0 - 0 - - - - CheckBox - - - - - - - - - - Qt::Horizontal - - - - 1 - 20 - - - - - - - - - - - - - diff --git a/src/modules/license/LicenseViewStep.cpp b/src/modules/license/LicenseViewStep.cpp deleted file mode 100644 index 52305c34fc..0000000000 --- a/src/modules/license/LicenseViewStep.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2015 Anke Boersma - * SPDX-FileCopyrightText: 2015 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "LicenseViewStep.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "LicensePage.h" - -#include "compat/Variant.h" -#include "utils/Logger.h" - -#include - -CALAMARES_PLUGIN_FACTORY_DEFINITION( LicenseViewStepFactory, registerPlugin< LicenseViewStep >(); ) - -LicenseViewStep::LicenseViewStep( QObject* parent ) - : Calamares::ViewStep( parent ) - , m_widget( new LicensePage ) -{ - emit nextStatusChanged( false ); - connect( m_widget, &LicensePage::nextStatusChanged, this, &LicenseViewStep::nextStatusChanged ); -} - - -LicenseViewStep::~LicenseViewStep() -{ - if ( m_widget && m_widget->parent() == nullptr ) - { - m_widget->deleteLater(); - } -} - - -QString -LicenseViewStep::prettyName() const -{ - return tr( "License", "@label" ); -} - - -QWidget* -LicenseViewStep::widget() -{ - return m_widget; -} - - -bool -LicenseViewStep::isNextEnabled() const -{ - return m_widget->isNextEnabled(); -} - - -bool -LicenseViewStep::isBackEnabled() const -{ - return true; -} - - -bool -LicenseViewStep::isAtBeginning() const -{ - return true; -} - - -bool -LicenseViewStep::isAtEnd() const -{ - return true; -} - - -QList< Calamares::job_ptr > -LicenseViewStep::jobs() const -{ - return QList< Calamares::job_ptr >(); -} - -void -LicenseViewStep::setConfigurationMap( const QVariantMap& configurationMap ) -{ - QList< LicenseEntry > entriesList; - if ( configurationMap.contains( "entries" ) - && Calamares::typeOf( configurationMap.value( "entries" ) ) == Calamares::ListVariantType ) - { - const auto entries = configurationMap.value( "entries" ).toList(); - for ( const QVariant& entryV : entries ) - { - if ( Calamares::typeOf( entryV ) != Calamares::MapVariantType ) - { - continue; - } - - LicenseEntry entry( entryV.toMap() ); - if ( entry.isValid() ) - { - entriesList.append( entry ); - } - } - } - - m_widget->setEntries( entriesList ); -} diff --git a/src/modules/license/LicenseViewStep.h b/src/modules/license/LicenseViewStep.h deleted file mode 100644 index 0e028f8c18..0000000000 --- a/src/modules/license/LicenseViewStep.h +++ /dev/null @@ -1,52 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2015 Anke Boersma - * SPDX-FileCopyrightText: 2015 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef LICENSEPAGEPLUGIN_H -#define LICENSEPAGEPLUGIN_H - -#include "DllMacro.h" -#include "utils/PluginFactory.h" -#include "viewpages/ViewStep.h" - -#include -#include -#include - -class LicensePage; - -class PLUGINDLLEXPORT LicenseViewStep : public Calamares::ViewStep -{ - Q_OBJECT - -public: - explicit LicenseViewStep( QObject* parent = nullptr ); - ~LicenseViewStep() override; - - QString prettyName() const override; - - QWidget* widget() override; - - bool isNextEnabled() const override; - bool isBackEnabled() const override; - - bool isAtBeginning() const override; - bool isAtEnd() const override; - - QList< Calamares::job_ptr > jobs() const override; - - void setConfigurationMap( const QVariantMap& configurationMap ) override; - -private: - LicensePage* m_widget; -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( LicenseViewStepFactory ) - -#endif // LICENSEPAGEPLUGIN_H diff --git a/src/modules/license/LicenseWidget.cpp b/src/modules/license/LicenseWidget.cpp deleted file mode 100644 index 4fa59cfd7f..0000000000 --- a/src/modules/license/LicenseWidget.cpp +++ /dev/null @@ -1,198 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2015 Anke Boersma - * SPDX-FileCopyrightText: 2015 Alexandre Arnt - * SPDX-FileCopyrightText: 2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "LicenseWidget.h" - -#include "utils/Logger.h" -#include "utils/QtCompat.h" - -#include -#include -#include -#include -#include -#include - -static QString -loadLocalFile( const QUrl& u ) -{ - if ( !u.isLocalFile() ) - { - return QString(); - } - - QFile file( u.path() ); - if ( !file.open( QIODevice::ReadOnly | QIODevice::Text ) ) - { - cWarning() << "Could not load license file" << u.path(); - return QString(); - } - - return QString( "\n" ) + file.readAll(); -} - -LicenseWidget::LicenseWidget( LicenseEntry entry, QWidget* parent ) - : QWidget( parent ) - , m_entry( std::move( entry ) ) - , m_label( new QLabel( this ) ) - , m_viewLicenseButton( new QPushButton( this ) ) - , m_licenceTextLabel( new QLabel( this ) ) - , m_isExpanded( m_entry.expandByDefault() ) -{ - QPalette pal( palette() ); - pal.setColor( WindowBackground, palette().window().color().lighter( 108 ) ); - - setObjectName( "licenseItem" ); - - setAutoFillBackground( true ); - setPalette( pal ); - setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum ); - setContentsMargins( 4, 4, 4, 4 ); - - QVBoxLayout* vLayout = new QVBoxLayout; - QWidget* topPart = new QWidget( this ); - topPart->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ); - vLayout->addWidget( topPart ); - - QHBoxLayout* wiLayout = new QHBoxLayout; - topPart->setLayout( wiLayout ); - - m_label->setWordWrap( true ); - m_label->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ); - wiLayout->addWidget( m_label ); - - wiLayout->addSpacing( 10 ); - m_viewLicenseButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed ); - wiLayout->addWidget( m_viewLicenseButton ); - - m_licenceTextLabel->setStyleSheet( "border-top: 1px solid black; margin-top: 0px; padding-top: 1em;" ); - m_licenceTextLabel->setObjectName( "licenseItemFullText" ); - - if ( m_entry.isLocal() ) - { - m_fullTextContents = loadLocalFile( m_entry.m_url ); - showLocalLicenseText(); - connect( m_viewLicenseButton, &QAbstractButton::clicked, this, &LicenseWidget::expandClicked ); - } - else - { - m_licenceTextLabel->setText( tr( "URL: %1", "@label" ).arg( m_entry.m_url.toDisplayString() ) ); - connect( m_viewLicenseButton, &QAbstractButton::clicked, this, &LicenseWidget::viewClicked ); - } - m_licenceTextLabel->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ); - - vLayout->addWidget( m_licenceTextLabel ); - setLayout( vLayout ); - - retranslateUi(); -} - -LicenseWidget::~LicenseWidget() {} - -void -LicenseWidget::retranslateUi() -{ - QString productDescription; - switch ( m_entry.m_type ) - { - case LicenseEntry::Type::Driver: - //: %1 is an untranslatable product name, example: Creative Audigy driver - productDescription = tr( "%1 driver
" - "by %2", "@label, %1 is product name, %2 is product vendor" ) - .arg( m_entry.m_prettyName ) - .arg( m_entry.m_prettyVendor ); - break; - case LicenseEntry::Type::GpuDriver: - //: %1 is usually a vendor name, example: Nvidia graphics driver - productDescription = tr( "%1 graphics driver
" - "by %2", "@label, %1 is product name, %2 is product vendor" ) - .arg( m_entry.m_prettyName ) - .arg( m_entry.m_prettyVendor ); - break; - case LicenseEntry::Type::BrowserPlugin: - productDescription = tr( "%1 browser plugin
" - "by %2", "@label, %1 is product name, %2 is product vendor" ) - .arg( m_entry.m_prettyName ) - .arg( m_entry.m_prettyVendor ); - break; - case LicenseEntry::Type::Codec: - productDescription = tr( "%1 codec
" - "by %2", "@label, %1 is product name, %2 is product vendor" ) - .arg( m_entry.m_prettyName ) - .arg( m_entry.m_prettyVendor ); - break; - case LicenseEntry::Type::Package: - productDescription = tr( "%1 package
" - "by %2", "@label, %1 is product name, %2 is product vendor" ) - .arg( m_entry.m_prettyName ) - .arg( m_entry.m_prettyVendor ); - break; - case LicenseEntry::Type::Software: - productDescription = tr( "%1
" - "by %2", "@label, %1 is product name, %2 is product vendor" ) - .arg( m_entry.m_prettyName ) - .arg( m_entry.m_prettyVendor ); - } - m_label->setText( productDescription ); - updateExpandToolTip(); -} - -void -LicenseWidget::showLocalLicenseText() -{ - if ( m_isExpanded ) - { - m_licenceTextLabel->setText( m_fullTextContents ); - } - else - { - QString fileName = m_entry.m_url.toDisplayString(); - if ( fileName.startsWith( "file:" ) ) - { - fileName = fileName.remove( 0, 5 ); - } - m_licenceTextLabel->setText( tr( "File: %1", "@label" ).arg( fileName ) ); - } -} - -void -LicenseWidget::expandClicked() -{ - m_isExpanded = !m_isExpanded; - // Show/hide based on the new arrow direction. - if ( !m_fullTextContents.isEmpty() ) - { - showLocalLicenseText(); - } - - updateExpandToolTip(); -} - -/** @brief Called on retranslate and when button state changes. */ -void -LicenseWidget::updateExpandToolTip() -{ - if ( m_entry.isLocal() ) - { - m_viewLicenseButton->setText( m_isExpanded ? tr( "Hide the license text", "@tooltip" ) : tr( "Show the license text", "@tooltip" ) ); - } - else - { - m_viewLicenseButton->setText( tr( "Open the license agreement in browser", "@tooltip" ) ); - } -} - -void -LicenseWidget::viewClicked() -{ - QDesktopServices::openUrl( m_entry.m_url ); -} diff --git a/src/modules/license/LicenseWidget.h b/src/modules/license/LicenseWidget.h deleted file mode 100644 index eb7d8edd87..0000000000 --- a/src/modules/license/LicenseWidget.h +++ /dev/null @@ -1,45 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2015 Anke Boersma - * SPDX-FileCopyrightText: 2015 Alexandre Arnt - * SPDX-FileCopyrightText: 2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef LICENSE_LICENSEWIDGET_H -#define LICENSE_LICENSEWIDGET_H - -#include "LicensePage.h" - -#include -#include - -class QPushButton; - -class LicenseWidget : public QWidget -{ - Q_OBJECT -public: - LicenseWidget( LicenseEntry e, QWidget* parent = nullptr ); - ~LicenseWidget() override; - - void retranslateUi(); - -private: - void showLocalLicenseText(); // Display (or hide) the local license text - void expandClicked(); // "slot" to toggle show/hide of local license text - void viewClicked(); // "slot" to open link - void updateExpandToolTip(); - - LicenseEntry m_entry; - QLabel* m_label; - QPushButton* m_viewLicenseButton; - QLabel* m_licenceTextLabel; - QString m_fullTextContents; - bool m_isExpanded; -}; -#endif diff --git a/src/modules/license/README.md b/src/modules/license/README.md deleted file mode 100644 index 0ad7a636e7..0000000000 --- a/src/modules/license/README.md +++ /dev/null @@ -1,26 +0,0 @@ -### License Approval Module - - - -For distributions shipping proprietary software, this module creates a -Global Storage entry when the user accepts or declines one or more of -the End User License Agreements files that are presented here. - -The number of licenses shown are configurable. The `license.conf` file -has a few examples of how to add URLs. - -If you do not want to include this module in your Calamares build, -add `-DSKIP_MODULES="license"` to your build settings (CMake call). - -How to implement the removal or not installing of proprietary software is -up to any distribution to implement. For example, proprietary graphics -drivers cannot simply be removed in the packages module, a free version -will need to be installed. - -An example of where the licenseAgree globalstorage entry is used: -https://github.com/KaOSx/calamares/blob/master/src/modules/nonfree_drivers/main.py - -![License Page](http://wstaw.org/m/2015/09/14/Screenshot_20150914_113333.png) diff --git a/src/modules/license/license.conf b/src/modules/license/license.conf deleted file mode 100644 index e32d49984f..0000000000 --- a/src/modules/license/license.conf +++ /dev/null @@ -1,53 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Configuration file for License viewmodule, Calamares -# Syntax is YAML 1.2 ---- -# Define a list of licenses which may / must be accepted before continuing. -# -# Each entry in this list has the following keys: -# - id Entry identifier, must be unique. Not user visible. YAML: string. -# - name Pretty name for the software product, user visible and untranslatable. YAML: string. -# - vendor Pretty name for the software vendor, user visible and untranslatable. YAML: string, optional, default is empty. -# - type Package type identifier for presentation, not user visible but affects user visible strings. YAML: string. -# values: driver, gpudriver, browserplugin, codec, package, software; optional, default is software. -# - required If set to true, the user cannot proceed without accepting this license. YAML: boolean, optional, default is false. -# - url A URL for the license; a remote URL is not shown in Calamares, but a link -# to the URL is provided, which opens in the default web browser. A local -# URL (i.e. file:///) assumes that the contents are HTML or plain text, and -# displays the license in-line. YAML: string, mandatory. -# - expand A boolean value only relevant for **local** URLs. If true, -# the license text is displayed in "expanded" form by -# default, rather than requiring the user to first open it up. -# YAML: boolean, optional, default is false. -entries: -- id: nvidia - name: Nvidia - vendor: Nvidia Corporation - type: driver - url: http://developer.download.nvidia.com/cg/Cg_3.0/license.pdf - required: false -- id: amd - name: Catalyst - vendor: "Advanced Micro Devices, Inc." - type: gpudriver - url: http://support.amd.com/en-us/download/eula - required: false -- id: flashplugin - name: Adobe Flash - vendor: Adobe Systems Incorporated - type: browserplugin - url: http://www.adobe.com/products/eulas/pdfs/PlatformClients_PC_WWEULA_Combined_20100108_1657.pdf - required: true -# This example uses a file: link. This example uses a relative link, which -# is relative to where you run Calamares. Assuming you run it from build/ -# as part of your testing, you'll get the LICENSE text for Calamares -# (which is the text of the GPLv3, not proprietary at all). -- id: mine_mine - name: Calamares Proprietary License - vendor: Calamares, Inc. - type: software - required: true - url: file:../LICENSE - expand: true diff --git a/src/modules/license/license.schema.yaml b/src/modules/license/license.schema.yaml deleted file mode 100644 index d933ac15a0..0000000000 --- a/src/modules/license/license.schema.yaml +++ /dev/null @@ -1,21 +0,0 @@ -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later ---- -$schema: https://json-schema.org/schema# -$id: https://calamares.io/schemas/license -additionalProperties: false -type: object -properties: - entries: - type: array - items: - type: object - additionalProperties: false - properties: - id: { type: string } - name: { type: string } - vendor: { type: string } - type: { type: string } - url: { type: string } - required: { type: boolean, default: false } - expand: { type: boolean, default: false } diff --git a/src/modules/localeq/CMakeLists.txt b/src/modules/localeq/CMakeLists.txt deleted file mode 100644 index eb7cbf0d4c..0000000000 --- a/src/modules/localeq/CMakeLists.txt +++ /dev/null @@ -1,42 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# -if(NOT WITH_QML) - calamares_skip_module( "localeq (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_TIMEZONES "Debug-friendly timezone widget." OFF) - -find_package(${qtname}Location CONFIG) -set_package_properties(${qtname}Location PROPERTIES DESCRIPTION "Used for rendering the map" TYPE RUNTIME) -find_package(${qtname}Positioning CONFIG) -set_package_properties(${qtname}Positioning PROPERTIES DESCRIPTION "Used for GeoLocation and GeoCoding" TYPE RUNTIME) - -# Because we're sharing sources with the regular locale module -set(_locale ${CMAKE_CURRENT_SOURCE_DIR}/../locale) - -calamares_add_plugin(localeq - TYPE viewmodule - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - LocaleQmlViewStep.cpp - ${_locale}/Config.cpp - ${_locale}/LocaleConfiguration.cpp - ${_locale}/LocaleNames.cpp - ${_locale}/SetTimezoneJob.cpp - RESOURCES - localeq${QT_VERSION_SUFFIX}.qrc - LINK_PRIVATE_LIBRARIES - ${qtname}::Network - SHARED_LIB -) -target_include_directories(${localeq_TARGET} PRIVATE ${_locale}) -if(DEBUG_TIMEZONES) - target_compile_definitions(${localeq_TARGET} PRIVATE DEBUG_TIMEZONES) -endif() diff --git a/src/modules/localeq/LocaleQmlViewStep.cpp b/src/modules/localeq/LocaleQmlViewStep.cpp deleted file mode 100644 index 6863bb78ad..0000000000 --- a/src/modules/localeq/LocaleQmlViewStep.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 20182020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "LocaleQmlViewStep.h" - -#include "utils/Logger.h" - -CALAMARES_PLUGIN_FACTORY_DEFINITION( LocaleQmlViewStepFactory, registerPlugin< LocaleQmlViewStep >(); ) - -LocaleQmlViewStep::LocaleQmlViewStep( QObject* parent ) - : Calamares::QmlViewStep( parent ) - , m_config( std::make_unique< Config >( this ) ) -{ -} - -QObject* -LocaleQmlViewStep::getConfig() -{ - return m_config.get(); -} - -QString -LocaleQmlViewStep::prettyName() const -{ - return tr( "Location", "@label" ); -} - -QString -LocaleQmlViewStep::prettyStatus() const -{ - return m_config->prettyStatus(); -} - -bool -LocaleQmlViewStep::isNextEnabled() const -{ - return true; -} - -bool -LocaleQmlViewStep::isBackEnabled() const -{ - return true; -} - - -bool -LocaleQmlViewStep::isAtBeginning() const -{ - return true; -} - - -bool -LocaleQmlViewStep::isAtEnd() const -{ - return true; -} - -Calamares::JobList -LocaleQmlViewStep::jobs() const -{ - return m_config->createJobs(); -} - -void -LocaleQmlViewStep::onActivate() -{ - m_config->setCurrentLocation(); // Finalize the location - QmlViewStep::onActivate(); -} - -void -LocaleQmlViewStep::onLeave() -{ - m_config->finalizeGlobalStorage(); -} - -void -LocaleQmlViewStep::setConfigurationMap( const QVariantMap& configurationMap ) -{ - m_config->setConfigurationMap( configurationMap ); - QmlViewStep::setConfigurationMap( configurationMap ); // call parent implementation last -} diff --git a/src/modules/localeq/LocaleQmlViewStep.h b/src/modules/localeq/LocaleQmlViewStep.h deleted file mode 100644 index ca70ca5d95..0000000000 --- a/src/modules/localeq/LocaleQmlViewStep.h +++ /dev/null @@ -1,51 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2019-2020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef LOCALE_QMLVIEWSTEP_H -#define LOCALE_QMLVIEWSTEP_H - -#include "Config.h" - -#include "DllMacro.h" -#include "utils/PluginFactory.h" -#include "viewpages/QmlViewStep.h" - -#include - -class PLUGINDLLEXPORT LocaleQmlViewStep : public Calamares::QmlViewStep -{ - Q_OBJECT - -public: - explicit LocaleQmlViewStep( QObject* parent = nullptr ); - - QString prettyName() const override; - QString prettyStatus() const override; - - bool isNextEnabled() const override; - bool isBackEnabled() const override; - - bool isAtBeginning() const override; - bool isAtEnd() const override; - - virtual void onActivate() override; - virtual void onLeave() override; - - Calamares::JobList jobs() const override; - - void setConfigurationMap( const QVariantMap& configurationMap ) override; - QObject* getConfig() override; - -private: - std::unique_ptr< Config > m_config; -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( LocaleQmlViewStepFactory ) - -#endif diff --git a/src/modules/localeq/Map-qt6.qml b/src/modules/localeq/Map-qt6.qml deleted file mode 100644 index b485dcadf6..0000000000 --- a/src/modules/localeq/Map-qt6.qml +++ /dev/null @@ -1,263 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 - 2022 Anke Boersma - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -import QtQuick -import QtQuick.Controls -import QtQuick.Window -import QtQuick.Layouts - -import org.kde.kirigami as Kirigami - -import QtLocation -import QtPositioning - -Column { - width: parent.width - - // These are used by the map query to initially center the - // map on the user's likely location. They are updated by - // getIp() which does a more accurate GeoIP lookup than - // the default one in Calamares - property var cityName: "" - property var countryName: "" - - /* This is an extra GeoIP lookup, which will find better-accuracy - * location data for the user's IP, and then sets the current timezone - * and map location. Call it from Component.onCompleted so that - * it happens "on time" before the page is shown. - */ - function getIpOnline() { - var xhr = new XMLHttpRequest - - xhr.onreadystatechange = function() { - if (xhr.readyState === XMLHttpRequest.DONE) { - var responseJSON = JSON.parse(xhr.responseText) - var tz = responseJSON.timezone - var ct = responseJSON.city - var cy = responseJSON.country - - cityName = ct - countryName = cy - - config.setCurrentLocation(tz) - } - } - - // Define the target of the request - xhr.open("GET", "https://get.geojs.io/v1/ip/geo.json") - // Execute the request - xhr.send() - } - - /* This is an "offline" GeoIP lookup -- it just follows what - * Calamares itself has figured out with its GeoIP or configuration. - * Call it from the **Component** onActivate() -- in localeq.qml -- - * so it happens as the page is shown. - */ - function getIpOffline() { - cityName = config.currentLocation.zone - countryName = config.currentLocation.countryCode - } - - /* This is an **accurate** TZ lookup method: it queries an - * online service for the TZ at the given coordinates. It - * requires an internet connection, though, and the distribution - * will need to have an account with geonames to not hit the - * daily query limit. - * - * See below, in MouseArea, for calling the right method. - */ - function getTzOnline() { - var xhr = new XMLHttpRequest - var latC = map.center.latitude - var lonC = map.center.longitude - - xhr.onreadystatechange = function() { - if (xhr.readyState === XMLHttpRequest.DONE) { - var responseJSON = JSON.parse(xhr.responseText) - var tz2 = responseJSON.timezoneId - - config.setCurrentLocation(tz2) - } - } - - console.log("Online lookup", latC, lonC) - // Needs to move to localeq.conf, each distribution will need their own account - xhr.open("GET", "http://api.geonames.org/timezoneJSON?lat=" + latC + "&lng=" + lonC + "&username=SOME_USERNAME") - xhr.send() - } - - /* This is a quick TZ lookup method: it uses the existing - * Calamares "closest TZ" code, which has lots of caveats. - * - * See below, in MouseArea, for calling the right method. - */ - function getTzOffline() { - var latC = map.center.latitude - var lonC = map.center.longitude - var tz = config.zonesModel.lookup(latC, lonC) - console.log("Offline lookup", latC, lonC) - config.setCurrentLocation(tz.region, tz.zone) - } - - Rectangle { - width: parent.width - height: parent.height / 1.28 - - Plugin { - id: mapPlugin - preferred: ["osm", "esri"] // "esri", "here", "itemsoverlay", "mapbox", "mapboxgl", "osm" - } - - Map { - id: map - anchors.fill: parent - plugin: mapPlugin - activeMapType: supportedMapTypes[0] - //might be desirable to set zoom level configurable? - zoomLevel: 7 - bearing: 0 - tilt: 0 - copyrightsVisible : true - fieldOfView : 0 - - GeocodeModel { - id: geocodeModel - plugin: mapPlugin - autoUpdate: true - query: Address { - id: address - city: cityName - country: countryName - } - - onLocationsChanged: { - if (count == 1) { - map.center.latitude = get(0).coordinate.latitude - map.center.longitude = get(0).coordinate.longitude - } - } - } - - MapQuickItem { - id: marker - anchorPoint.x: image.width/4 - anchorPoint.y: image.height - coordinate: QtPositioning.coordinate( - map.center.latitude, - map.center.longitude) - //coordinate: QtPositioning.coordinate(40.730610, -73.935242) // New York - - sourceItem: Image { - id: image - width: 32 - height: 32 - source: "img/pin.svg" - } - } - - MouseArea { - acceptedButtons: Qt.LeftButton - anchors.fill: map - hoverEnabled: true - property var coordinate: map.toCoordinate(Qt.point(mouseX, mouseY)) - - onClicked: { - marker.coordinate = coordinate - map.center.latitude = coordinate.latitude - map.center.longitude = coordinate.longitude - - // Pick a TZ lookup method here (quick:offline, accurate:online) - getTzOffline(); - } - } - } - - Column { - anchors.bottom: parent.bottom - anchors.right: parent.right - anchors.bottomMargin: 5 - anchors.rightMargin: 10 - - MouseArea { - width: 32 - height:32 - cursorShape: Qt.PointingHandCursor - Image { - source: "img/plus.png" - anchors.centerIn: parent - width: 36 - height: 36 - } - - onClicked: map.zoomLevel++ - } - - MouseArea { - width: 32 - height:32 - cursorShape: Qt.PointingHandCursor - Image { - source: "img/minus.png" - anchors.centerIn: parent - width: 32 - height: 32 - } - - onClicked: map.zoomLevel-- - } - } - } - - Rectangle { - width: parent.width - height: 100 - anchors.horizontalCenter: parent.horizontalCenter - - Item { - id: location - Kirigami.Theme.inherit: false - Kirigami.Theme.colorSet: Kirigami.Theme.Complementary - anchors.horizontalCenter: parent.horizontalCenter - - Rectangle { - anchors.centerIn: parent - width: 300 - height: 30 - color: Kirigami.Theme.backgroundColor - - Text { - id: tzText - text: qsTr("Timezone: %1", "@label").arg(config.currentTimezoneName) - color: Kirigami.Theme.textColor - anchors.centerIn: parent - } - - /* If you want an extra (and accurate) GeoIP lookup, - * enable this one and disable the offline lookup in - * onActivate(). - Component.onCompleted: getIpOnline(); - */ - } - } - - Text { - anchors.top: location.bottom - anchors.topMargin: 20 - padding: 10 - width: parent.width - wrapMode: Text.WordWrap - horizontalAlignment: Text.AlignHCenter - Kirigami.Theme.backgroundColor: Kirigami.Theme.backgroundColor - text: qsTr("Please select your preferred location on the map so the installer can suggest the locale - and timezone settings for you. You can fine-tune the suggested settings below. Search the map by dragging - to move and using the +/- buttons to zoom in/out or use mouse scrolling for zooming.", "@label") - } - } -} diff --git a/src/modules/localeq/Map.qml b/src/modules/localeq/Map.qml deleted file mode 100644 index d6b55d5a1a..0000000000 --- a/src/modules/localeq/Map.qml +++ /dev/null @@ -1,263 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 - 2022 Anke Boersma - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -import QtQuick 2.10 -import QtQuick.Controls 2.10 -import QtQuick.Window 2.14 -import QtQuick.Layouts 1.3 - -import org.kde.kirigami 2.7 as Kirigami - -import QtLocation 5.14 -import QtPositioning 5.14 - -Column { - width: parent.width - - // These are used by the map query to initially center the - // map on the user's likely location. They are updated by - // getIp() which does a more accurate GeoIP lookup than - // the default one in Calamares - property var cityName: "" - property var countryName: "" - - /* This is an extra GeoIP lookup, which will find better-accuracy - * location data for the user's IP, and then sets the current timezone - * and map location. Call it from Component.onCompleted so that - * it happens "on time" before the page is shown. - */ - function getIpOnline() { - var xhr = new XMLHttpRequest - - xhr.onreadystatechange = function() { - if (xhr.readyState === XMLHttpRequest.DONE) { - var responseJSON = JSON.parse(xhr.responseText) - var tz = responseJSON.timezone - var ct = responseJSON.city - var cy = responseJSON.country - - cityName = ct - countryName = cy - - config.setCurrentLocation(tz) - } - } - - // Define the target of the request - xhr.open("GET", "https://get.geojs.io/v1/ip/geo.json") - // Execute the request - xhr.send() - } - - /* This is an "offline" GeoIP lookup -- it just follows what - * Calamares itself has figured out with its GeoIP or configuration. - * Call it from the **Component** onActivate() -- in localeq.qml -- - * so it happens as the page is shown. - */ - function getIpOffline() { - cityName = config.currentLocation.zone - countryName = config.currentLocation.countryCode - } - - /* This is an **accurate** TZ lookup method: it queries an - * online service for the TZ at the given coordinates. It - * requires an internet connection, though, and the distribution - * will need to have an account with geonames to not hit the - * daily query limit. - * - * See below, in MouseArea, for calling the right method. - */ - function getTzOnline() { - var xhr = new XMLHttpRequest - var latC = map.center.latitude - var lonC = map.center.longitude - - xhr.onreadystatechange = function() { - if (xhr.readyState === XMLHttpRequest.DONE) { - var responseJSON = JSON.parse(xhr.responseText) - var tz2 = responseJSON.timezoneId - - config.setCurrentLocation(tz2) - } - } - - console.log("Online lookup", latC, lonC) - // Needs to move to localeq.conf, each distribution will need their own account - xhr.open("GET", "http://api.geonames.org/timezoneJSON?lat=" + latC + "&lng=" + lonC + "&username=SOME_USERNAME") - xhr.send() - } - - /* This is a quick TZ lookup method: it uses the existing - * Calamares "closest TZ" code, which has lots of caveats. - * - * See below, in MouseArea, for calling the right method. - */ - function getTzOffline() { - var latC = map.center.latitude - var lonC = map.center.longitude - var tz = config.zonesModel.lookup(latC, lonC) - console.log("Offline lookup", latC, lonC) - config.setCurrentLocation(tz.region, tz.zone) - } - - Rectangle { - width: parent.width - height: parent.height / 1.28 - - Plugin { - id: mapPlugin - preferred: ["osm", "esri"] // "esri", "here", "itemsoverlay", "mapbox", "mapboxgl", "osm" - } - - Map { - id: map - anchors.fill: parent - plugin: mapPlugin - activeMapType: supportedMapTypes[0] - //might be desirable to set zoom level configurable? - zoomLevel: 7 - bearing: 0 - tilt: 0 - copyrightsVisible : true - fieldOfView : 0 - - GeocodeModel { - id: geocodeModel - plugin: mapPlugin - autoUpdate: true - query: Address { - id: address - city: cityName - country: countryName - } - - onLocationsChanged: { - if (count == 1) { - map.center.latitude = get(0).coordinate.latitude - map.center.longitude = get(0).coordinate.longitude - } - } - } - - MapQuickItem { - id: marker - anchorPoint.x: image.width/4 - anchorPoint.y: image.height - coordinate: QtPositioning.coordinate( - map.center.latitude, - map.center.longitude) - //coordinate: QtPositioning.coordinate(40.730610, -73.935242) // New York - - sourceItem: Image { - id: image - width: 32 - height: 32 - source: "img/pin.svg" - } - } - - MouseArea { - acceptedButtons: Qt.LeftButton - anchors.fill: map - hoverEnabled: true - property var coordinate: map.toCoordinate(Qt.point(mouseX, mouseY)) - - onClicked: { - marker.coordinate = coordinate - map.center.latitude = coordinate.latitude - map.center.longitude = coordinate.longitude - - // Pick a TZ lookup method here (quick:offline, accurate:online) - getTzOffline(); - } - } - } - - Column { - anchors.bottom: parent.bottom - anchors.right: parent.right - anchors.bottomMargin: 5 - anchors.rightMargin: 10 - - MouseArea { - width: 32 - height:32 - cursorShape: Qt.PointingHandCursor - Image { - source: "img/plus.png" - anchors.centerIn: parent - width: 36 - height: 36 - } - - onClicked: map.zoomLevel++ - } - - MouseArea { - width: 32 - height:32 - cursorShape: Qt.PointingHandCursor - Image { - source: "img/minus.png" - anchors.centerIn: parent - width: 32 - height: 32 - } - - onClicked: map.zoomLevel-- - } - } - } - - Rectangle { - width: parent.width - height: 100 - anchors.horizontalCenter: parent.horizontalCenter - - Item { - id: location - Kirigami.Theme.inherit: false - Kirigami.Theme.colorSet: Kirigami.Theme.Complementary - anchors.horizontalCenter: parent.horizontalCenter - - Rectangle { - anchors.centerIn: parent - width: 300 - height: 30 - color: Kirigami.Theme.backgroundColor - - Text { - id: tzText - text: qsTr("Timezone: %1", "@label").arg(config.currentTimezoneName) - color: Kirigami.Theme.textColor - anchors.centerIn: parent - } - - /* If you want an extra (and accurate) GeoIP lookup, - * enable this one and disable the offline lookup in - * onActivate(). - Component.onCompleted: getIpOnline(); - */ - } - } - - Text { - anchors.top: location.bottom - anchors.topMargin: 20 - padding: 10 - width: parent.width - wrapMode: Text.WordWrap - horizontalAlignment: Text.AlignHCenter - Kirigami.Theme.backgroundColor: Kirigami.Theme.backgroundColor - text: qsTr("Please select your preferred location on the map so the installer can suggest the locale - and timezone settings for you. You can fine-tune the suggested settings below. Search the map by dragging - to move and using the +/- buttons to zoom in/out or use mouse scrolling for zooming.", "@info") - } - } -} diff --git a/src/modules/localeq/Offline-qt6.qml b/src/modules/localeq/Offline-qt6.qml deleted file mode 100644 index 7d319a1584..0000000000 --- a/src/modules/localeq/Offline-qt6.qml +++ /dev/null @@ -1,243 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020-2022 Anke Boersma - * 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 -import QtQuick.Controls -import QtQuick.Window -import QtQuick.Layouts - -import org.kde.kirigami as Kirigami - -Page { - width: 800 //parent.width - height: 500 - - id: control - property string currentRegion - property string currentZone - - readonly property color backgroundColor: Kirigami.Theme.backgroundColor //"#F5F5F5" - readonly property color backgroundLighterColor: "#ffffff" - readonly property color highlightColor: Kirigami.Theme.highlightColor //"#3498DB" - readonly property color textColor: Kirigami.Theme.textColor - readonly property color highlightedTextColor: Kirigami.Theme.highlightedTextColor - - StackView { - id: stack - anchors.fill: parent - clip: true - - initialItem: Item { - - Label { - - id: region - anchors.horizontalCenter: parent.horizontalCenter - color: textColor - horizontalAlignment: Text.AlignCenter - text: qsTr("Select your preferred region, or use the default settings", "@label") - } - - ListView { - - id: list - ScrollBar.vertical: ScrollBar { - active: true - } - - width: parent.width / 2 - height: parent.height / 1.5 - anchors.centerIn: parent - anchors.verticalCenterOffset: -30 - focus: true - clip: true - boundsBehavior: Flickable.StopAtBounds - spacing: 2 - - Rectangle { - - z: parent.z - 1 - anchors.fill: parent - color: backgroundLighterColor - } - - model: config.regionModel - currentIndex: 1 // offline install, means locale from config - delegate: ItemDelegate { - - hoverEnabled: true - width: parent.width - height: 28 - highlighted: ListView.isCurrentItem - - Label { - - text: model.name - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - width: parent.width - height: 28 - color: highlighted ? highlightedTextColor : textColor - - background: Rectangle { - - color: highlighted || hovered ? highlightColor : backgroundLighterColor - opacity: highlighted || hovered ? 0.5 : 1 - } - } - - onClicked: { - - list.currentIndex = index - control.currentRegion = model.name - config.regionalZonesModel.region = control.currentRegion - tztext.text = qsTr("Timezone: %1", "@label").arg(config.currentTimezoneName) - stack.push(zoneView) - } - } - } - } - - Component { - id: zoneView - - Item { - - Label { - - id: zone - anchors.horizontalCenter: parent.horizontalCenter - color: textColor - text: qsTr("Select your preferred zone within your region", "@label") - } - - ListView { - - id: list2 - ScrollBar.vertical: ScrollBar { - active: true - } - - width: parent.width / 2 - height: parent.height / 1.5 - anchors.centerIn: parent - anchors.verticalCenterOffset: -30 - focus: true - clip: true - boundsBehavior: Flickable.StopAtBounds - spacing: 2 - - Rectangle { - - z: parent.z - 1 - anchors.fill: parent - color: backgroundLighterColor - //radius: 5 - //opacity: 0.7 - } - - model: config.regionalZonesModel - currentIndex : 99 // index of New York - Component.onCompleted: positionViewAtIndex(currentIndex, ListView.Center) - delegate: ItemDelegate { - - hoverEnabled: true - width: parent.width - height: 24 - highlighted: ListView.isCurrentItem - - Label { - - text: model.name - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - width: parent.width - height: 24 - color: highlighted ? highlightedTextColor : textColor - - background: Rectangle { - - color: highlighted || hovered ? highlightColor : backgroundLighterColor - opacity: highlighted || hovered ? 0.5 : 1 - } - } - - onClicked: { - - list2.currentIndex = index - list2.positionViewAtIndex(index, ListView.Center) - control.currentZone = model.name - config.setCurrentLocation(control.currentRegion, control.currentZone) - tztext.text = qsTr("Timezone: %1", "@label").arg(config.currentTimezoneName) - } - } - } - - Button { - - Layout.fillWidth: true - anchors.verticalCenter: parent.verticalCenter - anchors.verticalCenterOffset: -30 - anchors.left: parent.left - anchors.leftMargin: parent.width / 15 - icon.name: "go-previous" - text: qsTr("Zones", "@button") - onClicked: stack.pop() - } - } - } - } - - Rectangle { - - width: parent.width - height: 60 - anchors.horizontalCenter: parent.horizontalCenter - anchors.bottom: parent.bottom - - Item { - - id: location - Kirigami.Theme.inherit: false - Kirigami.Theme.colorSet: Kirigami.Theme.Complementary - anchors.horizontalCenter: parent.horizontalCenter - - Rectangle { - - anchors.centerIn: parent - width: 300 - height: 30 - color: Kirigami.Theme.backgroundColor - - Text { - - id: tztext - text: qsTr("Timezone: %1", "@label").arg(config.currentTimezoneName) - color: Kirigami.Theme.textColor - anchors.centerIn: parent - } - } - } - - Text { - - anchors.top: location.bottom - anchors.topMargin: 20 - padding: 10 - width: parent.width - wrapMode: Text.WordWrap - horizontalAlignment: Text.AlignHCenter - Kirigami.Theme.backgroundColor: Kirigami.Theme.backgroundColor - text: qsTr("You can fine-tune language and locale settings below", "@label") - } - } -} diff --git a/src/modules/localeq/Offline.qml b/src/modules/localeq/Offline.qml deleted file mode 100644 index 9a4aef0e33..0000000000 --- a/src/modules/localeq/Offline.qml +++ /dev/null @@ -1,243 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020-2022 Anke Boersma - * 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.10 -import QtQuick.Controls 2.10 -import QtQuick.Window 2.14 -import QtQuick.Layouts 1.3 - -import org.kde.kirigami 2.7 as Kirigami - -Page { - width: 800 //parent.width - height: 500 - - id: control - property string currentRegion - property string currentZone - - readonly property color backgroundColor: Kirigami.Theme.backgroundColor //"#F5F5F5" - readonly property color backgroundLighterColor: "#ffffff" - readonly property color highlightColor: Kirigami.Theme.highlightColor //"#3498DB" - readonly property color textColor: Kirigami.Theme.textColor - readonly property color highlightedTextColor: Kirigami.Theme.highlightedTextColor - - StackView { - id: stack - anchors.fill: parent - clip: true - - initialItem: Item { - - Label { - - id: region - anchors.horizontalCenter: parent.horizontalCenter - color: textColor - horizontalAlignment: Text.AlignCenter - text: qsTr("Select your preferred region, or use the default settings", "@label") - } - - ListView { - - id: list - ScrollBar.vertical: ScrollBar { - active: true - } - - width: parent.width / 2 - height: parent.height / 1.5 - anchors.centerIn: parent - anchors.verticalCenterOffset: -30 - focus: true - clip: true - boundsBehavior: Flickable.StopAtBounds - spacing: 2 - - Rectangle { - - z: parent.z - 1 - anchors.fill: parent - color: backgroundLighterColor - } - - model: config.regionModel - currentIndex: 1 // offline install, means locale from config - delegate: ItemDelegate { - - hoverEnabled: true - width: parent.width - height: 28 - highlighted: ListView.isCurrentItem - - Label { - - text: model.name - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - width: parent.width - height: 28 - color: highlighted ? highlightedTextColor : textColor - - background: Rectangle { - - color: highlighted || hovered ? highlightColor : backgroundLighterColor - opacity: highlighted || hovered ? 0.5 : 1 - } - } - - onClicked: { - - list.currentIndex = index - control.currentRegion = model.name - config.regionalZonesModel.region = control.currentRegion - tztext.text = qsTr("Timezone: %1", "@label").arg(config.currentTimezoneName) - stack.push(zoneView) - } - } - } - } - - Component { - id: zoneView - - Item { - - Label { - - id: zone - anchors.horizontalCenter: parent.horizontalCenter - color: textColor - text: qsTr("Select your preferred zone within your region", "@label") - } - - ListView { - - id: list2 - ScrollBar.vertical: ScrollBar { - active: true - } - - width: parent.width / 2 - height: parent.height / 1.5 - anchors.centerIn: parent - anchors.verticalCenterOffset: -30 - focus: true - clip: true - boundsBehavior: Flickable.StopAtBounds - spacing: 2 - - Rectangle { - - z: parent.z - 1 - anchors.fill: parent - color: backgroundLighterColor - //radius: 5 - //opacity: 0.7 - } - - model: config.regionalZonesModel - currentIndex : 99 // index of New York - Component.onCompleted: positionViewAtIndex(currentIndex, ListView.Center) - delegate: ItemDelegate { - - hoverEnabled: true - width: parent.width - height: 24 - highlighted: ListView.isCurrentItem - - Label { - - text: model.name - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - width: parent.width - height: 24 - color: highlighted ? highlightedTextColor : textColor - - background: Rectangle { - - color: highlighted || hovered ? highlightColor : backgroundLighterColor - opacity: highlighted || hovered ? 0.5 : 1 - } - } - - onClicked: { - - list2.currentIndex = index - list2.positionViewAtIndex(index, ListView.Center) - control.currentZone = model.name - config.setCurrentLocation(control.currentRegion, control.currentZone) - tztext.text = qsTr("Timezone: %1", "@label").arg(config.currentTimezoneName) - } - } - } - - Button { - - Layout.fillWidth: true - anchors.verticalCenter: parent.verticalCenter - anchors.verticalCenterOffset: -30 - anchors.left: parent.left - anchors.leftMargin: parent.width / 15 - icon.name: "go-previous" - text: qsTr("Zones", "@button") - onClicked: stack.pop() - } - } - } - } - - Rectangle { - - width: parent.width - height: 60 - anchors.horizontalCenter: parent.horizontalCenter - anchors.bottom: parent.bottom - - Item { - - id: location - Kirigami.Theme.inherit: false - Kirigami.Theme.colorSet: Kirigami.Theme.Complementary - anchors.horizontalCenter: parent.horizontalCenter - - Rectangle { - - anchors.centerIn: parent - width: 300 - height: 30 - color: Kirigami.Theme.backgroundColor - - Text { - - id: tztext - text: qsTr("Timezone: %1", "@label").arg(config.currentTimezoneName) - color: Kirigami.Theme.textColor - anchors.centerIn: parent - } - } - } - - Text { - - anchors.top: location.bottom - anchors.topMargin: 20 - padding: 10 - width: parent.width - wrapMode: Text.WordWrap - horizontalAlignment: Text.AlignHCenter - Kirigami.Theme.backgroundColor: Kirigami.Theme.backgroundColor - text: qsTr("You can fine-tune language and locale settings below", "@label") - } - } -} diff --git a/src/modules/localeq/img/locale.svg b/src/modules/localeq/img/locale.svg deleted file mode 100755 index 20c21e5622..0000000000 --- a/src/modules/localeq/img/locale.svg +++ /dev/null @@ -1,5720 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/localeq/img/locale.svg.license b/src/modules/localeq/img/locale.svg.license deleted file mode 100644 index 5f43e650d3..0000000000 --- a/src/modules/localeq/img/locale.svg.license +++ /dev/null @@ -1,2 +0,0 @@ -SPDX-FileCopyrightText: 2020 demmm -SPDX-License-Identifier: GPL-3.0-or-later diff --git a/src/modules/localeq/img/minus.png b/src/modules/localeq/img/minus.png deleted file mode 100644 index be122dff24d8f51868e75d1249794d9073fcc1e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 177 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGooCO|{#S9F5M?jcysy3fAP%zok z#WAE}&fAL@IU5WFSPy3Ww>>V_BO#Xh?Eiy8YmjbaP;>I*gS3779>q_qt9lo8(3a^4 tO9!Wbu!5R{Ps0obL&hYa0J3@zTP#L;AEU&El#Jsbo~Nsy%Q~loCICDuEh+#2 diff --git a/src/modules/localeq/img/minus.png.license b/src/modules/localeq/img/minus.png.license deleted file mode 100644 index 5f43e650d3..0000000000 --- a/src/modules/localeq/img/minus.png.license +++ /dev/null @@ -1,2 +0,0 @@ -SPDX-FileCopyrightText: 2020 demmm -SPDX-License-Identifier: GPL-3.0-or-later diff --git a/src/modules/localeq/img/pin.svg b/src/modules/localeq/img/pin.svg deleted file mode 100644 index b4185d1afb..0000000000 --- a/src/modules/localeq/img/pin.svg +++ /dev/null @@ -1,60 +0,0 @@ - -image/svg+xml - - \ No newline at end of file diff --git a/src/modules/localeq/img/pin.svg.license b/src/modules/localeq/img/pin.svg.license deleted file mode 100644 index 5f43e650d3..0000000000 --- a/src/modules/localeq/img/pin.svg.license +++ /dev/null @@ -1,2 +0,0 @@ -SPDX-FileCopyrightText: 2020 demmm -SPDX-License-Identifier: GPL-3.0-or-later diff --git a/src/modules/localeq/img/plus.png b/src/modules/localeq/img/plus.png deleted file mode 100644 index 3bd5d832c21a5dddebf6c0d2a3df7281259dc388..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 483 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD0wg^q?%xcgSkfJR9T^xl_H+M9WCijSl0AZa z85pY67#JE_7#My5g&JNkFq9fFFuY1&V6d9Oz#v{QXIG#NP=YDR+ueoXe|!I#{XiaP zfk$L90|U1(2s1Lwnj--eWH0gbb!C6TBF1md5Vd00KA_MwPZ!6Kid%1Q8FC$R5OBEI z8KL*0aZl6ov!X@wHJ0@E9zCY^I^&1VpLErh!nz3}s|6>icuu;q^5KS)$x~k46)Ly- z8eP2RYPQ|0WWSQ-j9-}8E^tdY=qE7jZNSMnus*6!?D!5?)FK#IZ0z{o(? zz(m)`D8$gf%Fxuxz+BtFz{ -SPDX-License-Identifier: GPL-3.0-or-later diff --git a/src/modules/localeq/localeq-qt6.qml b/src/modules/localeq/localeq-qt6.qml deleted file mode 100644 index 956f07d969..0000000000 --- a/src/modules/localeq/localeq-qt6.qml +++ /dev/null @@ -1,259 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-FileCopyrightText: 2020 - 2022 Anke Boersma - * 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 -import QtQuick.Controls -import QtQuick.Layouts -import org.kde.kirigami as Kirigami - -Page { - id: root - width: parent.width - height: parent.height - - readonly property color headerBackgroundColor: Kirigami.Theme.alternateBackgroundColor //"#eff0f1" - readonly property color backgroundLighterColor: "#ffffff" - readonly property color highlightColor: Kirigami.Theme.highlightColor //"#3498DB" - readonly property color textColor: Kirigami.Theme.textColor //"#1F1F1F" - readonly property color highlightedTextColor: Kirigami.Theme.highlightedTextColor - - function onActivate() { - /* If you want the map to follow Calamares's GeoIP - * lookup or configuration, call the update function - * here, and disable the one at onCompleted in Map.qml. - */ - if (Network.hasInternet) { image.item.getIpOffline() } - } - - Loader { - id: image - anchors.horizontalCenter: parent.horizontalCenter - width: parent.width - height: parent.height / 1.28 - // Network is in io.calamares.core - source: Network.hasInternet ? "Map.qml" : "Offline.qml" - } - - RowLayout { - anchors.bottom: parent.bottom - anchors.bottomMargin : 20 - width: parent.width - spacing: 50 - - GridLayout { - rowSpacing: Kirigami.Units.largeSpacing - columnSpacing: Kirigami.Units.largeSpacing - - Kirigami.Icon { - source: "qrc:/img/locale.svg" - Layout.fillHeight: true - Layout.maximumHeight: Kirigami.Units.iconSizes.large - Layout.preferredWidth: height - } - - ColumnLayout { - Label { - Layout.fillWidth: true - wrapMode: Text.WordWrap - text: config.currentLanguageStatus - } - Kirigami.Separator { - Layout.fillWidth: true - } - Button { - Layout.alignment: Qt.AlignRight|Qt.AlignVCenter - Layout.columnSpan: 2 - text: qsTr("Change", "@button") - onClicked: { - drawerLanguage.open() - } - } - } - } - - GridLayout { - rowSpacing: Kirigami.Units.largeSpacing - columnSpacing: Kirigami.Units.largeSpacing - - Kirigami.Icon { - source: "qrc:/img/locale.svg" - Layout.fillHeight: true - Layout.maximumHeight: Kirigami.Units.iconSizes.large - Layout.preferredWidth: height - } - ColumnLayout { - Label { - Layout.fillWidth: true - wrapMode: Text.WordWrap - text: config.currentLCStatus - } - Kirigami.Separator { - Layout.fillWidth: true - } - Button { - Layout.alignment: Qt.AlignRight|Qt.AlignVCenter - Layout.columnSpan: 2 - text: qsTr("Change", "@button") - onClicked: { - drawerLocale.open() - } - } - } - } - - Drawer { - id: drawerLanguage - width: 0.33 * root.width - height: root.height - edge: Qt.LeftEdge - - ScrollView { - id: scroll1 - anchors.fill: parent - contentHeight: 800 - ScrollBar.horizontal.policy: ScrollBar.AlwaysOff - - ListView { - id: list1 - focus: true - clip: true - width: parent.width - - model: config.supportedLocales - currentIndex: -1 //config.localeIndex - - header: Rectangle { - width: parent.width - height: 100 - color: "#eff0f1" //headerBackgroundColor - Text { - anchors.fill: parent - wrapMode: Text.WordWrap - text: qsTr("

Languages


- The system locale setting affects the language and character set for some command line user interface elements. The current setting is %1.", "@info").arg(config.currentLanguageCode) - font.pointSize: 10 - } - } - - delegate: ItemDelegate { - - property variant myData: model - hoverEnabled: true - width: drawerLanguage.width - implicitHeight: 24 - highlighted: ListView.isCurrentItem - Label { - Layout.fillHeight: true - Layout.fillWidth: true - horizontalAlignment: Text.AlignHCenter - width: parent.width - height: 24 - color: highlighted ? "#eff0f1" : "#1F1F1F" // headerBackgroundColor : textColor - text: modelData - background: Rectangle { - - color: highlighted || hovered ? highlightColor : backgroundLighterColor - opacity: highlighted || hovered ? 0.5 : 0.9 - } - - MouseArea { - hoverEnabled: true - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - onClicked: { - list1.currentIndex = index - drawerLanguage.close() - } - } - } - } - onCurrentItemChanged: { config.currentLanguageCode = model[currentIndex] } /* This works because model is a stringlist */ - } - } - } - - Drawer { - id: drawerLocale - width: 0.33 * root.width - height: root.height - edge: Qt.RightEdge - - ScrollView { - id: scroll2 - anchors.fill: parent - contentHeight: 800 - ScrollBar.horizontal.policy: ScrollBar.AlwaysOff - - ListView { - id: list2 - focus: true - clip: true - width: parent.width - - model: config.supportedLocales - currentIndex: -1 //model.currentLCCodeIndex - - header: Rectangle { - width: parent.width - height: 100 - color: "#eff0f1" // headerBackgroundColor - Text { - anchors.fill: parent - wrapMode: Text.WordWrap - text: qsTr("

Locales


- The system locale setting affects the numbers and dates format. The current setting is %1.", "@info").arg(config.currentLCCode) - font.pointSize: 10 - } - } - - delegate: ItemDelegate { - - hoverEnabled: true - width: drawerLocale.width - implicitHeight: 24 - highlighted: ListView.isCurrentItem - Label { - Layout.fillHeight: true - Layout.fillWidth: true - horizontalAlignment: Text.AlignHCenter - width: parent.width - height: 24 - color: highlighted ? "#eff0f1" : "#1F1F1F" // headerBackgroundColor : textColor - text: modelData - background: Rectangle { - - color: highlighted || hovered ? highlightColor : backgroundLighterColor - opacity: highlighted || hovered ? 0.5 : 0.9 - } - - MouseArea { - hoverEnabled: true - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - onClicked: { - list2.currentIndex = index - drawerLocale.close() - } - } - } - } - onCurrentItemChanged: { config.currentLCCode = model[currentIndex]; } /* This works because model is a stringlist */ - } - } - } - } - Loader { - id:load - anchors.fill: parent - } -} diff --git a/src/modules/localeq/localeq-qt6.qrc b/src/modules/localeq/localeq-qt6.qrc deleted file mode 100644 index e4414a26f9..0000000000 --- a/src/modules/localeq/localeq-qt6.qrc +++ /dev/null @@ -1,11 +0,0 @@ - - - localeq-qt6.qml - Map-qt6.qml - Offline-qt6.qml - img/locale.svg - img/minus.png - img/pin.svg - img/plus.png - - diff --git a/src/modules/localeq/localeq.conf b/src/modules/localeq/localeq.conf deleted file mode 100644 index bb2a7e8167..0000000000 --- a/src/modules/localeq/localeq.conf +++ /dev/null @@ -1,100 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# ---- -# This settings are used to set your default system time zone. -# Time zones are usually located under /usr/share/zoneinfo and -# provided by the 'tzdata' package of your Distribution. -# -# Distributions using systemd can list available -# time zones by using the timedatectl command. -# timedatectl list-timezones -# -# The starting timezone (e.g. the pin-on-the-map) when entering -# the locale page can be set through keys *region* and *zone*. -# If either is not set, defaults to America/New_York. -# -region: "America" -zone: "New_York" - - -# System locales are detected in the following order: -# -# - /usr/share/i18n/SUPPORTED -# - localeGenPath (defaults to /etc/locale.gen if not set) -# - 'locale -a' output -# -# Enable only when your Distribution is using an -# custom path for locale.gen -# -#localeGenPath: "PATH_TO/locale.gen" - -# GeoIP based Language settings: Leave commented out to disable GeoIP. -# -# GeoIP needs a working Internet connection. -# This can be managed from `welcome.conf` by adding -# internet to the list of required conditions. -# -# The configuration -# is in three parts: a *style*, which can be "json" or "xml" -# depending on the kind of data returned by the service, and -# a *url* where the data is retrieved, and an optional *selector* -# to pick the right field out of the returned data (e.g. field -# name in JSON or element name in XML). -# -# The default selector (when the setting is blank) is picked to -# work with existing JSON providers (which use "time_zone") and -# Ubiquity's XML providers (which use "TimeZone"). -# -# If the service configured via *url* uses -# a different attribute name (e.g. "timezone") in JSON or a -# different element tag (e.g. "") in XML, set this -# string to the name or tag to be used. -# -# In JSON: -# - if the string contains "." characters, this is used as a -# multi-level selector, e.g. "a.b" will select the timezone -# from data "{a: {b: "Europe/Amsterdam" } }". -# - each part of the string split by "." characters is used as -# a key into the JSON data. -# In XML: -# - all elements with the named tag (e.g. all TimeZone) elements -# from the document are checked; the first one with non-empty -# text value is used. -# -# -# An HTTP(S) request is made to *url*. The request should return -# valid data in a suitable format, depending on *style*; -# generally this includes a string value with the timezone -# in / format. For services that return data which -# does not follow the conventions of "suitable data" described -# below, *selector* may be used to pick different data. -# -# Note that this example URL works, but the service is shutting -# down in June 2018. -# -# Suitable JSON data looks like -# ``` -# {"time_zone":"America/New_York"} -# ``` -# Suitable XML data looks like -# ``` -# Europe/Brussels -# ``` -# -# To accommodate providers of GeoIP timezone data with peculiar timezone -# naming conventions, the following cleanups are performed automatically: -# - backslashes are removed -# - spaces are replaced with _ -# -# Legacy settings "geoipStyle", "geoipUrl" and "geoipSelector" -# in the top-level are still supported, but I'd advise against. -# -# To disable GeoIP checking, either comment-out the entire geoip section, -# or set the *style* key to an unsupported format (e.g. `none`). -# Also, note the analogous feature in src/modules/welcome/welcome.conf. -# -geoip: - style: "json" - url: "https://geoip.kde.org/v1/calamares" - selector: "" # leave blank for the default diff --git a/src/modules/localeq/localeq.qml b/src/modules/localeq/localeq.qml deleted file mode 100644 index 7467f7ddc9..0000000000 --- a/src/modules/localeq/localeq.qml +++ /dev/null @@ -1,259 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-FileCopyrightText: 2020 - 2022 Anke Boersma - * 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.10 -import QtQuick.Controls 2.10 -import QtQuick.Layouts 1.3 -import org.kde.kirigami 2.7 as Kirigami - -Page { - id: root - width: parent.width - height: parent.height - - readonly property color headerBackgroundColor: Kirigami.Theme.alternateBackgroundColor //"#eff0f1" - readonly property color backgroundLighterColor: "#ffffff" - readonly property color highlightColor: Kirigami.Theme.highlightColor //"#3498DB" - readonly property color textColor: Kirigami.Theme.textColor //"#1F1F1F" - readonly property color highlightedTextColor: Kirigami.Theme.highlightedTextColor - - function onActivate() { - /* If you want the map to follow Calamares's GeoIP - * lookup or configuration, call the update function - * here, and disable the one at onCompleted in Map.qml. - */ - if (Network.hasInternet) { image.item.getIpOffline() } - } - - Loader { - id: image - anchors.horizontalCenter: parent.horizontalCenter - width: parent.width - height: parent.height / 1.28 - // Network is in io.calamares.core - source: Network.hasInternet ? "Map.qml" : "Offline.qml" - } - - RowLayout { - anchors.bottom: parent.bottom - anchors.bottomMargin : 20 - width: parent.width - spacing: 50 - - GridLayout { - rowSpacing: Kirigami.Units.largeSpacing - columnSpacing: Kirigami.Units.largeSpacing - - Kirigami.Icon { - source: "qrc:/img/locale.svg" - Layout.fillHeight: true - Layout.maximumHeight: Kirigami.Units.iconSizes.large - Layout.preferredWidth: height - } - - ColumnLayout { - Label { - Layout.fillWidth: true - wrapMode: Text.WordWrap - text: config.currentLanguageStatus - } - Kirigami.Separator { - Layout.fillWidth: true - } - Button { - Layout.alignment: Qt.AlignRight|Qt.AlignVCenter - Layout.columnSpan: 2 - text: qsTr("Change", "@button") - onClicked: { - drawerLanguage.open() - } - } - } - } - - GridLayout { - rowSpacing: Kirigami.Units.largeSpacing - columnSpacing: Kirigami.Units.largeSpacing - - Kirigami.Icon { - source: "qrc:/img/locale.svg" - Layout.fillHeight: true - Layout.maximumHeight: Kirigami.Units.iconSizes.large - Layout.preferredWidth: height - } - ColumnLayout { - Label { - Layout.fillWidth: true - wrapMode: Text.WordWrap - text: config.currentLCStatus - } - Kirigami.Separator { - Layout.fillWidth: true - } - Button { - Layout.alignment: Qt.AlignRight|Qt.AlignVCenter - Layout.columnSpan: 2 - text: qsTr("Change", "@button") - onClicked: { - drawerLocale.open() - } - } - } - } - - Drawer { - id: drawerLanguage - width: 0.33 * root.width - height: root.height - edge: Qt.LeftEdge - - ScrollView { - id: scroll1 - anchors.fill: parent - contentHeight: 800 - ScrollBar.horizontal.policy: ScrollBar.AlwaysOff - - ListView { - id: list1 - focus: true - clip: true - width: parent.width - - model: config.supportedLocales - currentIndex: -1 //config.localeIndex - - header: Rectangle { - width: parent.width - height: 100 - color: "#eff0f1" //headerBackgroundColor - Text { - anchors.fill: parent - wrapMode: Text.WordWrap - text: qsTr("

Languages


- The system locale setting affects the language and character set for some command line user interface elements. The current setting is %1.", "@info").arg(config.currentLanguageCode) - font.pointSize: 10 - } - } - - delegate: ItemDelegate { - - property variant myData: model - hoverEnabled: true - width: drawerLanguage.width - implicitHeight: 24 - highlighted: ListView.isCurrentItem - Label { - Layout.fillHeight: true - Layout.fillWidth: true - horizontalAlignment: Text.AlignHCenter - width: parent.width - height: 24 - color: highlighted ? "#eff0f1" : "#1F1F1F" // headerBackgroundColor : textColor - text: modelData - background: Rectangle { - - color: highlighted || hovered ? highlightColor : backgroundLighterColor - opacity: highlighted || hovered ? 0.5 : 0.9 - } - - MouseArea { - hoverEnabled: true - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - onClicked: { - list1.currentIndex = index - drawerLanguage.close() - } - } - } - } - onCurrentItemChanged: { config.currentLanguageCode = model[currentIndex] } /* This works because model is a stringlist */ - } - } - } - - Drawer { - id: drawerLocale - width: 0.33 * root.width - height: root.height - edge: Qt.RightEdge - - ScrollView { - id: scroll2 - anchors.fill: parent - contentHeight: 800 - ScrollBar.horizontal.policy: ScrollBar.AlwaysOff - - ListView { - id: list2 - focus: true - clip: true - width: parent.width - - model: config.supportedLocales - currentIndex: -1 //model.currentLCCodeIndex - - header: Rectangle { - width: parent.width - height: 100 - color: "#eff0f1" // headerBackgroundColor - Text { - anchors.fill: parent - wrapMode: Text.WordWrap - text: qsTr("

Locales


- The system locale setting affects the numbers and dates format. The current setting is %1.", "@info").arg(config.currentLCCode) - font.pointSize: 10 - } - } - - delegate: ItemDelegate { - - hoverEnabled: true - width: drawerLocale.width - implicitHeight: 24 - highlighted: ListView.isCurrentItem - Label { - Layout.fillHeight: true - Layout.fillWidth: true - horizontalAlignment: Text.AlignHCenter - width: parent.width - height: 24 - color: highlighted ? "#eff0f1" : "#1F1F1F" // headerBackgroundColor : textColor - text: modelData - background: Rectangle { - - color: highlighted || hovered ? highlightColor : backgroundLighterColor - opacity: highlighted || hovered ? 0.5 : 0.9 - } - - MouseArea { - hoverEnabled: true - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - onClicked: { - list2.currentIndex = index - drawerLocale.close() - } - } - } - } - onCurrentItemChanged: { config.currentLCCode = model[currentIndex]; } /* This works because model is a stringlist */ - } - } - } - } - Loader { - id:load - anchors.fill: parent - } -} diff --git a/src/modules/localeq/localeq.qrc b/src/modules/localeq/localeq.qrc deleted file mode 100644 index af6f7e911b..0000000000 --- a/src/modules/localeq/localeq.qrc +++ /dev/null @@ -1,11 +0,0 @@ - - - localeq.qml - Map.qml - Offline.qml - img/locale.svg - img/minus.png - img/pin.svg - img/plus.png - - diff --git a/src/modules/luksbootkeyfile/CMakeLists.txt b/src/modules/luksbootkeyfile/CMakeLists.txt deleted file mode 100644 index 735d3174f9..0000000000 --- a/src/modules/luksbootkeyfile/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# -calamares_add_plugin(luksbootkeyfile - TYPE job - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - LuksBootKeyFileJob.cpp - SHARED_LIB -) - -calamares_add_test(luksbootkeyfiletest SOURCES Tests.cpp LuksBootKeyFileJob.cpp) diff --git a/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp b/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp deleted file mode 100644 index 620957d278..0000000000 --- a/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp +++ /dev/null @@ -1,343 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#include "LuksBootKeyFileJob.h" - -#include "utils/Entropy.h" -#include "utils/Logger.h" -#include "utils/NamedEnum.h" -#include "utils/System.h" -#include "utils/UMask.h" -#include "utils/Variant.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" - -#include -#include - -LuksBootKeyFileJob::LuksBootKeyFileJob( QObject* parent ) - : Calamares::CppJob( parent ) -{ -} - -LuksBootKeyFileJob::~LuksBootKeyFileJob() {} - -QString -LuksBootKeyFileJob::prettyName() const -{ - return tr( "Configuring LUKS key file." ); -} - -struct LuksDevice -{ - LuksDevice( const QMap< QString, QVariant >& pinfo ) - : isValid( false ) - , isRoot( false ) - { - if ( pinfo.contains( "luksMapperName" ) ) - { - QString fs = pinfo[ "fs" ].toString(); - QString mountPoint = pinfo[ "mountPoint" ].toString(); - - if ( !mountPoint.isEmpty() || fs == QStringLiteral( "linuxswap" ) ) - { - isValid = true; - isRoot = mountPoint == '/'; - device = pinfo[ "device" ].toString(); - passphrase = pinfo[ "luksPassphrase" ].toString(); - } - } - } - - bool isValid; - bool isRoot; - QString device; - QString passphrase; -}; - -/** @brief Extract the luks passphrases setup. - * - * Given a list of partitions (as set up by the partitioning module, - * so there's maps with keys inside), returns just the list of - * luks passphrases for each device. - */ -static QList< LuksDevice > -getLuksDevices( const QVariantList& list ) -{ - QList< LuksDevice > luksItems; - - for ( const auto& p : list ) - { - if ( p.canConvert< QVariantMap >() ) - { - LuksDevice d( p.toMap() ); - if ( d.isValid ) - { - luksItems.append( d ); - } - } - } - return luksItems; -} - -struct LuksDeviceList -{ - LuksDeviceList( const QVariant& partitions ) - : valid( false ) - { - if ( partitions.canConvert< QVariantList >() ) - { - devices = getLuksDevices( partitions.toList() ); - valid = true; - } - } - - QList< LuksDevice > devices; - bool valid; -}; - -static const char keyfile[] = "/crypto_keyfile.bin"; - -static bool -generateTargetKeyfile() -{ - Calamares::UMask m( Calamares::UMask::Safe ); - - // Get the data - QByteArray entropy; - auto entropySource = Calamares::getEntropy( 2048, entropy ); - if ( entropySource != Calamares::EntropySource::URandom ) - { - cWarning() << "Could not get entropy from /dev/urandom for LUKS."; - return false; - } - - auto fileResult - = Calamares::System::instance()->createTargetFile( keyfile, entropy, Calamares::System::WriteMode::Overwrite ); - entropy.fill( 'A' ); - if ( !fileResult ) - { - cWarning() << "Could not create LUKS keyfile:" << smash( fileResult.code() ); - return false; - } - - // Give ample time to check that the file was created correctly; - // we actually expect ls to return pretty-much-instantly. - auto r = Calamares::System::instance()->targetEnvCommand( - { "ls", "-la", "/" }, QString(), QString(), std::chrono::seconds( 5 ) ); - cDebug() << "In target system after creating LUKS file" << r.getOutput(); - return true; -} - -static bool -setupLuks( const LuksDevice& d, const QString& luks2Hash ) -{ - // Get luksDump for this device - auto luks_dump = Calamares::System::instance()->targetEnvCommand( - { QStringLiteral( "cryptsetup" ), QStringLiteral( "luksDump" ), d.device }, - QString(), - QString(), - std::chrono::seconds( 5 ) ); - if ( luks_dump.getExitCode() != 0 ) - { - cWarning() << "Could not get LUKS information on " << d.device << ':' << luks_dump.getOutput() << "(exit code" - << luks_dump.getExitCode() << ')'; - return false; - } - - // Check LUKS version - int luks_version = 0; - QRegularExpression version_re( QStringLiteral( R"(version:\s*([0-9]))" ), - QRegularExpression::CaseInsensitiveOption ); - QRegularExpressionMatch match = version_re.match( luks_dump.getOutput() ); - if ( !match.hasMatch() ) - { - cWarning() << "Could not get LUKS version on device: " << d.device; - return false; - } - bool ok; - luks_version = match.captured( 1 ).toInt( &ok ); - if ( !ok ) - { - cWarning() << "Could not get LUKS version on device: " << d.device; - return false; - } - cDebug() << "LUKS" << luks_version << " found on device: " << d.device; - - // Check the number of slots used for LUKS1 devices - if ( luks_version == 1 ) - { - QRegularExpression slots_re( QStringLiteral( R"(\d+:\s*enabled)" ), QRegularExpression::CaseInsensitiveOption ); - if ( luks_dump.getOutput().count( slots_re ) == 8 ) - { - cWarning() << "No key slots left on LUKS1 device: " << d.device; - return false; - } - } - - // Add the key to the keyfile - QStringList args = { QStringLiteral( "cryptsetup" ), QStringLiteral( "luksAddKey" ), d.device, keyfile }; - if ( luks_version == 2 && luks2Hash != QString() ) - { - args.insert( 2, "--pbkdf" ); - args.insert( 3, luks2Hash ); - } - auto r - = Calamares::System::instance()->targetEnvCommand( args, QString(), d.passphrase, std::chrono::seconds( 60 ) ); - if ( r.getExitCode() != 0 ) - { - cWarning() << "Could not configure LUKS keyfile on" << d.device << ':' << r.getOutput() << "(exit code" - << r.getExitCode() << ')'; - return false; - } - return true; -} - -static QVariantList -partitionsFromGlobalStorage() -{ - Calamares::GlobalStorage* globalStorage = Calamares::JobQueue::instance()->globalStorage(); - return globalStorage->value( QStringLiteral( "partitions" ) ).toList(); -} - -/// Checks if the partition (represented by @p map) mounts to the given @p path -STATICTEST bool -hasMountPoint( const QVariantMap& map, const QString& path ) -{ - const auto v = map.value( QStringLiteral( "mountPoint" ) ); - return v.isValid() && QDir::cleanPath( v.toString() ) == path; -} - -STATICTEST bool -isEncrypted( const QVariantMap& map ) -{ - return map.contains( QStringLiteral( "luksMapperName" ) ); -} - -/// Checks for any partition satisfying @p pred -STATICTEST bool -anyPartition( bool ( *pred )( const QVariantMap& ) ) -{ - const auto partitions = partitionsFromGlobalStorage(); - return std::find_if( partitions.cbegin(), - partitions.cend(), - [ &pred ]( const QVariant& partitionVariant ) { return pred( partitionVariant.toMap() ); } ) - != partitions.cend(); -} - -STATICTEST bool -hasUnencryptedSeparateBoot() -{ - return anyPartition( - []( const QVariantMap& partition ) - { return hasMountPoint( partition, QStringLiteral( "/boot" ) ) && !isEncrypted( partition ); } ); -} - -Calamares::JobResult -LuksBootKeyFileJob::exec() -{ - const auto* gs = Calamares::JobQueue::instance()->globalStorage(); - if ( !gs ) - { - return Calamares::JobResult::internalError( - "LuksBootKeyFile", "No GlobalStorage defined.", Calamares::JobResult::InvalidConfiguration ); - } - if ( !gs->contains( "partitions" ) ) - { - cError() << "No GS[partitions] key."; - return Calamares::JobResult::internalError( - "LuksBootKeyFile", tr( "No partitions are defined." ), Calamares::JobResult::InvalidConfiguration ); - } - - LuksDeviceList s( gs->value( "partitions" ) ); - if ( !s.valid ) - { - cError() << "GS[partitions] is invalid"; - return Calamares::JobResult::internalError( - "LuksBootKeyFile", tr( "No partitions are defined." ), Calamares::JobResult::InvalidConfiguration ); - } - - cDebug() << "There are" << s.devices.count() << "LUKS partitions"; - if ( s.devices.count() < 1 ) - { - cDebug() << Logger::SubEntry << "Nothing to do for LUKS."; - return Calamares::JobResult::ok(); - } - - auto it = std::partition( s.devices.begin(), s.devices.end(), []( const LuksDevice& d ) { return d.isRoot; } ); - for ( const auto& d : s.devices ) - { - cDebug() << Logger::SubEntry << ( d.isRoot ? "root" : "dev." ) << d.device << "passphrase?" - << !d.passphrase.isEmpty(); - } - - if ( it == s.devices.begin() ) - { - // User has configured non-root partition for encryption - cDebug() << Logger::SubEntry << "No root partition, skipping keyfile creation."; - return Calamares::JobResult::ok(); - } - - if ( hasUnencryptedSeparateBoot() ) - { - // /boot partition is not encrypted, keyfile must not be used. - cDebug() << Logger::SubEntry << "/boot partition is not encrypted, skipping keyfile creation."; - return Calamares::JobResult::ok(); - } - - if ( s.devices.first().passphrase.isEmpty() ) - { - cDebug() << Logger::SubEntry << "No root passphrase."; - return Calamares::JobResult::error( - tr( "Encrypted rootfs setup error" ), - tr( "Root partition %1 is LUKS but no passphrase has been set." ).arg( s.devices.first().device ) ); - } - - if ( !generateTargetKeyfile() ) - { - return Calamares::JobResult::error( - tr( "Encrypted rootfs setup error" ), - tr( "Could not create LUKS key file for root partition %1." ).arg( s.devices.first().device ) ); - } - - for ( const auto& d : s.devices ) - { - // Skip setupLuks for root partition if system has an unencrypted /boot - if ( d.isRoot && hasUnencryptedSeparateBoot() ) - { - continue; - } - - if ( !setupLuks( d, m_luks2Hash ) ) - { - // Could not configure the LUKS partition - // This should not stop the installation: do not return Calamares::JobResult::error. - cError() << "Encrypted rootfs setup error: could not configure LUKS key file on partition " << d.device; - } - } - - return Calamares::JobResult::ok(); -} - -void -LuksBootKeyFileJob::setConfigurationMap( const QVariantMap& configurationMap ) -{ - // Map the value from the config file to accepted values; - // this is an immediately-invoked lambda which is passed the - // return value of getString(). - m_luks2Hash = []( const QString& value ) - { - if ( value == QStringLiteral( "default" ) ) - { - return QString(); // Empty is used internally for "default from cryptsetup" - } - return value.toLower(); - }( Calamares::getString( configurationMap, QStringLiteral( "luks2Hash" ), QString() ) ); -} - -CALAMARES_PLUGIN_FACTORY_DEFINITION( LuksBootKeyFileJobFactory, registerPlugin< LuksBootKeyFileJob >(); ) diff --git a/src/modules/luksbootkeyfile/LuksBootKeyFileJob.h b/src/modules/luksbootkeyfile/LuksBootKeyFileJob.h deleted file mode 100644 index 05288a152e..0000000000 --- a/src/modules/luksbootkeyfile/LuksBootKeyFileJob.h +++ /dev/null @@ -1,42 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#ifndef LUKSBOOTKEYFILEJOB_H -#define LUKSBOOTKEYFILEJOB_H - -#include "CppJob.h" -#include "DllMacro.h" -#include "utils/PluginFactory.h" - -#include -#include - -/** @brief Creates the LUKS boot key file and adds it to the cryptsetup. - * - * This job has no configuration, because it takes everything - * from the global storage settings set by others. - */ -class PLUGINDLLEXPORT LuksBootKeyFileJob : public Calamares::CppJob -{ - Q_OBJECT -public: - explicit LuksBootKeyFileJob( QObject* parent = nullptr ); - ~LuksBootKeyFileJob() override; - - QString prettyName() const override; - - Calamares::JobResult exec() override; - - void setConfigurationMap( const QVariantMap& configurationMap ) override; - -private: - QString m_luks2Hash; -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( LuksBootKeyFileJobFactory ) - -#endif // LUKSBOOTKEYFILEJOB_H diff --git a/src/modules/luksbootkeyfile/Tests.cpp b/src/modules/luksbootkeyfile/Tests.cpp deleted file mode 100644 index 07eacd8a9e..0000000000 --- a/src/modules/luksbootkeyfile/Tests.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2022 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "utils/Logger.h" - -#include - -#undef STATICTEST -#define STATICTEST extern - -// Implementation details -STATICTEST bool hasMountPoint( const QVariantMap& map, const QString& path ); - -STATICTEST bool isEncrypted( const QVariantMap& map ); - -STATICTEST bool anyPartition( bool ( *pred )( const QVariantMap& ) ); - -STATICTEST bool hasUnencryptedSeparateBoot(); - -STATICTEST bool hasEncryptedRoot(); - -class LuksBootKeyFileTests : public QObject -{ - Q_OBJECT -public: - LuksBootKeyFileTests() {} - ~LuksBootKeyFileTests() override {} - -private Q_SLOTS: - void initTestCase(); - - void testMountPoint(); - void testIsEncrypted(); - void testAnyPartition(); -}; - -void -LuksBootKeyFileTests::initTestCase() -{ - Logger::setupLogLevel( Logger::LOGDEBUG ); - cDebug() << "LuksBootKeyFile test started."; - - if ( !Calamares::JobQueue::instance() ) - { - (void)new Calamares::JobQueue(); - } -} - -void -LuksBootKeyFileTests::testMountPoint() -{ - QVariantMap m; // As if this is a partition data - const QString key = QStringLiteral( "mountPoint" ); - const QString boot = QStringLiteral( "/boot" ); - const QString root = QStringLiteral( "/" ); - - QVERIFY( !hasMountPoint( m, QString() ) ); - QVERIFY( !hasMountPoint( m, boot ) ); - - m.insert( key, boot ); - QVERIFY( hasMountPoint( m, boot ) ); - QVERIFY( !hasMountPoint( m, QString() ) ); - QVERIFY( !hasMountPoint( m, root ) ); - - m.insert( key, root ); - QVERIFY( !hasMountPoint( m, boot ) ); - QVERIFY( !hasMountPoint( m, QString() ) ); - QVERIFY( hasMountPoint( m, root ) ); - - m.remove( key ); - QVERIFY( !hasMountPoint( m, root ) ); -} - -void -LuksBootKeyFileTests::testIsEncrypted() -{ - QVariantMap m; // As if this is a partition data - const QString key = QStringLiteral( "luksMapperName" ); - const QString name = QStringLiteral( "any-name" ); - - QVERIFY( !isEncrypted( m ) ); - - // Even an empty string is considered encrypted - m.insert( key, QString() ); - QVERIFY( isEncrypted( m ) ); - - m.insert( key, name ); - QVERIFY( isEncrypted( m ) ); - - m.insert( key, QString() ); - QVERIFY( isEncrypted( m ) ); - - m.remove( key ); - QVERIFY( !isEncrypted( m ) ); -} - - -void -LuksBootKeyFileTests::testAnyPartition() -{ - // This is kind of annoying: we need to build up - // partition data in GS because the functions we're testing - // go straight to GS. - auto* gs = Calamares::JobQueue::instanceGlobalStorage(); - QVERIFY( gs ); - - const QString partitionsKey = QStringLiteral( "partitions" ); - const QString mountPointKey = QStringLiteral( "mountPoint" ); - const QString boot = QStringLiteral( "/boot" ); - const QString root = QStringLiteral( "/" ); - - QVariantList partitions; - QVariantMap p; - QVERIFY( !gs->contains( partitionsKey ) ); - - // Empty list! - QVERIFY( !anyPartition( []( const QVariantMap& ) { return true; } ) ); - - gs->insert( partitionsKey, partitions ); - QVERIFY( !anyPartition( []( const QVariantMap& ) { return true; } ) ); // Still an empty list - - partitions.append( p ); - QCOMPARE( partitions.count(), 1 ); - gs->insert( partitionsKey, partitions ); - QVERIFY( anyPartition( []( const QVariantMap& ) { return true; } ) ); // Now a one-element list - QVERIFY( !anyPartition( []( const QVariantMap& ) { return false; } ) ); // Now a one-element list - - p.insert( mountPointKey, boot ); - QVERIFY( hasMountPoint( p, boot ) ); - partitions.append( p ); - QCOMPARE( partitions.count(), 2 ); - - // Note that GS is not updated yet, so we expect this to fail - QEXPECT_FAIL( "", "GS not updated", Continue ); - QVERIFY( anyPartition( - []( const QVariantMap& partdata ) - { - cDebug() << partdata; - return hasMountPoint( partdata, QStringLiteral( "/boot" ) ); - } ) ); - - gs->insert( partitionsKey, partitions ); // Update GS - QVERIFY( anyPartition( - []( const QVariantMap& partdata ) - { - cDebug() << partdata; - return hasMountPoint( partdata, QStringLiteral( "/boot" ) ); - } ) ); - QVERIFY( !anyPartition( []( const QVariantMap& partdata ) - { return hasMountPoint( partdata, QStringLiteral( "/" ) ); } ) ); - QVERIFY( !anyPartition( []( const QVariantMap& partdata ) { return hasMountPoint( partdata, QString() ); } ) ); - - QVERIFY( hasUnencryptedSeparateBoot() ); -} - -QTEST_GUILESS_MAIN( LuksBootKeyFileTests ) - -#include "utils/moc-warnings.h" - -#include "Tests.moc" diff --git a/src/modules/luksbootkeyfile/luksbootkeyfile.conf b/src/modules/luksbootkeyfile/luksbootkeyfile.conf deleted file mode 100644 index 477d0e30ed..0000000000 --- a/src/modules/luksbootkeyfile/luksbootkeyfile.conf +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Luksbootkeyfile configuration. A key file is created for the -# LUKS encrypted devices. ---- -# Set Password-Based Key Derivation Function (PBKDF) algorithm -# for LUKS keyslot. -# -# There are three usable specific values: pbkdf2, argon2i or argon2id. -# There is one value equivalent to not setting it: default -# -# When not set (or explicitly set to "default"), the cryptsetup default is used -luks2Hash: default diff --git a/src/modules/luksbootkeyfile/luksbootkeyfile.schema.yaml b/src/modules/luksbootkeyfile/luksbootkeyfile.schema.yaml deleted file mode 100644 index 71d26eac36..0000000000 --- a/src/modules/luksbootkeyfile/luksbootkeyfile.schema.yaml +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-FileCopyrightText: 2023 Arjen Balfoort -# SPDX-License-Identifier: GPL-3.0-or-later ---- -$schema: https://json-schema.org/schema# -$id: https://calamares.io/schemas/luksbootkeyfile -additionalProperties: false -type: object -properties: - luks2Hash: { type: string, enum: [ pbkdf2, argon2i, argon2id, default ] } diff --git a/src/modules/luksopenswaphookcfg/CMakeLists.txt b/src/modules/luksopenswaphookcfg/CMakeLists.txt deleted file mode 100644 index f186fbdc68..0000000000 --- a/src/modules/luksopenswaphookcfg/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2021 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# - -# Because LUKS Open Swap Hook (Job) is such a mouthful, we'll -# use LOSH all over the place as a shorthand. -calamares_add_plugin(luksopenswaphookcfg - TYPE job - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - LOSHJob.cpp - SHARED_LIB -) - -calamares_add_test(luksopenswaphooktest SOURCES LOSHJob.cpp Tests.cpp) diff --git a/src/modules/luksopenswaphookcfg/LOSHInfo.h b/src/modules/luksopenswaphookcfg/LOSHInfo.h deleted file mode 100644 index 1a87f4e612..0000000000 --- a/src/modules/luksopenswaphookcfg/LOSHInfo.h +++ /dev/null @@ -1,66 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2021 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ -#ifndef LUKSOPENSWAPHOOKCFG_LOSHINFO_H -#define LUKSOPENSWAPHOOKCFG_LOSHINFO_H - -#include - -/** @brief Information needed to create a suitable config file - * - * The LUKS swap configuration has a handful of keys that need to - * be written to the config file. This struct holds those keys - * and can find the key values from Global Storage (where the - * *partition* module sets them). - */ -struct LOSHInfo -{ - // Member names copied from Python code - QString swap_outer_uuid; - QString swap_mapper_name; - QString mountable_keyfile_device; - QString swap_device_path; - QString keyfile_device_mount_options; - - bool isValid() const { return !swap_device_path.isEmpty(); } - - /** @brief Helper method for doing key-value replacements - * - * Given a named @p key (e.g. "duck", or "swap_device"), returns the - * value set for that key. Invalid keys (e.g. "duck") return an empty string. - */ - QString replacementFor( const QString& key ) const - { - if ( key == QStringLiteral( "swap_device" ) ) - { - return swap_device_path; - } - if ( key == QStringLiteral( "crypt_swap_name" ) ) - { - return swap_mapper_name; - } - if ( key == QStringLiteral( "keyfile_device" ) ) - { - return mountable_keyfile_device; - } - if ( key == QStringLiteral( "keyfile_filename" ) ) - { - return QStringLiteral( "crypto_keyfile.bin" ); - } - if ( key == QStringLiteral( "keyfile_device_mount_options" ) ) - { - return keyfile_device_mount_options; - } - return QString(); - } - - /** @brief Creates a struct from information already set in GS - * - */ - static LOSHInfo fromGlobalStorage(); -}; - -#endif diff --git a/src/modules/luksopenswaphookcfg/LOSHJob.cpp b/src/modules/luksopenswaphookcfg/LOSHJob.cpp deleted file mode 100644 index 5913262e4b..0000000000 --- a/src/modules/luksopenswaphookcfg/LOSHJob.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2021 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ -#include "LOSHJob.h" - -#include "LOSHInfo.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "utils/Logger.h" -#include "utils/Permissions.h" -#include "utils/PluginFactory.h" -#include "utils/String.h" -#include "utils/System.h" -#include "utils/Variant.h" - -#include -#include -#include -#include - -LOSHJob::LOSHJob( QObject* parent ) - : Calamares::CppJob( parent ) -{ -} - -LOSHJob::~LOSHJob() {} - -QString -LOSHJob::prettyName() const -{ - return tr( "Configuring encrypted swap." ); -} - -STATICTEST QString -get_assignment_part( const QString& line ) -{ - static QRegularExpression re( "^[# \\t]*([A-Za-z_]+)[ \\t]*=" ); - auto m = re.match( line ); - if ( m.hasMatch() ) - { - return m.captured( 1 ); - } - return QString(); -} - -/** Writes the config file at @p path - * - * NOTE: @p path is relative to the target system, not an absolute path. - */ -STATICTEST void -write_openswap_conf( const QString& path, QStringList& contents, const LOSHInfo& info ) -{ - if ( info.isValid() ) - { - for ( auto& line : contents ) - { - const QString key = get_assignment_part( line ); - QString replacement = info.replacementFor( key ); - if ( !replacement.isEmpty() ) - { - line.clear(); - line.append( QStringLiteral( "%1=%2" ).arg( key, replacement ) ); - } - } - cDebug() << "Writing" << contents.length() << "line configuration to" << path; - // \n between each two lines, and a \n at the end - Calamares::System::instance()->createTargetFile( - path, contents.join( '\n' ).append( '\n' ).toUtf8(), Calamares::System::WriteMode::Overwrite ); - } - else - { - cDebug() << "Will not write an invalid configuration to" << path; - } -} - -Calamares::JobResult -LOSHJob::exec() -{ - const auto* sys = Calamares::System::instance(); - if ( !sys ) - { - return Calamares::JobResult::internalError( - "LuksOpenSwapHook", tr( "No target system available." ), Calamares::JobResult::InvalidConfiguration ); - } - - Calamares::GlobalStorage* gs - = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; - if ( !gs || gs->value( "rootMountPoint" ).toString().isEmpty() ) - { - return Calamares::JobResult::internalError( - "LuksOpenSwapHook", tr( "No rootMountPoint is set." ), Calamares::JobResult::InvalidConfiguration ); - } - if ( m_configFilePath.isEmpty() ) - { - return Calamares::JobResult::internalError( - "LuksOpenSwapHook", tr( "No configFilePath is set." ), Calamares::JobResult::InvalidConfiguration ); - } - - QStringList contents = sys->readTargetFile( m_configFilePath ); - if ( contents.isEmpty() ) - { - contents << QStringLiteral( "# swap_device=" ) << QStringLiteral( "# crypt_swap_name=" ) - << QStringLiteral( "# keyfile_device=" ) << QStringLiteral( "# keyfile_filename=" ) - << QStringLiteral( "# keyfile_device_mount_options" ); - } - - write_openswap_conf( m_configFilePath, contents, LOSHInfo::fromGlobalStorage() ); - return Calamares::JobResult::ok(); -} - -void -LOSHJob::setConfigurationMap( const QVariantMap& configurationMap ) -{ - m_configFilePath = Calamares::getString( - configurationMap, QStringLiteral( "configFilePath" ), QStringLiteral( "/etc/openswap.conf" ) ); -} - -STATICTEST void -globalStoragePartitionInfo( Calamares::GlobalStorage* gs, LOSHInfo& info ) -{ - if ( !gs ) - { - return; - } - QVariantList l = gs->value( "partitions" ).toList(); - if ( l.isEmpty() ) - { - return; - } - - for ( const auto& pv : l ) - { - const QVariantMap partition = pv.toMap(); - if ( !partition.isEmpty() ) - { - QString mountPoint = partition.value( "mountPoint" ).toString(); - QString fileSystem = partition.value( "fs" ).toString(); - QString luksMapperName = partition.value( "luksMapperName" ).toString(); - // if partition["fs"] == "linuxswap" and "luksMapperName" in partition: - if ( fileSystem == QStringLiteral( "linuxswap" ) && !luksMapperName.isEmpty() ) - { - info.swap_outer_uuid = partition.value( "luksUuid" ).toString(); - info.swap_mapper_name = luksMapperName; - } - else if ( mountPoint == QStringLiteral( "/" ) && !luksMapperName.isEmpty() ) - { - - info.mountable_keyfile_device = QStringLiteral( "/dev/mapper/" ) + luksMapperName; - } - } - } - - if ( !info.mountable_keyfile_device.isEmpty() && !info.swap_outer_uuid.isEmpty() ) - { - info.swap_device_path = QStringLiteral( "/dev/disk/by-uuid/" ) + info.swap_outer_uuid; - } - - QString btrfsRootSubvolume = gs->value( "btrfsRootSubvolume" ).toString(); - if ( !btrfsRootSubvolume.isEmpty() ) - { - Calamares::String::removeLeading( btrfsRootSubvolume, '/' ); - info.keyfile_device_mount_options = QStringLiteral( "--options=subvol=" ) + btrfsRootSubvolume; - } -} - -LOSHInfo -LOSHInfo::fromGlobalStorage() -{ - LOSHInfo i {}; - globalStoragePartitionInfo( - Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr, i ); - return i; -} - -CALAMARES_PLUGIN_FACTORY_DEFINITION( LOSHJobFactory, registerPlugin< LOSHJob >(); ) diff --git a/src/modules/luksopenswaphookcfg/LOSHJob.h b/src/modules/luksopenswaphookcfg/LOSHJob.h deleted file mode 100644 index 4a435a9357..0000000000 --- a/src/modules/luksopenswaphookcfg/LOSHJob.h +++ /dev/null @@ -1,37 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2021 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ -#ifndef LUKSOPENSWAPHOOKCFG_LOSHJOB_H -#define LUKSOPENSWAPHOOKCFG_LOSHJOB_H - -#include "CppJob.h" -#include "DllMacro.h" -#include "utils/PluginFactory.h" - -#include -#include - -class PLUGINDLLEXPORT LOSHJob : public Calamares::CppJob -{ - Q_OBJECT - -public: - explicit LOSHJob( QObject* parent = nullptr ); - ~LOSHJob() override; - - QString prettyName() const override; - - Calamares::JobResult exec() override; - - void setConfigurationMap( const QVariantMap& configurationMap ) override; - -private: - QString m_configFilePath; -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( LOSHJobFactory ) - -#endif diff --git a/src/modules/luksopenswaphookcfg/Tests.cpp b/src/modules/luksopenswaphookcfg/Tests.cpp deleted file mode 100644 index 094b113ed0..0000000000 --- a/src/modules/luksopenswaphookcfg/Tests.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2021 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#include "LOSHInfo.h" -#include "LOSHJob.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "utils/Logger.h" -#include "utils/System.h" - -#include - -// LOSH = LUKS Open Swap Hook (Job) - -// Implementation details -extern QString get_assignment_part( const QString& line ); -extern void write_openswap_conf( const QString& path, QStringList& contents, const LOSHInfo& info ); - -class LOSHTests : public QObject -{ - Q_OBJECT -public: - LOSHTests(); - ~LOSHTests() override {} - -private Q_SLOTS: - void initTestCase(); - - void testAssignmentExtraction_data(); - void testAssignmentExtraction(); - - void testLOSHInfo(); - void testConfigWriting(); - void testJob(); -}; - -LOSHTests::LOSHTests() {} - -void -LOSHTests::initTestCase() -{ - Logger::setupLogLevel( Logger::LOGDEBUG ); - cDebug() << "LOSH test started."; -} - -void -LOSHTests::testAssignmentExtraction_data() -{ - QTest::addColumn< QString >( "line" ); - QTest::addColumn< QString >( "match" ); - - QTest::newRow( "empty" ) << QString() << QString(); - QTest::newRow( "comment-only1" ) << QStringLiteral( "# " ) << QString(); - QTest::newRow( "comment-only2" ) << QStringLiteral( "###" ) << QString(); - QTest::newRow( "comment-only3" ) << QStringLiteral( "# # #" ) << QString(); - - QTest::newRow( "comment-text" ) << QStringLiteral( "# NOTE:" ) << QString(); - QTest::newRow( "comment-story" ) << QStringLiteral( "# This is a shell comment" ) << QString(); - // We look for assignments, but only for single-words - QTest::newRow( "comment-space-eq" ) << QStringLiteral( "# Check that a = b" ) << QString(); - - QTest::newRow( "assignment1" ) << QStringLiteral( "a=1" ) << QStringLiteral( "a" ); - QTest::newRow( "assignment2" ) << QStringLiteral( "a = 1" ) << QStringLiteral( "a" ); - QTest::newRow( "assignment3" ) << QStringLiteral( "# a=1" ) << QStringLiteral( "a" ); - QTest::newRow( "assignment4" ) << QStringLiteral( "cows = 12" ) << QStringLiteral( "cows" ); - QTest::newRow( "assignment5" ) << QStringLiteral( "# # cows=1" ) << QStringLiteral( "cows" ); - QTest::newRow( "assignment6" ) << QStringLiteral( "# moose='cool' # not cows" ) << QStringLiteral( "moose" ); - QTest::newRow( "assignment7" ) << QStringLiteral( " moose=cows=42" ) << QStringLiteral( "moose" ); - QTest::newRow( "assignment8" ) << QStringLiteral( "#swap_device=/dev/something" ) - << QStringLiteral( "swap_device" ); - QTest::newRow( "assignment9" ) << QStringLiteral( "# swap_device=/dev/something" ) - << QStringLiteral( "swap_device" ); - QTest::newRow( "assignment10" ) << QStringLiteral( "swap_device=/dev/something" ) - << QStringLiteral( "swap_device" ); -} - -void -LOSHTests::testAssignmentExtraction() -{ - QFETCH( QString, line ); - QFETCH( QString, match ); - - QCOMPARE( get_assignment_part( line ), match ); -} - -static Calamares::System* -file_setup( const QTemporaryDir& tempRoot ) -{ - Calamares::System* ss = Calamares::System::instance(); - if ( !ss ) - { - ss = new Calamares::System( true ); - } - - Calamares::GlobalStorage* gs - = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; - if ( !gs ) - { - cDebug() << "Creating new JobQueue"; - (void)new Calamares::JobQueue(); - gs = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; - } - if ( gs ) - { - // Working with a rootMountPoint set - gs->insert( "rootMountPoint", tempRoot.path() ); - } - return ss; -} - -static void -make_valid_loshinfo( LOSHInfo& i ) -{ - i.swap_outer_uuid = QStringLiteral( "UUID-0000" ); - i.swap_mapper_name = QStringLiteral( "/dev/mapper/0000" ); - i.swap_device_path = QStringLiteral( "/dev/sda0" ); - i.mountable_keyfile_device = QStringLiteral( "/dev/ada0p0s0" ); -} - -void -LOSHTests::testLOSHInfo() -{ - LOSHInfo i {}; - QVERIFY( !i.isValid() ); - - make_valid_loshinfo( i ); - QVERIFY( i.isValid() ); - QCOMPARE( i.replacementFor( QStringLiteral( "swap_device" ) ), QStringLiteral( "/dev/sda0" ) ); - QCOMPARE( i.replacementFor( QStringLiteral( "duck" ) ), QString() ); -} - -void -LOSHTests::testConfigWriting() -{ - QTemporaryDir tempRoot( QDir::tempPath() + QStringLiteral( "/test-job-XXXXXX" ) ); - QVERIFY( tempRoot.isValid() ); - auto* ss = file_setup( tempRoot ); - QVERIFY( ss ); - QVERIFY( Calamares::JobQueue::instance()->globalStorage() ); - QVERIFY( QFile::exists( tempRoot.path() ) ); - QVERIFY( QFileInfo( tempRoot.path() ).isDir() ); - - const QString targetFilePath = QStringLiteral( "losh.conf" ); - const QString filePath = tempRoot.filePath( targetFilePath ); - QStringList contents { QStringLiteral( "# Calamares demo" ), - QStringLiteral( "# swap_device=a thing" ), - QStringLiteral( "# duck duck swap_device=another" ) }; - - // When the information is invalid, file contents are unchanged, - // and no file is written either. - LOSHInfo i {}; - QVERIFY( !i.isValid() ); - QVERIFY( !QFile::exists( filePath ) ); - write_openswap_conf( targetFilePath, contents, i ); // Invalid i - QVERIFY( !QFile::exists( filePath ) ); - QCOMPARE( contents.length(), 3 ); - QCOMPARE( contents.at( 1 ).left( 4 ), QStringLiteral( "# s" ) ); - - // Can we write there at all? - QFile derp( filePath ); - QVERIFY( derp.open( QIODevice::WriteOnly ) ); - QVERIFY( derp.write( "xx", 2 ) ); - derp.close(); - QVERIFY( QFile::exists( filePath ) ); - QVERIFY( QFile::remove( filePath ) ); - - // Once the information is valid, though, the file is written - make_valid_loshinfo( i ); - QVERIFY( i.isValid() ); - QVERIFY( !QFile::exists( filePath ) ); - write_openswap_conf( targetFilePath, contents, i ); // Now it is valid - QVERIFY( QFile::exists( filePath ) ); - QCOMPARE( contents.length(), 3 ); - QCOMPARE( i.swap_device_path, QStringLiteral( "/dev/sda0" ) ); // expected key value - QCOMPARE( contents.at( 1 ), QStringLiteral( "swap_device=/dev/sda0" ) ); // expected line - - // readLine() returns with newlines-added - QFile f( filePath ); - QVERIFY( f.open( QIODevice::ReadOnly ) ); - QCOMPARE( f.readLine(), QStringLiteral( "# Calamares demo\n" ) ); - QCOMPARE( f.readLine(), QStringLiteral( "swap_device=/dev/sda0\n" ) ); - QCOMPARE( f.readLine(), QStringLiteral( "# duck duck swap_device=another\n" ) ); - QCOMPARE( f.readLine(), QString() ); - QVERIFY( f.atEnd() ); - - // Note how the contents is updated on every write_openswap_conf() - i.swap_device_path = QStringLiteral( "/dev/zram/0.zram" ); - write_openswap_conf( targetFilePath, contents, i ); // Still valid - QCOMPARE( contents.length(), 3 ); - QCOMPARE( i.swap_device_path, QStringLiteral( "/dev/zram/0.zram" ) ); // expected key value - QCOMPARE( contents.at( 1 ), QStringLiteral( "swap_device=/dev/zram/0.zram" ) ); // expected line -} - -void -LOSHTests::testJob() -{ - QTemporaryDir tempRoot( QDir::tempPath() + QStringLiteral( "/test-job-XXXXXX" ) ); - QVERIFY( tempRoot.isValid() ); - auto* ss = file_setup( tempRoot ); - QVERIFY( ss ); - Calamares::GlobalStorage* gs - = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; - QVERIFY( gs ); - - { - QDir d( tempRoot.path() ); - d.mkdir( "etc" ); - } - - QVERIFY( !LOSHInfo::fromGlobalStorage().isValid() ); - QVariantList outerPartition; - QVariantMap innerPartition; - innerPartition.insert( "mountPoint", "/" ); - innerPartition.insert( "fs", "ext4" ); - innerPartition.insert( "luksMapperName", "root" ); - innerPartition.insert( "luksUUID", "0000" ); - outerPartition.append( innerPartition ); - innerPartition.remove( "mountPoint" ); - innerPartition.insert( "fs", "linuxswap" ); - innerPartition.insert( "luksMapperName", "swap" ); - innerPartition.insert( "luksUuid", "0001" ); - outerPartition.append( innerPartition ); - gs->insert( "partitions", outerPartition ); - QVERIFY( LOSHInfo::fromGlobalStorage().isValid() ); - - LOSHJob j; - j.setConfigurationMap( QVariantMap() ); - auto jobresult = j.exec(); - QVERIFY( jobresult ); - - { - QFile f( tempRoot.filePath( "etc/openswap.conf" ) ); - QVERIFY( f.exists() ); - QVERIFY( f.open( QIODevice::ReadOnly ) ); - cDebug() << f.readAll(); - } -} - -QTEST_GUILESS_MAIN( LOSHTests ) - -#include "utils/moc-warnings.h" - -#include "Tests.moc" diff --git a/src/modules/luksopenswaphookcfg/luksopenswaphookcfg.conf b/src/modules/luksopenswaphookcfg/luksopenswaphookcfg.conf deleted file mode 100644 index f1f03bbe49..0000000000 --- a/src/modules/luksopenswaphookcfg/luksopenswaphookcfg.conf +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Writes an openswap configuration with LUKS settings to the given path ---- -# Path of the configuration file to write (in the target system) -configFilePath: /etc/openswap.conf diff --git a/src/modules/luksopenswaphookcfg/luksopenswaphookcfg.schema.yaml b/src/modules/luksopenswaphookcfg/luksopenswaphookcfg.schema.yaml deleted file mode 100644 index ed2ae79719..0000000000 --- a/src/modules/luksopenswaphookcfg/luksopenswaphookcfg.schema.yaml +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later ---- -$schema: https://json-schema.org/schema# -$id: https://calamares.io/schemas/luksopenswaphookcfg -additionalProperties: false -type: object -properties: - configFilePath: { type: string } -required: [ configFilePath ] diff --git a/src/modules/machineid/CMakeLists.txt b/src/modules/machineid/CMakeLists.txt deleted file mode 100644 index 869d113878..0000000000 --- a/src/modules/machineid/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# -calamares_add_plugin(machineid - TYPE job - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - MachineIdJob.cpp - Workers.cpp - SHARED_LIB -) - -calamares_add_test(machineidtest SOURCES Tests.cpp MachineIdJob.cpp Workers.cpp) diff --git a/src/modules/machineid/MachineIdJob.cpp b/src/modules/machineid/MachineIdJob.cpp deleted file mode 100644 index 87ebb0e40f..0000000000 --- a/src/modules/machineid/MachineIdJob.cpp +++ /dev/null @@ -1,188 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Kevin Kofler - * SPDX-FileCopyrightText: 2016 Philip Müller - * SPDX-FileCopyrightText: 2017 Alf Gaida - * SPDX-FileCopyrightText: 2019-2020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "MachineIdJob.h" -#include "Workers.h" - -#include "utils/Logger.h" -#include "utils/NamedEnum.h" -#include "utils/System.h" -#include "utils/Variant.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" - -#include - -const NamedEnumTable< SystemdMachineIdStyle >& -styleNames() -{ - using T = SystemdMachineIdStyle; - // *INDENT-OFF* - // clang-format off - static const NamedEnumTable< SystemdMachineIdStyle > names { - { QStringLiteral( "none" ), T::Blank }, - { QStringLiteral( "blank" ), T::Blank }, - { QStringLiteral( "uuid" ), T::Uuid }, - { QStringLiteral( "systemd" ), T::Uuid }, - { QStringLiteral( "literal-uninitialized" ), T::Uninitialized }, - }; - // clang-format on - // *INDENT-ON* - - return names; -} - -MachineIdJob::MachineIdJob( QObject* parent ) - : Calamares::CppJob( parent ) -{ -} - -MachineIdJob::~MachineIdJob() {} - -QString -MachineIdJob::prettyName() const -{ - return tr( "Generate machine-id." ); -} - -Calamares::JobResult -MachineIdJob::exec() -{ - QString root; - - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - if ( gs && gs->contains( "rootMountPoint" ) ) - { - root = gs->value( "rootMountPoint" ).toString(); - } - else - { - cWarning() << "No *rootMountPoint* defined."; - return Calamares::JobResult::internalError( tr( "Configuration Error" ), - tr( "No root mount point is set for MachineId." ), - Calamares::JobResult::InvalidConfiguration ); - } - - QString target_systemd_machineid_file = QStringLiteral( "/etc/machine-id" ); - QString target_dbus_machineid_file = QStringLiteral( "/var/lib/dbus/machine-id" ); - - const Calamares::System* system = Calamares::System::instance(); - - // Clear existing files - for ( const auto& entropy_file : m_entropy_files ) - { - system->removeTargetFile( entropy_file ); - } - if ( m_dbus ) - { - system->removeTargetFile( target_dbus_machineid_file ); - } - if ( m_systemd ) - { - system->removeTargetFile( target_systemd_machineid_file ); - } - - //Create new files - for ( const auto& entropy_file : m_entropy_files ) - { - if ( !Calamares::System::instance()->createTargetParentDirs( entropy_file ) ) - { - return Calamares::JobResult::error( - QObject::tr( "Directory not found" ), - QObject::tr( "Could not create new random file
%1
." ).arg( entropy_file ) ); - } - auto r = createEntropy( m_entropy_copy ? EntropyGeneration::CopyFromHost - : EntropyGeneration::New, - root, - entropy_file ); - if ( !r ) - { - return r; - } - } - if ( m_systemd ) - { - if ( !system->createTargetParentDirs( target_systemd_machineid_file ) ) - { - cWarning() << "Could not create systemd data-directory."; - } - auto r = createSystemdMachineId( m_systemd_style, root, target_systemd_machineid_file ); - if ( !r ) - { - return r; - } - } - if ( m_dbus ) - { - if ( !system->createTargetParentDirs( target_dbus_machineid_file ) ) - { - cWarning() << "Could not create DBus data-directory."; - } - if ( m_dbus_symlink && QFile::exists( root + target_systemd_machineid_file ) ) - { - auto r = createDBusLink( root, target_dbus_machineid_file, target_systemd_machineid_file ); - if ( !r ) - { - return r; - } - } - else - { - auto r = createDBusMachineId( root, target_dbus_machineid_file ); - if ( !r ) - { - return r; - } - } - } - - return Calamares::JobResult::ok(); -} - -void -MachineIdJob::setConfigurationMap( const QVariantMap& map ) -{ - m_systemd = Calamares::getBool( map, "systemd", false ); - - const auto style = Calamares::getString( map, "systemd-style", QString() ); - if ( !style.isEmpty() ) - { - m_systemd_style = styleNames().find( style, SystemdMachineIdStyle::Uuid ); - } - - m_dbus = Calamares::getBool( map, "dbus", false ); - if ( map.contains( "dbus-symlink" ) ) - { - m_dbus_symlink = Calamares::getBool( map, "dbus-symlink", false ); - } - else if ( map.contains( "symlink" ) ) - { - m_dbus_symlink = Calamares::getBool( map, "symlink", false ); - cWarning() << "MachineId: configuration setting *symlink* is deprecated, use *dbus-symlink*."; - } - // else it's still false from the constructor - - // ignore it, though, if dbus is false - m_dbus_symlink = m_dbus && m_dbus_symlink; - - m_entropy_copy = Calamares::getBool( map, "entropy-copy", false ); - m_entropy_files = Calamares::getStringList( map, "entropy-files" ); - if ( Calamares::getBool( map, "entropy", false ) ) - { - cWarning() << " configuration setting *entropy* is deprecated, use *entropy-files* instead."; - m_entropy_files.append( QStringLiteral( "/var/lib/urandom/random-seed" ) ); - } - m_entropy_files.removeDuplicates(); -} - -CALAMARES_PLUGIN_FACTORY_DEFINITION( MachineIdJobFactory, registerPlugin< MachineIdJob >(); ) diff --git a/src/modules/machineid/MachineIdJob.h b/src/modules/machineid/MachineIdJob.h deleted file mode 100644 index 1029182289..0000000000 --- a/src/modules/machineid/MachineIdJob.h +++ /dev/null @@ -1,62 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef MACHINEIDJOB_H -#define MACHINEIDJOB_H - -#include "Workers.h" - -#include "CppJob.h" -#include "DllMacro.h" -#include "utils/PluginFactory.h" - -#include -#include -#include - -/** @brief Write 'random' data: machine id, entropy, UUIDs - * - */ -class PLUGINDLLEXPORT MachineIdJob : public Calamares::CppJob -{ - Q_OBJECT - -public: - explicit MachineIdJob( QObject* parent = nullptr ); - ~MachineIdJob() override; - - QString prettyName() const override; - - Calamares::JobResult exec() override; - - void setConfigurationMap( const QVariantMap& configurationMap ) override; - - /** @brief The list of filenames to write full of entropy. - * - * The list may be empty (no entropy files are configure) or - * contain one or more filenames to be interpreted within the - * target system. - */ - QStringList entropyFileNames() const { return m_entropy_files; } - -private: - bool m_systemd = false; ///< write systemd's files - - SystemdMachineIdStyle m_systemd_style = SystemdMachineIdStyle::Uuid; - - bool m_dbus = false; ///< write dbus files - bool m_dbus_symlink = false; ///< .. or just symlink to systemd - - bool m_entropy_copy = false; ///< copy from host system - QStringList m_entropy_files; ///< names of files to write -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( MachineIdJobFactory ) - -#endif // MACHINEIDJOB_H diff --git a/src/modules/machineid/Tests.cpp b/src/modules/machineid/Tests.cpp deleted file mode 100644 index 915812814a..0000000000 --- a/src/modules/machineid/Tests.cpp +++ /dev/null @@ -1,264 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "MachineIdJob.h" -#include "Workers.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "utils/Logger.h" -#include "utils/System.h" - -#include -#include -#include - -#include - -// Internals of Workers.cpp -extern int getUrandomPoolSize(); - -class MachineIdTests : public QObject -{ - Q_OBJECT -public: - MachineIdTests() {} - ~MachineIdTests() override {} - -private Q_SLOTS: - void initTestCase(); - void testConfigEntropyFiles(); - - void testCopyFile(); - - void testPoolSize(); - - void testJob(); -}; - -void -MachineIdTests::initTestCase() -{ - Logger::setupLogLevel( Logger::LOGDEBUG ); -} - -void -MachineIdTests::testConfigEntropyFiles() -{ - static QString urandom_entropy( "/var/lib/urandom/random-seed" ); - // No config at all - { - QVariantMap m; - MachineIdJob j; - j.setConfigurationMap( m ); - QCOMPARE( j.entropyFileNames(), QStringList() ); - } - // No entropy, deprecated setting - { - QVariantMap m; - MachineIdJob j; - m.insert( "entropy", false ); - j.setConfigurationMap( m ); - QCOMPARE( j.entropyFileNames(), QStringList() ); - } - // Entropy, deprecated setting - { - QVariantMap m; - MachineIdJob j; - m.insert( "entropy", true ); - j.setConfigurationMap( m ); - QCOMPARE( j.entropyFileNames(), QStringList { urandom_entropy } ); - } - // Duplicate entry, with deprecated setting - { - QVariantMap m; - MachineIdJob j; - m.insert( "entropy", true ); - m.insert( "entropy-files", QStringList { urandom_entropy } ); - j.setConfigurationMap( m ); - QCOMPARE( j.entropyFileNames(), QStringList { urandom_entropy } ); - - m.clear(); - j.setConfigurationMap( m ); - QCOMPARE( j.entropyFileNames(), QStringList() ); - - // This would be weird - m.insert( "entropy", false ); - m.insert( "entropy-files", QStringList { urandom_entropy } ); - j.setConfigurationMap( m ); - QCOMPARE( j.entropyFileNames(), QStringList { urandom_entropy } ); - } - // No deprecated setting - { - QString tmp_entropy( "/tmp/entropy" ); - QVariantMap m; - MachineIdJob j; - m.insert( "entropy-files", QStringList { urandom_entropy, tmp_entropy } ); - j.setConfigurationMap( m ); - QVERIFY( !j.entropyFileNames().isEmpty() ); - QCOMPARE( j.entropyFileNames(), QStringList() << urandom_entropy << tmp_entropy ); - } -} - -void -MachineIdTests::testCopyFile() -{ - QTemporaryDir tempRoot( QDir::tempPath() + QStringLiteral( "/test-root-XXXXXX" ) ); - cDebug() << "Temporary files as" << QDir::tempPath(); - cDebug() << "Temp dir file at " << tempRoot.path(); - QVERIFY( !tempRoot.path().isEmpty() ); - - // This will pretend to be the host system - QTemporaryDir tempISOdir( QDir::tempPath() + QStringLiteral( "/test-live-XXXXXX" ) ); - QVERIFY( QDir( tempRoot.path() ).mkpath( tempRoot.path() + tempISOdir.path() ) ); - - QFile source( tempRoot.filePath( "example" ) ); - QVERIFY( !source.exists() ); - source.open( QIODevice::WriteOnly ); - source.write( "Derp" ); - source.close(); - QCOMPARE( source.size(), 4 ); - QVERIFY( source.exists() ); - - // This should fail since "example" isn't standard in our test directory - auto r0 = copyFile( tempRoot.path(), "example" ); - QVERIFY( !r0 ); - - const QString sampleFile = QStringLiteral( "CMakeCache.txt" ); - if ( QFile::exists( sampleFile ) ) - { - auto r1 = copyFile( tempRoot.path(), sampleFile ); - // Also fail, because it's not an absolute path - QVERIFY( !r1 ); - - QVERIFY( QFile::copy( sampleFile, tempISOdir.path() + '/' + sampleFile ) ); - auto r2 = copyFile( tempRoot.path(), tempISOdir.path() + '/' + sampleFile ); - QVERIFY( r2 ); - } -} - -void -MachineIdTests::testPoolSize() -{ -#ifdef Q_OS_FREEBSD - // It hardly makes sense, but also the /proc entry is missing - QCOMPARE( getUrandomPoolSize(), 512 ); -#else - // Based on a sample size of 1, Netrunner had 4096. - // Physical HW KDE neon had 256, which gets reported as 512, - // but regular CI builds pass, so leave that special case - // #if-fed out. -#if 0 - KOSRelease r; - if ( r.id() == QStringLiteral( "neon" ) ) - { - QCOMPARE( getUrandomPoolSize(), 512 ); - } - else -#endif - { - QVERIFY( getUrandomPoolSize() >= 512 ); - } -#endif -} - -void -MachineIdTests::testJob() -{ - Logger::setupLogLevel( Logger::LOGDEBUG ); - - QTemporaryDir tempRoot( QDir::tempPath() + QStringLiteral( "/test-job-XXXXXX" ) ); - // Only clean up if the tests succeed - tempRoot.setAutoRemove( false ); - cDebug() << "Temporary files as" << QDir::tempPath(); - - // Ensure we have a system object, expect it to be a "bogus" one - Calamares::System* system = Calamares::System::instance(); - QVERIFY( system ); - QVERIFY( system->doChroot() ); - - // Ensure we have a system-wide GlobalStorage with /tmp as root - if ( !Calamares::JobQueue::instance() ) - { - cDebug() << "Creating new JobQueue"; - (void)new Calamares::JobQueue(); - } - Calamares::GlobalStorage* gs - = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; - QVERIFY( gs ); - gs->insert( "rootMountPoint", tempRoot.path() ); - - // Prepare part of the target filesystem - { - QVERIFY( system->createTargetDirs( "/etc" ) ); - auto r = system->createTargetFile( "/etc/machine-id", "Hello" ); - QVERIFY( !r.failed() ); - QVERIFY( r ); - QVERIFY( !r.path().isEmpty() ); - } - - MachineIdJob job( nullptr ); - QVERIFY( !job.prettyName().isEmpty() ); - - QVariantMap config; - config.insert( "dbus", true ); - job.setConfigurationMap( config ); - - { - auto r = job.exec(); - QVERIFY( !r ); // It's supposed to fail, because no dbus-uuidgen executable exists - QVERIFY( QFile::exists( tempRoot.filePath( "var/lib/dbus" ) ) ); // but the target dir exists - } - - config.insert( "dbus-symlink", true ); - job.setConfigurationMap( config ); - { - auto r = job.exec(); - QVERIFY( !r ); // It's supposed to fail, because no dbus-uuidgen executable exists - QVERIFY( QFile::exists( tempRoot.filePath( "var/lib/dbus" ) ) ); // but the target dir exists - - // These all (would) fail, because the chroot isn't viable -#if 0 - QVERIFY( QFile::exists( "/tmp/var/lib/dbus/machine-id" ) ); - - QFileInfo fi( "/tmp/var/lib/dbus/machine-id" ); - QVERIFY( fi.exists() ); - QVERIFY( fi.isSymLink() ); - QCOMPARE( fi.size(), 5 ); -#endif - } - - { - QString tmp_entropy2( "/pineapple.random" ); - QString tmp_entropy( "/tmp/entropy" ); - QVariantMap m; - MachineIdJob j; - m.insert( "entropy-files", QStringList { tmp_entropy2, tmp_entropy } ); - m.insert( "entropy", true ); - j.setConfigurationMap( m ); - QCOMPARE( j.entropyFileNames().count(), 3 ); // Because of the standard entropy entry - - // Check all three are created - auto r = j.exec(); - QVERIFY( r ); - for ( const auto& fileName : j.entropyFileNames() ) - { - cDebug() << "Verifying existence of" << fileName; - QVERIFY( QFile::exists( tempRoot.filePath( fileName.mid( 1 ) ) ) ); - } - } - - tempRoot.setAutoRemove( true ); // All tests succeeded -} - -QTEST_GUILESS_MAIN( MachineIdTests ) - -#include "utils/moc-warnings.h" - -#include "Tests.moc" diff --git a/src/modules/machineid/Workers.cpp b/src/modules/machineid/Workers.cpp deleted file mode 100644 index fe86401d5d..0000000000 --- a/src/modules/machineid/Workers.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Kevin Kofler - * SPDX-FileCopyrightText: 2016 Philip Müller - * SPDX-FileCopyrightText: 2017 Alf Gaida - * SPDX-FileCopyrightText: 2019-2020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "Workers.h" - -#include "MachineIdJob.h" - -#include "utils/Entropy.h" -#include "utils/Logger.h" -#include "utils/System.h" - -#include - -/// @brief Returns a recommended size for the entropy pool (in bytes) -STATICTEST int -getUrandomPoolSize() -{ - QFile f( "/proc/sys/kernel/random/poolsize" ); - constexpr const int minimumPoolSize = 512; - int poolSize = minimumPoolSize; - - if ( f.exists() && f.open( QIODevice::ReadOnly | QIODevice::Text ) ) - { - QByteArray v = f.read( 16 ); - if ( v.length() > 2 ) - { - if ( v.endsWith( '\n' ) ) - { - v.chop( 1 ); - } - bool ok = false; - poolSize = v.toInt( &ok ); - if ( !ok ) - { - poolSize = minimumPoolSize; - } - } - } - return ( poolSize >= minimumPoolSize ) ? poolSize : minimumPoolSize; -} - -static inline bool -isAbsolutePath( const QString& fileName ) -{ - return fileName.startsWith( '/' ); -} - -Calamares::JobResult -copyFile( const QString& rootMountPoint, const QString& fileName ) -{ - if ( !isAbsolutePath( fileName ) ) - { - return Calamares::JobResult::internalError( - MachineIdJob::tr( "File not found" ), - MachineIdJob::tr( "Path
%1
must be an absolute path." ).arg( fileName ), - 0 ); - } - - QFile f( fileName ); - if ( !f.exists() ) - { - return Calamares::JobResult::error( MachineIdJob::tr( "File not found" ), fileName ); - } - if ( !f.copy( rootMountPoint + fileName ) ) - { - return Calamares::JobResult::error( MachineIdJob::tr( "File not found" ), rootMountPoint + fileName ); - } - return Calamares::JobResult::ok(); -} - -Calamares::JobResult -createNewEntropy( int poolSize, const QString& rootMountPoint, const QString& fileName ) -{ - QFile entropyFile( rootMountPoint + fileName ); - if ( entropyFile.exists() ) - { - cWarning() << "Entropy file" << ( rootMountPoint + fileName ) << "already exists."; - return Calamares::JobResult::ok(); // .. anyway - } - if ( !entropyFile.open( QIODevice::WriteOnly ) ) - { - return Calamares::JobResult::error( - MachineIdJob::tr( "File not found" ), - MachineIdJob::tr( "Could not create new random file
%1
." ).arg( fileName ) ); - } - - QByteArray data; - Calamares::EntropySource source = Calamares::getEntropy( poolSize, data ); - entropyFile.write( data ); - entropyFile.close(); - if ( entropyFile.size() < data.length() ) - { - cWarning() << "Entropy file is" << entropyFile.size() << "bytes, random data was" << data.length(); - } - if ( data.length() < poolSize ) - { - cWarning() << "Entropy data is" << data.length() << "bytes, rather than poolSize" << poolSize; - } - if ( source != Calamares::EntropySource::URandom ) - { - cWarning() << "Entropy data for pool is low-quality."; - } - return Calamares::JobResult::ok(); -} - -Calamares::JobResult -createEntropy( const EntropyGeneration kind, const QString& rootMountPoint, const QString& fileName ) -{ - if ( kind == EntropyGeneration::CopyFromHost ) - { - if ( QFile::exists( fileName ) ) - { - auto r = copyFile( rootMountPoint, fileName ); - if ( r ) - { - return r; - } - else - { - cWarning() << "Could not copy" << fileName << "for entropy, generating new."; - } - } - else - { - cWarning() << "Host system entropy does not exist at" << fileName; - } - } - - int poolSize = getUrandomPoolSize(); - return createNewEntropy( poolSize, rootMountPoint, fileName ); -} - -static Calamares::JobResult -runCmd( const QStringList& cmd, bool inTarget ) -{ - auto r = inTarget ? Calamares::System::instance()->targetEnvCommand( cmd ) - : Calamares::System::instance()->runCommand( cmd, std::chrono::seconds( 0 ) ); - if ( r.getExitCode() ) - { - return r.explainProcess( cmd, std::chrono::seconds( 0 ) ); - } - - return Calamares::JobResult::ok(); -} - -Calamares::JobResult -createSystemdMachineId( SystemdMachineIdStyle style, const QString& rootMountPoint, const QString& machineIdFile ) -{ - switch ( style ) - { - case SystemdMachineIdStyle::Uuid: - return runCmd( - QStringList { QStringLiteral( "systemd-machine-id-setup" ), QStringLiteral( "--root=" ) + rootMountPoint }, - false ); - case SystemdMachineIdStyle::Blank: - Calamares::System::instance()->createTargetFile( - machineIdFile, QByteArray(), Calamares::System::WriteMode::Overwrite ); - return Calamares::JobResult::ok(); - case SystemdMachineIdStyle::Uninitialized: - Calamares::System::instance()->createTargetFile( - machineIdFile, "uninitialized\n", Calamares::System::WriteMode::Overwrite ); - return Calamares::JobResult::ok(); - } - return Calamares::JobResult::internalError( QStringLiteral( "Invalid systemd-style" ), - QStringLiteral( "Invalid value %1" ).arg( int( style ) ), - Calamares::JobResult::InvalidConfiguration ); -} - -Calamares::JobResult -createDBusMachineId( const QString& rootMountPoint, const QString& fileName ) -{ - Q_UNUSED( rootMountPoint ) - Q_UNUSED( fileName ) - return runCmd( QStringList { QStringLiteral( "dbus-uuidgen" ), QStringLiteral( "--ensure" ) }, true ); -} - -Calamares::JobResult -createDBusLink( const QString& rootMountPoint, const QString& fileName, const QString& systemdFileName ) -{ - Q_UNUSED( rootMountPoint ) - return runCmd( QStringList { QStringLiteral( "ln" ), QStringLiteral( "-sf" ), systemdFileName, fileName }, true ); -} diff --git a/src/modules/machineid/Workers.h b/src/modules/machineid/Workers.h deleted file mode 100644 index 7665a15717..0000000000 --- a/src/modules/machineid/Workers.h +++ /dev/null @@ -1,70 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef MACHINEID_WORKERS_H -#define MACHINEID_WORKERS_H - -#include "Job.h" - -/** @brief Utility functions - * - * These probably belong in libcalamares, since they're general utilities - * for moving files around in the target system. - */ - -/// @brief Copy @p fileName from host into target system at @p rootMountPoint -Calamares::JobResult copyFile( const QString& rootMountPoint, const QString& fileName ); - - -/** @brief Entropy functions - * - * The target system may want to pre-seed the entropy pool with a suitable - * chunk of entropy data. During installation we have lots of disk access - * so plenty of entropy -- this is used mostly be Debian. - */ - -/// @brief How to generate entropy (bool-like) -enum class EntropyGeneration -{ - New, - CopyFromHost -}; - -/// @brief Creates a new entropy file @p fileName in the target system at @p rootMountPoint -Calamares::JobResult createNewEntropy( int poolSize, const QString& rootMountPoint, const QString& fileName ); - -/// @brief Create an entropy file @p fileName in the target system at @p rootMountPoint -Calamares::JobResult -createEntropy( const EntropyGeneration kind, const QString& rootMountPoint, const QString& fileName ); - - -/** @brief MachineID functions - * - * Creating UUIDs for DBUS and SystemD. - */ - - -/// @brief Create a new DBus UUID file -Calamares::JobResult createDBusMachineId( const QString& rootMountPoint, const QString& fileName ); - -/// @brief Symlink DBus UUID file to the one from systemd (which must exist already) -Calamares::JobResult -createDBusLink( const QString& rootMountPoint, const QString& fileName, const QString& systemdFileName ); - -enum class SystemdMachineIdStyle -{ - Uuid, - Blank, - Uninitialized -}; - -Calamares::JobResult -createSystemdMachineId( SystemdMachineIdStyle style, const QString& rootMountPoint, const QString& fileName ); - -#endif // WORKERS_H diff --git a/src/modules/machineid/machineid.conf b/src/modules/machineid/machineid.conf deleted file mode 100644 index 6a45234cfc..0000000000 --- a/src/modules/machineid/machineid.conf +++ /dev/null @@ -1,56 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Machine-ID and other random data on the target system. -# -# This module can create a number of "random" things on the target: -# - a systemd machine-id file (hence the name of the Calamares module) -# with a random UUID. -# - a dbus machine-id file (or, optionally, link to the one from systemd) -# - an entropy file -# ---- -# Whether to create /etc/machine-id for systemd. -# The default is *false*. -systemd: true -# If systemd is true, the kind of /etc/machine-id to create in the target -# - uuid (default) generates a UUID -# - systemd alias of uuid -# - blank creates the file but leaves it empty at 0 bytes -# - none alias of blank (use `systemd: false` if you don't want one at all) -# - literal-uninitialized creates the file and writes the string "uninitialized\n" -systemd-style: uuid - -# Whether to create /var/lib/dbus/machine-id for D-Bus. -# The default is *false*. -dbus: true -# Whether /var/lib/dbus/machine-id should be a symlink to /etc/machine-id -# (ignored if dbus is false, or if there is no /etc/machine-id to point to). -# The default is *false*. -dbus-symlink: true - -# Copy entropy from the host? If this is set to *true*, then -# any entropy file listed below will be copied from the host -# if it exists. Non-existent files will be generated from -# /dev/urandom . The default is *false*. -entropy-copy: false -# Which files to write (paths in the target). Each of these files is -# either generated from /dev/urandom or copied from the host, depending -# on the setting for *entropy-copy*, above. -entropy-files: - - /var/lib/urandom/random-seed - - /var/lib/systemd/random-seed - -# Whether to create an entropy file /var/lib/urandom/random-seed -# -# DEPRECATED: list the file in entropy-files instead. If this key -# exists and is set to *true*, a warning is printed and Calamares -# behaves as if `/var/lib/urandom/random-seed` is listed in *entropy-files*. -# -# entropy: false - -# Whether to create a symlink for D-Bus -# -# DEPRECATED: set *dbus-symlink* with the same meaning instead. -# -# symlink: false diff --git a/src/modules/machineid/machineid.schema.yaml b/src/modules/machineid/machineid.schema.yaml deleted file mode 100644 index f56b390182..0000000000 --- a/src/modules/machineid/machineid.schema.yaml +++ /dev/null @@ -1,17 +0,0 @@ -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later ---- -$schema: https://json-schema.org/schema# -$id: https://calamares.io/schemas/machineid -additionalProperties: false -type: object -properties: - systemd: { type: boolean, default: false } - "systemd-style": { type: string, enum: [ uuid, blank, literal-uninitialized ] } - dbus: { type: boolean, default: false } - "dbus-symlink": { type: boolean, default: false } - "entropy-copy": { type: boolean, default: false } - "entropy-files": { type: array, items: { type: string } } - # Deprecated properties - symlink: { type: boolean, default: false } - entropy: { type: boolean, default: false } diff --git a/src/modules/mkinitfs/main.py b/src/modules/mkinitfs/main.py deleted file mode 100644 index e3e6e176ab..0000000000 --- a/src/modules/mkinitfs/main.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2014-2015 Philip Müller -# SPDX-FileCopyrightText: 2014 Teo Mrnjavac -# SPDX-FileCopyrightText: 2017 Alf Gaida -# SPDX-FileCopyrightText: 2019 Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later -# -# Calamares is Free Software: see the License-Identifier above. -# - -import libcalamares -from libcalamares.utils import target_env_call - - -import gettext -_ = gettext.translation("calamares-python", - localedir=libcalamares.utils.gettext_path(), - languages=libcalamares.utils.gettext_languages(), - fallback=True).gettext - - -def pretty_name(): - return _("Creating initramfs with mkinitfs.") - - -def run_mkinitfs(): - """ - Creates initramfs, even when initramfs already exists. - - :return: - """ - return target_env_call(['mkinitfs']) - - -def run(): - """ - Starts routine to create initramfs. It passes back the exit code - if it fails. - - :return: - """ - return_code = run_mkinitfs() - - if return_code != 0: - return ( _("Failed to run mkinitfs on the target"), - _("The exit code was {}").format(return_code) ) diff --git a/src/modules/mkinitfs/module.desc b/src/modules/mkinitfs/module.desc deleted file mode 100644 index decc3259f1..0000000000 --- a/src/modules/mkinitfs/module.desc +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -type: "job" -name: "mkinitfs" -interface: "python" -script: "main.py" diff --git a/src/modules/mount/main.py b/src/modules/mount/main.py deleted file mode 100644 index 4202639f33..0000000000 --- a/src/modules/mount/main.py +++ /dev/null @@ -1,379 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2014 Aurélien Gâteau -# SPDX-FileCopyrightText: 2017 Alf Gaida -# SPDX-FileCopyrightText: 2019 Adriaan de Groot -# SPDX-FileCopyrightText: 2019 Kevin Kofler -# SPDX-FileCopyrightText: 2019-2020 Collabora Ltd -# SPDX-License-Identifier: GPL-3.0-or-later -# -# Calamares is Free Software: see the License-Identifier above. -# - -import tempfile -import subprocess -import os -import re - -import libcalamares - -import gettext - -_ = gettext.translation("calamares-python", - localedir=libcalamares.utils.gettext_path(), - languages=libcalamares.utils.gettext_languages(), - fallback=True).gettext - - -class ZfsException(Exception): - """Exception raised when there is a problem with zfs - - Attributes: - message -- explanation of the error - """ - - def __init__(self, message): - self.message = message - - -def pretty_name(): - return _("Mounting partitions.") - - -def disk_name_for_partition(partition): - """ Returns disk name for each found partition. - - :param partition: - :return: - """ - name = os.path.basename(partition["device"]) - - if name.startswith("/dev/mmcblk") or name.startswith("/dev/nvme"): - return re.sub("p[0-9]+$", "", name) - - return re.sub("[0-9]+$", "", name) - - -def is_ssd_disk(partition): - """ Checks if given partition is on an ssd disk. - - :param partition: A dict containing the partition information - :return: True is the partition in on an ssd, False otherwise - """ - - try: - disk_name = disk_name_for_partition(partition) - filename = os.path.join("/sys/block", disk_name, "queue/rotational") - - with open(filename) as sysfile: - return sysfile.read() == "0\n" - except: - return False - - -def get_mount_options(filesystem, mount_options, partition): - """ - Returns the mount options for the partition object and filesystem - - :param filesystem: A string containing the filesystem - :param mount_options: A list of dicts that descripes the mount options for each mountpoint - :param partition: A dict containing information about the partition - :return: A comma seperated string containing the mount options suitable for passing to mount - """ - - # Extra mounts can optionally have "options" set, in this case, they override other all other settings - if "options" in partition: - return ",".join(partition["options"]) - - # If there are no mount options defined then we use the defaults - if mount_options is None: - return "defaults" - - options = next((x for x in mount_options if x["filesystem"] == filesystem), None) - - # If there is no match then check for default options - if options is None: - options = next((x for x in mount_options if x["filesystem"] == "default"), None) - - # If it is still None, then fallback to returning defaults - if options is None: - return "defaults" - - option_items = options.get("options", []).copy() - - # Append the appropriate options for ssd or hdd if set - if is_ssd_disk(partition): - option_items.extend(options.get("ssdOptions", [])) - else: - option_items.extend(options.get("hddOptions", [])) - - if option_items: - return ",".join(option_items) - else: - return "defaults" - - -def get_btrfs_subvolumes(partitions): - """ - Gets the job-configuration for btrfs subvolumes, or if there is - none given, returns a default configuration that matches - the setup (/ and /home) from before configurability was introduced. - - @param partitions - The partitions (from the partitioning module) that will exist on disk. - This is used to filter out subvolumes that don't need to be created - because they get a dedicated partition instead. - """ - btrfs_subvolumes = libcalamares.job.configuration.get("btrfsSubvolumes", None) - # Warn if there's no configuration at all, and empty configurations are - # replaced by a simple root-only layout. - if btrfs_subvolumes is None: - libcalamares.utils.warning("No configuration for btrfsSubvolumes") - if not btrfs_subvolumes: - btrfs_subvolumes = [dict(mountPoint="/", subvolume="/@"), dict(mountPoint="/home", subvolume="/@home")] - - # Filter out the subvolumes which have a dedicated partition - non_root_partition_mounts = [m for m in [p.get("mountPoint", None) for p in partitions] if - m is not None and m != '/'] - btrfs_subvolumes = list(filter(lambda s: s["mountPoint"] not in non_root_partition_mounts, btrfs_subvolumes)) - - # If we have a swap **file**, give it a separate subvolume. - swap_choice = libcalamares.globalstorage.value("partitionChoices") - if swap_choice and swap_choice.get("swap", None) == "file": - swap_subvol = libcalamares.job.configuration.get("btrfsSwapSubvol", "/@swap") - btrfs_subvolumes.append({'mountPoint': '/swap', 'subvolume': swap_subvol}) - libcalamares.globalstorage.insert("btrfsSwapSubvol", swap_subvol) - - return btrfs_subvolumes - - -def mount_zfs(root_mount_point, partition): - """ Mounts a zfs partition at @p root_mount_point - - :param root_mount_point: The absolute path to the root of the install - :param partition: The partition map from global storage for this partition - :return: - """ - # Get the list of zpools from global storage - zfs_pool_list = libcalamares.globalstorage.value("zfsPoolInfo") - if not zfs_pool_list: - libcalamares.utils.warning("Failed to locate zfsPoolInfo data in global storage") - raise ZfsException(_("Internal error mounting zfs datasets")) - - # Find the zpool matching this partition - for zfs_pool in zfs_pool_list: - if zfs_pool["mountpoint"] == partition["mountPoint"]: - pool_name = zfs_pool["poolName"] - ds_name = zfs_pool["dsName"] - - # import the zpool - try: - libcalamares.utils.host_env_process_output(["zpool", "import", "-N", "-R", root_mount_point, pool_name], None) - except subprocess.CalledProcessError: - raise ZfsException(_("Failed to import zpool")) - - # Get the encrpytion information from global storage - zfs_info_list = libcalamares.globalstorage.value("zfsInfo") - encrypt = False - if zfs_info_list: - for zfs_info in zfs_info_list: - if zfs_info["mountpoint"] == partition["mountPoint"] and zfs_info["encrypted"] is True: - encrypt = True - passphrase = zfs_info["passphrase"] - - if encrypt is True: - # The zpool is encrypted, we need to unlock it - try: - libcalamares.utils.host_env_process_output(["zfs", "load-key", pool_name], None, passphrase) - except subprocess.CalledProcessError: - raise ZfsException(_("Failed to unlock zpool")) - - if partition["mountPoint"] == '/': - # Get the zfs dataset list from global storage - zfs = libcalamares.globalstorage.value("zfsDatasets") - - if not zfs: - libcalamares.utils.warning("Failed to locate zfs dataset list") - raise ZfsException(_("Internal error mounting zfs datasets")) - - zfs.sort(key=lambda x: x["mountpoint"]) - for dataset in zfs: - try: - if dataset["canMount"] == "noauto" or dataset["canMount"] is True: - libcalamares.utils.host_env_process_output(["zfs", "mount", - dataset["zpool"] + '/' + dataset["dsName"]]) - except subprocess.CalledProcessError: - raise ZfsException(_("Failed to set zfs mountpoint")) - else: - try: - libcalamares.utils.host_env_process_output(["zfs", "mount", pool_name + '/' + ds_name]) - except subprocess.CalledProcessError: - raise ZfsException(_("Failed to set zfs mountpoint")) - - -def mount_partition(root_mount_point, partition, partitions, mount_options, mount_options_list): - """ - Do a single mount of @p partition inside @p root_mount_point. - - :param root_mount_point: A string containing the root of the install - :param partition: A dict containing information about the partition - :param partitions: The full list of partitions used to filter out btrfs subvols which have duplicate mountpoints - :param mount_options: The mount options from the config file - :param mount_options_list: A list of options for each mountpoint to be placed in global storage for future modules - :return: - """ - # Create mount point with `+` rather than `os.path.join()` because - # `partition["mountPoint"]` starts with a '/'. - raw_mount_point = partition["mountPoint"] - if not raw_mount_point: - return - - mount_point = root_mount_point + raw_mount_point - - # Ensure that the created directory has the correct SELinux context on - # SELinux-enabled systems. - os.makedirs(mount_point, exist_ok=True) - try: - subprocess.call(['chcon', '--reference=' + raw_mount_point, mount_point]) - except FileNotFoundError as e: - libcalamares.utils.warning(str(e)) - except OSError: - libcalamares.utils.error("Cannot run 'chcon' normally.") - raise - - fstype = partition.get("fs", "").lower() - if fstype == "unformatted": - return - - if fstype == "fat16" or fstype == "fat32": - fstype = "vfat" - - device = partition["device"] - - if "luksMapperName" in partition: - device = os.path.join("/dev/mapper", partition["luksMapperName"]) - - if fstype == "zfs": - mount_zfs(root_mount_point, partition) - else: # fstype == "zfs" - mount_options_string = get_mount_options(fstype, mount_options, partition) - if libcalamares.utils.mount(device, - mount_point, - fstype, - mount_options_string) != 0: - libcalamares.utils.warning("Cannot mount {}".format(device)) - mount_options_list.append({"mountpoint": raw_mount_point, "option_string": mount_options_string}) - - # Special handling for btrfs subvolumes. Create the subvolumes listed in mount.conf - if fstype == "btrfs" and partition["mountPoint"] == '/': - # Root has been mounted to btrfs volume -> create subvolumes from configuration - btrfs_subvolumes = get_btrfs_subvolumes(partitions) - - # Store created list in global storage so it can be used in the fstab module - libcalamares.globalstorage.insert("btrfsSubvolumes", btrfs_subvolumes) - # Create the subvolumes that are in the completed list - for s in btrfs_subvolumes: - if not s["subvolume"]: - continue - os.makedirs(root_mount_point + os.path.dirname(s["subvolume"]), exist_ok=True) - subprocess.check_call(["btrfs", "subvolume", "create", - root_mount_point + s["subvolume"]]) - if s["mountPoint"] == "/": - # insert the root subvolume into global storage - libcalamares.globalstorage.insert("btrfsRootSubvolume", s["subvolume"]) - subprocess.check_call(["umount", "-v", root_mount_point]) - - device = partition["device"] - - if "luksMapperName" in partition: - device = os.path.join("/dev/mapper", partition["luksMapperName"]) - - # Mount the subvolumes - swap_subvol = libcalamares.job.configuration.get("btrfsSwapSubvol", "/@swap") - for s in btrfs_subvolumes: - if s['subvolume'] == swap_subvol: - mount_option_no_subvol = get_mount_options("btrfs_swap", mount_options, partition) - else: - mount_option_no_subvol = get_mount_options(fstype, mount_options, partition) - - # Only add subvol= argument if we are not mounting the entire filesystem - if s['subvolume']: - mount_option = f"subvol={s['subvolume']},{mount_option_no_subvol}" - else: - mount_option = mount_option_no_subvol - subvolume_mountpoint = mount_point[:-1] + s['mountPoint'] - mount_options_list.append({"mountpoint": s['mountPoint'], "option_string": mount_option_no_subvol}) - if libcalamares.utils.mount(device, - subvolume_mountpoint, - fstype, - mount_option) != 0: - libcalamares.utils.warning("Cannot mount {}".format(device)) - - -def enable_swap_partition(devices): - try: - for d in devices: - libcalamares.utils.host_env_process_output(["swapon", d]) - except subprocess.CalledProcessError: - libcalamares.utils.warning(f"Failed to enable swap for devices: {devices}") - - -def run(): - """ - Mount all the partitions from GlobalStorage and from the job configuration. - Partitions are mounted in-lexical-order of their mountPoint. - """ - - partitions = libcalamares.globalstorage.value("partitions") - - if not partitions: - libcalamares.utils.warning("partitions is empty, {!s}".format(partitions)) - return (_("Configuration Error"), - _("No partitions are defined for
{!s}
to use.").format("mount")) - - # Find existing swap partitions that are part of the installation and enable them now - swap_devices = [p["device"] for p in partitions if (p["fs"] == "linuxswap" and p.get("claimed", False))] - - enable_swap_partition(swap_devices) - - root_mount_point = tempfile.mkdtemp(prefix="calamares-root-") - - # Get the mountOptions, if this is None, that is OK and will be handled later - mount_options = libcalamares.job.configuration.get("mountOptions") - - # Guard against missing keys (generally a sign that the config file is bad) - extra_mounts = libcalamares.job.configuration.get("extraMounts") or [] - if not extra_mounts: - libcalamares.utils.warning("No extra mounts defined. Does mount.conf exist?") - - if libcalamares.globalstorage.value("firmwareType") != "efi": - for mount in extra_mounts: - if mount.get("efi", None) is True: - extra_mounts.remove(mount) - - # Add extra mounts to the partitions list and sort by mount points. - # This way, we ensure / is mounted before the rest, and every mount point - # is created on the right partition (e.g. if a partition is to be mounted - # under /tmp, we make sure /tmp is mounted before the partition) - mountable_partitions = [p for p in partitions + extra_mounts if "mountPoint" in p and p["mountPoint"]] - mountable_partitions.sort(key=lambda x: x["mountPoint"]) - - # mount_options_list will be inserted into global storage for use in fstab later - mount_options_list = [] - try: - for partition in mountable_partitions: - mount_partition(root_mount_point, partition, partitions, mount_options, mount_options_list) - except ZfsException as ze: - return _("zfs mounting error"), ze.message - - if not mount_options_list: - libcalamares.utils.warning("No mount options defined, {!s} partitions, {!s} mountable".format(len(partitions), len(mountable_partitions))) - - libcalamares.globalstorage.insert("rootMountPoint", root_mount_point) - libcalamares.globalstorage.insert("mountOptionsList", mount_options_list) - - # Remember the extra mounts for the unpackfs module - libcalamares.globalstorage.insert("extraMounts", extra_mounts) diff --git a/src/modules/mount/module.desc b/src/modules/mount/module.desc deleted file mode 100644 index e4486cf12d..0000000000 --- a/src/modules/mount/module.desc +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -type: "job" -name: "mount" -interface: "python" -script: "main.py" diff --git a/src/modules/mount/mount.conf b/src/modules/mount/mount.conf deleted file mode 100644 index da95395699..0000000000 --- a/src/modules/mount/mount.conf +++ /dev/null @@ -1,125 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Mount filesystems in the target (generally, before treating the -# target as a usable chroot / "live" system). Filesystems are -# automatically mounted from the partitioning module. Filesystems -# listed here are **extra**. The filesystems listed in *extraMounts* -# are mounted in all target systems. ---- -# Extra filesystems to mount. The key's value is a list of entries; each -# entry has five keys: -# - device The device node to mount -# - fs (optional) The filesystem type to use -# - mountPoint Where to mount the filesystem -# - options (optional) An array of options to pass to mount -# - efi (optional) A boolean that when true is only mounted for UEFI installs -# -# The device is not mounted if the mountPoint is unset or if the fs is -# set to unformatted. -# -extraMounts: - - device: proc - fs: proc - mountPoint: /proc - - device: sys - fs: sysfs - mountPoint: /sys - - device: /dev - mountPoint: /dev - options: [ bind ] - - device: tmpfs - fs: tmpfs - mountPoint: /run - - device: /run/udev - mountPoint: /run/udev - options: [ bind ] - - device: efivarfs - fs: efivarfs - mountPoint: /sys/firmware/efi/efivars - efi: true - -# Btrfs subvolumes to create if root filesystem is on btrfs volume. -# If *mountpoint* is mounted already to another partition, it is ignored. -# Separate subvolume for swapfile is handled separately and automatically. -# -# It is possible to prevent subvolume creation -- this is likely only relevant -# for the root (/) subvolume -- by giving an empty string as a subvolume -# name. In this case no subvolume will be created. -# -btrfsSubvolumes: - - mountPoint: / - subvolume: /@ - # As an alternative: - # - # subvolume: "" - - mountPoint: /home - subvolume: /@home - - mountPoint: /var/cache - subvolume: /@cache - - mountPoint: /var/log - subvolume: /@log - -# The name of the btrfs subvolume holding the swapfile. This only used when -# a swapfile is selected and the root filesystem is btrfs -# -btrfsSwapSubvol: /@swap - -# The mount options used to mount each filesystem. -# -# filesystem contains the name of the filesystem or on of three special -# values, "default", efi" and "btrfs_swap". The logic is applied in this manner: -# - If the partition is the EFI partition, the "efi" entry will be used -# - If the fs is btrfs and the subvolume is for the swapfile, -# the "btrfs_swap" entry is used -# - If the filesystem is an exact match for filesystem, that entry is used -# - If no match is found in the above, the default entry is used -# - If there is no match and no default entry, "defaults" is used -# - If the mountOptions key is not present, "defaults" is used -# -# Each filesystem entry contains 3 keys, all of which are optional -# options - An array of mount options that is used on all disk types -# ssdOptions - An array of mount options combined with options for ssds -# hddOptions - An array of mount options combined with options for hdds -# If combining these options results in an empty array, "defaults" is used -# -# Example 1 -# In this example, there are specific options for ext4 and btrfs filesystems, -# the EFI partition and the subvolume holding the btrfs swapfile. All other -# filesystems use the default entry. For the btrfs filesystem, there are -# additional options specific to hdds and ssds -# -# mountOptions: -# - filesystem: default -# options: [ defaults ] -# - filesystem: efi -# options: [ defaults, umask=0077 ] -# - filesystem: ext4 -# options: [ defaults ] -# - filesystem: btrfs -# options: [ defaults, compress=zstd:1 ] -# ssdOptions: [ discard=async ] -# hddOptions: [ autodefrag ] -# - filesystem: btrfs_swap -# options: [ defaults, noatime ] -# -# Example 2 -# In this example there is a single default used by all filesystems -# -# mountOptions: -# - filesystem: default -# options: [ defaults ] -# -mountOptions: - - filesystem: default - options: [ defaults ] - - filesystem: efi - options: [ defaults, umask=0077 ] - - filesystem: btrfs - options: [ defaults, compress=zstd:1 ] - - filesystem: btrfs_swap - options: [ defaults, noatime ] - - - - diff --git a/src/modules/mount/mount.schema.yaml b/src/modules/mount/mount.schema.yaml deleted file mode 100644 index a083ed75aa..0000000000 --- a/src/modules/mount/mount.schema.yaml +++ /dev/null @@ -1,43 +0,0 @@ -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later ---- -$schema: https://json-schema.org/schema# -$id: https://calamares.io/schemas/mount -additionalProperties: false -type: object -properties: - extraMounts: - type: array - items: - type: object - additionalProperties: false - properties: - device: { type: string } - fs: { type: string } - mountPoint: { type: string } - options: { type: array, items: { type: string } } - efi: { type: boolean, default: false } - required: [ device, mountPoint ] - btrfsSubvolumes: - type: array - items: - type: object - additionalProperties: false - properties: - mountPoint: { type: string } - subvolume: { type: string } - required: [ subvolume, mountPoint ] - btrfsSwapSubvol: { type: string } - mountOptions: - type: array - items: - type: object - additionalProperties: false - properties: - filesystem: { type: string } - options: { type: array, items: { type: string } } - ssdOptions: { type: array, items: { type: string } } - hddOptions: { type: array, items: { type: string } } - required: [ filesystem ] - - diff --git a/src/modules/mount/tests/1.global b/src/modules/mount/tests/1.global deleted file mode 100644 index ce3e12e4e6..0000000000 --- a/src/modules/mount/tests/1.global +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -partitions: - - device: "/dev/sdb1" - mountPoint: "/" - fs: "ext4" - - device: "/dev/sdb2" - mountPoint: "/home" - fs: "ext4" - - device: "/dev/sdb3" - mountPoint: "" - fs: "linuxswap" diff --git a/src/modules/mount/tests/1.job b/src/modules/mount/tests/1.job deleted file mode 100644 index 5d2365cc61..0000000000 --- a/src/modules/mount/tests/1.job +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -btrfsSwapSubvol: "" - -# No configuration needed because the partitions are -# all filesystems that require no special handling. diff --git a/src/modules/mount/tests/2.global b/src/modules/mount/tests/2.global deleted file mode 100644 index 20aba89ec0..0000000000 --- a/src/modules/mount/tests/2.global +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -partitions: - - device: "/dev/sdb1" - mountPoint: "/" - fs: "btrfs" - -# Expect a complaint and a default btrfs layout diff --git a/src/modules/mount/tests/2.job b/src/modules/mount/tests/2.job deleted file mode 100644 index 54ff59d4a2..0000000000 --- a/src/modules/mount/tests/2.job +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -btrfsSwapSubvol: "" - -# Expect a complaint and a default btrfs layout because the -# partitions use btrfs diff --git a/src/modules/mount/tests/3.global b/src/modules/mount/tests/3.global deleted file mode 100644 index 9dae421dfb..0000000000 --- a/src/modules/mount/tests/3.global +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -partitions: - - device: "/dev/sdb1" - mountPoint: "/" - fs: "btrfs" -partitionChoices: - swap: file diff --git a/src/modules/mount/tests/3.job b/src/modules/mount/tests/3.job deleted file mode 100644 index 5d2365cc61..0000000000 --- a/src/modules/mount/tests/3.job +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -btrfsSwapSubvol: "" - -# No configuration needed because the partitions are -# all filesystems that require no special handling. diff --git a/src/modules/mount/tests/4.global b/src/modules/mount/tests/4.global deleted file mode 100644 index 1856c9dc39..0000000000 --- a/src/modules/mount/tests/4.global +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -partitions: - - device: "/dev/sdb1" - mountPoint: "/" - fs: "btrfs" - - device: "/dev/sdb2" - mountPoint: "/home" - fs: "ext4" -partitionChoices: - swap: file diff --git a/src/modules/mount/tests/4.job b/src/modules/mount/tests/4.job deleted file mode 100644 index dac7582278..0000000000 --- a/src/modules/mount/tests/4.job +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 - -btrfsSubvolumes: - - mountPoint: / - subvolume: /@ - - mountPoint: /home - subvolume: /@home - - mountPoint: /var/cache - subvolume: /@cache - - mountPoint: /var/log - subvolume: /@log diff --git a/src/modules/networkcfg/main.py b/src/modules/networkcfg/main.py deleted file mode 100644 index efe6930eec..0000000000 --- a/src/modules/networkcfg/main.py +++ /dev/null @@ -1,187 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2014 Philip Müller -# SPDX-FileCopyrightText: 2014 Teo Mrnjavac -# SPDX-FileCopyrightText: 2017 Alf Gaida -# SPDX-FileCopyrightText: 2019 Adriaan de Groot -# SPDX-FileCopyrightText: 2021 Anke boersma -# SPDX-License-Identifier: GPL-3.0-or-later -# -# Calamares is Free Software: see the License-Identifier above. -# - -import os -import glob -import shutil - -import libcalamares - -import gettext -_ = gettext.translation("calamares-python", - localedir=libcalamares.utils.gettext_path(), - languages=libcalamares.utils.gettext_languages(), - fallback=True).gettext - - -def pretty_name(): - return _("Saving network configuration.") - - -def get_live_user(): - """ - Gets the "live user" login. This might be "live", or "nitrux", - or something similar: it is the login name used *right now*, - and network configurations saved for that user, should be applied - also for the installed user (which probably has a different name). - """ - # getlogin() is a thin-wrapper, and depends on getlogin(3), - # which reads utmp -- and utmp isn't always set up right. - try: - return os.getlogin() - except OSError: - pass - # getpass will return the **current** user, which is generally root. - # That isn't very useful, because the network settings have been - # made outside of Calamares-running-as-root, as a different user. - # - # If Calamares is running as non-root, though, this is fine. - import getpass - name = getpass.getuser() - if name != "root": - return name - - # TODO: other mechanisms, e.g. guessing that "live" is the name - # TODO: support a what-is-the-live-user setting - return None - - -def replace_username(nm_config_filename, live_user, target_user): - """ - If @p live_user isn't None, then go through the given - file and replace @p live_user by the @p target_user. - - Reads the file, then (re-)writes it with new permissions lives. - """ - # FIXME: Perhaps if live_user is None, we should just replace **all** - # permissions lines? After all, this is supposed to be a live - # system so **whatever** NM networks are configured, should be - # available to the new user. - if live_user is None: - return - if not os.path.exists(nm_config_filename): - return - - with open(nm_config_filename, "r", encoding="UTF-8") as network_conf: - text = network_conf.readlines() - - live_permissions = 'permissions=user:{}:;'.format(live_user) - target_permissions = 'permissions=user:{}:;\n'.format(target_user) - with open(nm_config_filename, "w", encoding="UTF-8") as network_conf: - for line in text: - if live_permissions in line: - line = target_permissions - network_conf.write(line) - - -def path_pair(root_mount_point, relative_path): - """ - Returns /relative_path and the relative path in the target system. - """ - return ("/" + relative_path, os.path.join(root_mount_point, relative_path)) - - -def run(): - """ - Setup network configuration - """ - root_mount_point = libcalamares.globalstorage.value("rootMountPoint") - user = libcalamares.globalstorage.value("username") - live_user = get_live_user() - - if root_mount_point is None: - libcalamares.utils.warning("rootMountPoint is empty, {!s}".format(root_mount_point)) - return (_("Configuration Error"), - _("No root mount point is given for
{!s}
to use." ).format("networkcfg")) - - source_nm, target_nm = path_pair(root_mount_point, "etc/NetworkManager/system-connections/") - - # Sanity checks. We don't want to do anything if a network - # configuration already exists on the target - if os.path.exists(source_nm) and os.path.exists(target_nm): - for network in os.listdir(source_nm): - # Skip LTSP live - if network == "LTSP": - continue - - source_network = os.path.join(source_nm, network) - target_network = os.path.join(target_nm, network) - - if os.path.exists(target_network): - continue - - try: - shutil.copy(source_network, target_network, follow_symlinks=False) - replace_username(target_network, live_user, user) - except FileNotFoundError: - libcalamares.utils.debug( - "Can't copy network configuration files in {}".format(source_network) - ) - except FileExistsError: - pass - - # Also install netplan files - source_netplan = "/etc/netplan" - root_mount_point = libcalamares.globalstorage.value("rootMountPoint") - target_netplan = os.path.join(root_mount_point, source_netplan.lstrip('/')) - - if os.path.exists(source_netplan) and os.path.exists(target_netplan): - # Set NetworkManager to be the default renderer if Netplan is installed - # TODO: We might rather do that inside the network-manager package, see: - # https://bugs.launchpad.net/ubuntu/+source/ubuntu-settings/+bug/2020110 - default_renderer = os.path.join(root_mount_point, "usr/lib/netplan", - "00-network-manager-all.yaml") - if not os.path.exists(default_renderer): - renderer_file = os.path.join(target_netplan, - "01-network-manager-all.yaml") - nm_renderer = """# This file was written by calamares. -# Let NetworkManager manage all devices on this system. -# For more information, see netplan(5). -network: - version: 2 - renderer: NetworkManager -""" - with open(renderer_file, 'w') as f: - f.writelines(nm_renderer) - os.chmod(f.fileno(), 0o600) - - # Copy existing Netplan configuration - for cfg in glob.glob(os.path.join(source_netplan, "*.yaml")): - source_cfg = os.path.join(source_netplan, cfg) - target_cfg = os.path.join(target_netplan, os.path.basename(cfg)) - - if os.path.exists(target_cfg): - continue - - shutil.copy(source_cfg, target_cfg) - - # We need to overwrite the default resolv.conf in the chroot. - source_resolv, target_resolv = path_pair(root_mount_point, "etc/resolv.conf") - if source_resolv != target_resolv and os.path.exists(source_resolv): - try: - os.remove(target_resolv) - except Exception as err: - libcalamares.utils.debug( - "Couldn't remove {}: {}".format(target_resolv, err) - ) - - try: - shutil.copy(source_resolv, target_resolv, follow_symlinks=False) - except Exception as err: - libcalamares.utils.debug( - "Can't copy resolv.conf from {}: {}".format(source_resolv, err) - ) - - return None diff --git a/src/modules/networkcfg/module.desc b/src/modules/networkcfg/module.desc deleted file mode 100644 index cbafe8cd5a..0000000000 --- a/src/modules/networkcfg/module.desc +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -type: "job" -name: "networkcfg" -interface: "python" -script: "main.py" -noconfig: true diff --git a/src/modules/oemid/CMakeLists.txt b/src/modules/oemid/CMakeLists.txt deleted file mode 100644 index d7c35bbbea..0000000000 --- a/src/modules/oemid/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# -calamares_add_plugin(oemid - TYPE viewmodule - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - IDJob.cpp - OEMViewStep.cpp - UI - OEMPage.ui - LINK_PRIVATE_LIBRARIES - ${qtname}::Widgets - SHARED_LIB -) diff --git a/src/modules/oemid/IDJob.cpp b/src/modules/oemid/IDJob.cpp deleted file mode 100644 index e673f7c017..0000000000 --- a/src/modules/oemid/IDJob.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "IDJob.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "Settings.h" - -#include "utils/Logger.h" - -#include -#include - -IDJob::IDJob( const QString& id, QObject* parent ) - : Job( parent ) - , m_batchIdentifier( id ) -{ -} - -QString -IDJob::prettyName() const -{ - return tr( "OEM Batch Identifier" ); -} - -Calamares::JobResult -IDJob::writeId( const QString& dirs, const QString& filename, const QString& contents ) -{ - if ( !QDir().mkpath( dirs ) ) - { - cError() << "Could not create directories" << dirs; - return Calamares::JobResult::error( tr( "OEM Batch Identifier" ), - tr( "Could not create directories %1." ).arg( dirs ) ); - } - - QFile output( QDir( dirs ).filePath( filename ) ); - if ( output.exists() ) - { - cWarning() << "Existing OEM Batch ID" << output.fileName() << "overwritten."; - } - - if ( !output.open( QIODevice::WriteOnly ) ) - { - cError() << "Could not write to" << output.fileName(); - return Calamares::JobResult::error( tr( "OEM Batch Identifier" ), - tr( "Could not open file %1." ).arg( output.fileName() ) ); - } - - if ( output.write( contents.toUtf8() ) < 0 ) - { - cError() << "Write error on" << output.fileName(); - return Calamares::JobResult::error( tr( "OEM Batch Identifier" ), - tr( "Could not write to file %1." ).arg( output.fileName() ) ); - } - output.write( "\n" ); // Ignore error on this one - - return Calamares::JobResult::ok(); -} - -Calamares::JobResult -IDJob::exec() -{ - cDebug() << "Setting OEM Batch ID to" << m_batchIdentifier; - - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - - QString targetDir = QStringLiteral( "/var/log/installer/" ); - QString targetFile = QStringLiteral( "oem-id" ); - QString rootMount = gs->value( "rootMountPoint" ).toString(); - - // Don't bother translating internal errors - if ( rootMount.isEmpty() && Calamares::Settings::instance()->doChroot() ) - { - return Calamares::JobResult::internalError( "OEM Batch Identifier", - "No rootMountPoint is set, but a chroot is required. " - "Is there a module before oemid that sets up the partitions?", - Calamares::JobResult::InvalidConfiguration ); - } - return writeId( Calamares::Settings::instance()->doChroot() ? rootMount + targetDir : targetDir, - targetFile, - m_batchIdentifier ); -} diff --git a/src/modules/oemid/IDJob.h b/src/modules/oemid/IDJob.h deleted file mode 100644 index 17d97b4ee4..0000000000 --- a/src/modules/oemid/IDJob.h +++ /dev/null @@ -1,33 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef IDJOB_H -#define IDJOB_H - -#include "Job.h" - -#include - -class IDJob : public Calamares::Job -{ - Q_OBJECT -public: - explicit IDJob( const QString& id, QObject* parent = nullptr ); - - virtual QString prettyName() const override; - virtual Calamares::JobResult exec() override; - -private: - Calamares::JobResult writeId( const QString&, const QString&, const QString& ); - - QString m_batchIdentifier; -}; - - -#endif diff --git a/src/modules/oemid/OEMPage.ui b/src/modules/oemid/OEMPage.ui deleted file mode 100644 index 2194ac24c4..0000000000 --- a/src/modules/oemid/OEMPage.ui +++ /dev/null @@ -1,100 +0,0 @@ - - - -SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org> -SPDX-License-Identifier: GPL-3.0-or-later - - OEMPage - - - - 0 - 0 - 592 - 300 - - - - - 1 - 0 - - - - OEMPage - - - - - - - - Ba&tch: - - - batchIdentifier - - - - - - - <html><head/><body><p>Enter a batch-identifier here. This will be stored in the target system.</p></body></html> - - - batch-identifier - - - - - - - <html><head/><body><h1>OEM Configuration</h1><p>Calamares will use OEM settings while configuring the target system.</p></body></html> - - - Qt::RichText - - - Qt::AlignCenter - - - true - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 40 - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - diff --git a/src/modules/oemid/OEMViewStep.cpp b/src/modules/oemid/OEMViewStep.cpp deleted file mode 100644 index bf37001642..0000000000 --- a/src/modules/oemid/OEMViewStep.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "OEMViewStep.h" - -#include "ui_OEMPage.h" - -#include "IDJob.h" - -#include "utils/Retranslator.h" -#include "utils/StringExpander.h" -#include "utils/Variant.h" - -#include -#include -#include - -class OEMPage : public QWidget -{ -public: - OEMPage() - : QWidget( nullptr ) - , m_ui( new Ui_OEMPage() ) - { - m_ui->setupUi( this ); - - CALAMARES_RETRANSLATE( m_ui->retranslateUi( this ); ); - } - - ~OEMPage() override; - - Ui_OEMPage* m_ui; -}; - -OEMPage::~OEMPage() {} - -OEMViewStep::OEMViewStep( QObject* parent ) - : Calamares::ViewStep( parent ) - , m_widget( nullptr ) - , m_visited( false ) -{ -} - -OEMViewStep::~OEMViewStep() -{ - if ( m_widget && m_widget->parent() == nullptr ) - { - m_widget->deleteLater(); - } -} - -bool -OEMViewStep::isBackEnabled() const -{ - return true; -} - -bool -OEMViewStep::isNextEnabled() const -{ - return true; -} - -bool -OEMViewStep::isAtBeginning() const -{ - return true; -} - -bool -OEMViewStep::isAtEnd() const -{ - return true; -} - -static QString -substitute( QString s ) -{ - Calamares::String::DictionaryExpander d; - d.insert( QStringLiteral( "DATE" ), QDate::currentDate().toString( Qt::ISODate ) ); - - return d.expand( s ); -} - -void -OEMViewStep::onActivate() -{ - if ( !m_widget ) - { - (void)widget(); - } - if ( !m_visited && m_widget ) - { - m_widget->m_ui->batchIdentifier->setText( m_user_batchIdentifier ); - } - m_visited = true; - - ViewStep::onActivate(); -} - -void -OEMViewStep::onLeave() -{ - m_user_batchIdentifier = m_widget->m_ui->batchIdentifier->text(); - - ViewStep::onLeave(); -} - -QString -OEMViewStep::prettyName() const -{ - return tr( "OEM Configuration" ); -} - -QString -OEMViewStep::prettyStatus() const -{ - return tr( "Set the OEM Batch Identifier to %1." ).arg( m_user_batchIdentifier ); -} - -QWidget* -OEMViewStep::widget() -{ - if ( !m_widget ) - { - m_widget = new OEMPage; - } - return m_widget; -} - -Calamares::JobList -OEMViewStep::jobs() const -{ - return Calamares::JobList() << Calamares::job_ptr( new IDJob( m_user_batchIdentifier ) ); -} - -void -OEMViewStep::setConfigurationMap( const QVariantMap& configurationMap ) -{ - m_conf_batchIdentifier = Calamares::getString( configurationMap, "batch-identifier" ); - m_user_batchIdentifier = substitute( m_conf_batchIdentifier ); -} - -CALAMARES_PLUGIN_FACTORY_DEFINITION( OEMViewStepFactory, registerPlugin< OEMViewStep >(); ) diff --git a/src/modules/oemid/OEMViewStep.h b/src/modules/oemid/OEMViewStep.h deleted file mode 100644 index a0b07c6fd2..0000000000 --- a/src/modules/oemid/OEMViewStep.h +++ /dev/null @@ -1,57 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef OEMVIEWSTEP_H -#define OEMVIEWSTEP_H - -#include "utils/PluginFactory.h" -#include "viewpages/ViewStep.h" - -#include "DllMacro.h" - -#include - -class OEMPage; - -class PLUGINDLLEXPORT OEMViewStep : public Calamares::ViewStep -{ - Q_OBJECT - -public: - explicit OEMViewStep( QObject* parent = nullptr ); - ~OEMViewStep() override; - - QString prettyName() const override; - QString prettyStatus() const override; - - QWidget* widget() override; - - bool isNextEnabled() const override; - bool isBackEnabled() const override; - - bool isAtBeginning() const override; - bool isAtEnd() const override; - - void onActivate() override; - void onLeave() override; - - Calamares::JobList jobs() const override; - - void setConfigurationMap( const QVariantMap& configurationMap ) override; - -private: - QString m_conf_batchIdentifier; - QString m_user_batchIdentifier; - OEMPage* m_widget; - bool m_visited; -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( OEMViewStepFactory ) - -#endif diff --git a/src/modules/oemid/oemid.conf b/src/modules/oemid/oemid.conf deleted file mode 100644 index 4fb14d9317..0000000000 --- a/src/modules/oemid/oemid.conf +++ /dev/null @@ -1,16 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# This is an OEM setup (phase-0) configuration file. ---- -# The batch-identifier is written to /var/log/installer/oem-id. -# This value is put into the text box as the **suggested** -# OEM ID. If ${DATE} is included in the identifier, then -# that is replaced by the current date in yyyy-MM-dd (ISO) format. -# -# It is ok for the identifier to be empty. -# -# The identifier is written to the file as UTF-8 (this will be no -# different from ASCII, for most inputs) and followed by a newline. -# If the identifier is empty, only a newline is written. -batch-identifier: neon-${DATE} diff --git a/src/modules/openrcdmcryptcfg/main.py b/src/modules/openrcdmcryptcfg/main.py deleted file mode 100644 index 06f21da4bf..0000000000 --- a/src/modules/openrcdmcryptcfg/main.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2017 Ghiunhan Mamut -# SPDX-FileCopyrightText: 2019 Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later -# -# Calamares is Free Software: see the License-Identifier above. -# - -import os.path - -import libcalamares - -import gettext -_ = gettext.translation("calamares-python", - localedir=libcalamares.utils.gettext_path(), - languages=libcalamares.utils.gettext_languages(), - fallback=True).gettext - - - -def pretty_name(): - return _("Configuring OpenRC dmcrypt service.") - - -def write_dmcrypt_conf(partitions, root_mount_point, dmcrypt_conf_path): - crypto_target = "" - crypto_source = "" - unencrypted_separate_boot = any(p["mountPoint"] == "/boot" and "luksMapperName" not in p for p in partitions) - - for partition in partitions: - has_luks = "luksMapperName" in partition - skip_partitions = partition["mountPoint"] == "/" or partition["fs"] == "linuxswap" - - if not has_luks and not skip_partitions: - libcalamares.utils.debug( - "Skip writing OpenRC LUKS configuration for partition {!s}".format(partition["mountPoint"])) - if has_luks and not skip_partitions: - crypto_target = partition["luksMapperName"] - crypto_source = "/dev/disk/by-uuid/{!s}".format(partition["uuid"]) - libcalamares.utils.debug( - "Writing OpenRC LUKS configuration for partition {!s}".format(partition["mountPoint"])) - - with open(os.path.join(root_mount_point, dmcrypt_conf_path), 'a+') as dmcrypt_file: - dmcrypt_file.write("\ntarget=" + crypto_target) - dmcrypt_file.write("\nsource=" + crypto_source) - # Don't use keyfile if boot is unencrypted, keys must not be stored on unencrypted partitions - if not unencrypted_separate_boot: - dmcrypt_file.write("\nkey=/crypto_keyfile.bin") - dmcrypt_file.write("\n") - - if has_luks and skip_partitions: - pass # root and swap partitions should be handled by initramfs generators - - return None - -def run(): - """ - This module configures OpenRC dmcrypt service for LUKS encrypted partitions. - :return: - """ - - root_mount_point = libcalamares.globalstorage.value("rootMountPoint") - dmcrypt_conf_path = libcalamares.job.configuration["configFilePath"] - partitions = libcalamares.globalstorage.value("partitions") - - if not partitions: - libcalamares.utils.warning("partitions is empty, {!s}".format(partitions)) - return (_("Configuration Error"), - _("No partitions are defined for
{!s}
to use." ).format("openrcdmcryptcfg")) - if not root_mount_point: - libcalamares.utils.warning("rootMountPoint is empty, {!s}".format(root_mount_point)) - return (_("Configuration Error"), - _("No root mount point is given for
{!s}
to use." ).format("openrcdmcryptcfg")) - - dmcrypt_conf_path = dmcrypt_conf_path.lstrip('/') - - return write_dmcrypt_conf(partitions, root_mount_point, dmcrypt_conf_path) diff --git a/src/modules/openrcdmcryptcfg/module.desc b/src/modules/openrcdmcryptcfg/module.desc deleted file mode 100644 index e63339573a..0000000000 --- a/src/modules/openrcdmcryptcfg/module.desc +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -type: "job" -name: "openrcdmcryptcfg" -interface: "python" -script: "main.py" diff --git a/src/modules/openrcdmcryptcfg/openrcdmcryptcfg.conf b/src/modules/openrcdmcryptcfg/openrcdmcryptcfg.conf deleted file mode 100644 index 911a4eff39..0000000000 --- a/src/modules/openrcdmcryptcfg/openrcdmcryptcfg.conf +++ /dev/null @@ -1,5 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# ---- -configFilePath: /etc/conf.d/dmcrypt diff --git a/src/modules/partition/CMakeLists.txt b/src/modules/partition/CMakeLists.txt deleted file mode 100644 index 5a92e713e9..0000000000 --- a/src/modules/partition/CMakeLists.txt +++ /dev/null @@ -1,122 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# - -# When debugging the partitioning widget, or experimenting, you may -# want to allow unsafe partitioning choices (e.g. doing things to the -# current disk). Set DEBUG_PARTITION_UNSAFE to allow that (it turns off -# some filtering of devices). If you **do** allow unsafe partitioning, -# it will error out at runtime unless you **also** switch **off** -# DEBUG_PARTITION_BAIL_OUT, at which point you are welcome to shoot -# yourself in the foot. -# -# Independently, DEBUG_PARTITION_SKIP will not do the actual partitioning -# through KPMCore, but it **will** save the global storage setup as if -# it has done the partitioning. This is going to confuse subsequent -# modules since the partitions on disk won't match GS, but it can be -# useful for debugging simulated installations that don't need to -# mount the target filesystems. -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) - -# This is very chatty, useful mostly if you don't know what KPMCore offers. -option(DEBUG_FILESYSTEMS "Log all available Filesystems from KPMCore." OFF) - -include_directories(${CMAKE_SOURCE_DIR}) # For 3rdparty - -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() - -include(KPMcoreHelper) - -if(KPMcore_FOUND) - include_directories(${PROJECT_BINARY_DIR}/src/libcalamaresui) - - add_subdirectory(tests) - - calamares_add_plugin(partition - TYPE viewmodule - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - Config.cpp - PartitionViewStep.cpp - - core/BootLoaderModel.cpp - core/ColorUtils.cpp - core/DeviceList.cpp - core/DeviceModel.cpp - core/KPMHelpers.cpp - core/PartitionActions.cpp - core/PartitionCoreModule.cpp - core/PartitionInfo.cpp - core/PartitionLayout.cpp - core/PartitionModel.cpp - core/PartUtils.cpp - gui/BootInfoWidget.cpp - gui/ChoicePage.cpp - gui/CreatePartitionDialog.cpp - gui/CreateVolumeGroupDialog.cpp - gui/DeviceInfoWidget.cpp - gui/EditExistingPartitionDialog.cpp - gui/EncryptWidget.cpp - gui/ListPhysicalVolumeWidgetItem.cpp - gui/PartitionPage.cpp - gui/PartitionBarsView.cpp - gui/PartitionDialogHelpers.cpp - gui/PartitionLabelsView.cpp - gui/PartitionSizeController.cpp - gui/PartitionSplitterWidget.cpp - gui/ResizeVolumeGroupDialog.cpp - gui/ScanningDialog.cpp - gui/VolumeGroupBaseDialog.cpp - jobs/AutoMountManagementJob.cpp - jobs/ChangeFilesystemLabelJob.cpp - jobs/ClearMountsJob.cpp - jobs/ClearTempMountsJob.cpp - jobs/CreatePartitionJob.cpp - jobs/CreatePartitionTableJob.cpp - jobs/CreateVolumeGroupJob.cpp - jobs/DeactivateVolumeGroupJob.cpp - jobs/DeletePartitionJob.cpp - jobs/FillGlobalStorageJob.cpp - jobs/FormatPartitionJob.cpp - jobs/PartitionJob.cpp - jobs/RemoveVolumeGroupJob.cpp - jobs/ResizePartitionJob.cpp - jobs/ResizeVolumeGroupJob.cpp - jobs/SetPartitionFlagsJob.cpp - UI - gui/ChoicePage.ui - gui/CreatePartitionDialog.ui - gui/CreatePartitionTableDialog.ui - gui/EditExistingPartitionDialog.ui - gui/EncryptWidget.ui - gui/PartitionPage.ui - gui/VolumeGroupBaseDialog.ui - LINK_PRIVATE_LIBRARIES - calamares::kpmcore - ${kfname}::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() diff --git a/src/modules/partition/Config.cpp b/src/modules/partition/Config.cpp deleted file mode 100644 index 2010fecdd4..0000000000 --- a/src/modules/partition/Config.cpp +++ /dev/null @@ -1,466 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "Config.h" - -#include "core/PartUtils.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "partition/PartitionSize.h" -#include "utils/Logger.h" -#include "utils/Variant.h" - -Config::Config( QObject* parent ) - : QObject( parent ) -{ -} - -const NamedEnumTable< Config::InstallChoice >& -Config::installChoiceNames() -{ - // *INDENT-OFF* - // clang-format off - static const NamedEnumTable< InstallChoice > names { - { QStringLiteral( "none" ), InstallChoice::NoChoice }, - { QStringLiteral( "nochoice" ), InstallChoice::NoChoice }, - { QStringLiteral( "alongside" ), InstallChoice::Alongside }, - { QStringLiteral( "erase" ), InstallChoice::Erase }, - { QStringLiteral( "replace" ), InstallChoice::Replace }, - { QStringLiteral( "manual" ), InstallChoice::Manual }, - }; - // clang-format on - // *INDENT-ON* - - return names; -} - -const NamedEnumTable< Config::SwapChoice >& -Config::swapChoiceNames() -{ - // *INDENT-OFF* - // clang-format off - static const NamedEnumTable< SwapChoice > names { - { QStringLiteral( "none" ), SwapChoice::NoSwap }, - { QStringLiteral( "small" ), SwapChoice::SmallSwap }, - { QStringLiteral( "suspend" ), SwapChoice::FullSwap }, - { QStringLiteral( "reuse" ), SwapChoice::ReuseSwap }, - { QStringLiteral( "file" ), SwapChoice::SwapFile }, - }; - // clang-format on - // *INDENT-ON* - - return names; -} - -const NamedEnumTable< Config::LuksGeneration >& -Config::luksGenerationNames() -{ - // *INDENT-OFF* - // clang-format off - static const NamedEnumTable< LuksGeneration > names { - { QStringLiteral( "luks1" ), LuksGeneration::Luks1 }, - { QStringLiteral( "luks" ), LuksGeneration::Luks1 }, - { QStringLiteral( "luks2" ), LuksGeneration::Luks2 }, - }; - // clang-format on - // *INDENT-ON* - - return names; -} - -Config::SwapChoice -pickOne( const Config::SwapChoiceSet& s ) -{ - if ( s.count() == 0 ) - { - return Config::SwapChoice::NoSwap; - } - if ( s.count() == 1 ) - { - return *( s.begin() ); - } - if ( s.contains( Config::SwapChoice::NoSwap ) ) - { - return Config::SwapChoice::NoSwap; - } - // Here, count > 1 but NoSwap is not a member. - return *( s.begin() ); -} - -static Config::SwapChoiceSet -getSwapChoices( const QVariantMap& configurationMap ) -{ - // SWAP SETTINGS - // - // This is a bit convoluted because there's legacy settings to handle as well - // as the new-style list of choices, with mapping back-and-forth. - if ( configurationMap.contains( "userSwapChoices" ) - && ( configurationMap.contains( "ensureSuspendToDisk" ) || configurationMap.contains( "neverCreateSwap" ) ) ) - { - cError() << "Partition-module configuration mixes old- and new-style swap settings."; - } - - if ( configurationMap.contains( "ensureSuspendToDisk" ) ) - { - cWarning() << "Partition-module setting *ensureSuspendToDisk* is deprecated."; - } - bool ensureSuspendToDisk = Calamares::getBool( configurationMap, "ensureSuspendToDisk", true ); - - if ( configurationMap.contains( "neverCreateSwap" ) ) - { - cWarning() << "Partition-module setting *neverCreateSwap* is deprecated."; - } - bool neverCreateSwap = Calamares::getBool( configurationMap, "neverCreateSwap", false ); - - Config::SwapChoiceSet choices; // Available swap choices - if ( configurationMap.contains( "userSwapChoices" ) ) - { - // We've already warned about overlapping settings with the - // legacy *ensureSuspendToDisk* and *neverCreateSwap*. - QStringList l = configurationMap[ "userSwapChoices" ].toStringList(); - - for ( const auto& item : l ) - { - bool ok = false; - auto v = Config::swapChoiceNames().find( item, ok ); - if ( ok ) - { - choices.insert( v ); - } - } - - if ( choices.isEmpty() ) - { - cWarning() << "Partition-module configuration for *userSwapChoices* is empty:" << l; - choices.insert( Config::SwapChoice::FullSwap ); - } - - // suspend if it's one of the possible choices; suppress swap only if it's - // the **only** choice available. - ensureSuspendToDisk = choices.contains( Config::SwapChoice::FullSwap ); - neverCreateSwap = ( choices.count() == 1 ) && choices.contains( Config::SwapChoice::NoSwap ); - } - else - { - // Convert the legacy settings into a single setting for now. - if ( neverCreateSwap ) - { - choices.insert( Config::SwapChoice::NoSwap ); - } - else if ( ensureSuspendToDisk ) - { - choices.insert( Config::SwapChoice::FullSwap ); - } - else - { - choices.insert( Config::SwapChoice::SmallSwap ); - } - } - - // Not all are supported right now // FIXME - static const char unsupportedSetting[] = "Partition-module does not support *userSwapChoices* setting"; - -#define COMPLAIN_UNSUPPORTED( x ) \ - if ( choices.contains( x ) ) \ - { \ - bool bogus = false; \ - cWarning() << unsupportedSetting << Config::swapChoiceNames().find( x, bogus ); \ - choices.remove( x ); \ - } - - COMPLAIN_UNSUPPORTED( Config::SwapChoice::ReuseSwap ) -#undef COMPLAIN_UNSUPPORTED - - return choices; -} - -void -updateGlobalStorage( Config::InstallChoice installChoice, Config::SwapChoice swapChoice ) -{ - auto* gs = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; - if ( gs ) - { - QVariantMap m; - m.insert( "install", Config::installChoiceNames().find( installChoice ) ); - m.insert( "swap", Config::swapChoiceNames().find( swapChoice ) ); - gs->insert( "partitionChoices", m ); - } -} - -void -Config::setInstallChoice( int c ) -{ - if ( ( c < InstallChoice::NoChoice ) || ( c > InstallChoice::Manual ) ) - { - cWarning() << "Invalid install choice (int)" << c; - c = InstallChoice::NoChoice; - } - setInstallChoice( static_cast< InstallChoice >( c ) ); -} - -void -Config::setInstallChoice( InstallChoice c ) -{ - if ( c != m_installChoice ) - { - m_installChoice = c; - Q_EMIT installChoiceChanged( c ); - ::updateGlobalStorage( c, m_swapChoice ); - } -} - -void -Config::setSwapChoice( int c ) -{ - if ( ( c < SwapChoice::NoSwap ) || ( c > SwapChoice::SwapFile ) ) - { - cWarning() << "Invalid swap choice (int)" << c; - c = SwapChoice::NoSwap; - } - setSwapChoice( static_cast< SwapChoice >( c ) ); -} - -void -Config::setSwapChoice( Config::SwapChoice c ) -{ - if ( c != m_swapChoice ) - { - m_swapChoice = c; - Q_EMIT swapChoiceChanged( c ); - ::updateGlobalStorage( m_installChoice, c ); - } -} - -void -Config::setEraseFsTypeChoice( const QString& choice ) -{ - const QString canonicalChoice = PartUtils::canonicalFilesystemName( choice, nullptr ); - if ( canonicalChoice != m_eraseFsTypeChoice ) - { - m_eraseFsTypeChoice = canonicalChoice; - Q_EMIT eraseModeFilesystemChanged( canonicalChoice ); - } -} - -void -Config::setReplaceFilesystemChoice( const QString& filesystemName ) -{ - const QString canonicalChoice = PartUtils::canonicalFilesystemName( filesystemName, nullptr ); - if ( canonicalChoice != m_replaceFileSystemChoice ) - { - m_replaceFileSystemChoice = canonicalChoice; - Q_EMIT replaceModeFilesystemChanged( canonicalChoice ); - } -} - -bool -Config::acceptPartitionTableType( PartitionTable::TableType tableType ) const -{ - return m_requiredPartitionTableType.empty() - || m_requiredPartitionTableType.contains( PartitionTable::tableTypeToName( tableType ) ); -} - -static void -fillGSConfigurationEFI( Calamares::GlobalStorage* gs, const QVariantMap& configurationMap ) -{ - // Set up firmwareType global storage entry. This is used, e.g. by the bootloader module. - QString firmwareType( PartUtils::isEfiSystem() ? QStringLiteral( "efi" ) : QStringLiteral( "bios" ) ); - gs->insert( "firmwareType", firmwareType ); - - bool ok = false; - auto efiConfiguration = Calamares::getSubMap( configurationMap, "efi", ok ); - - // Mount Point - { - const auto efiSystemPartition = Calamares::getString( - efiConfiguration, - "mountPoint", - Calamares::getString( configurationMap, "efiSystemPartition", QStringLiteral( "/boot/efi" ) ) ); - // This specific GS key is also used by bootloader and grubcfg modules, - // as well as partition module internalls. - gs->insert( "efiSystemPartition", efiSystemPartition ); - } - - // Sizes - { - const auto efiRecommendedSize = Calamares::getString( - efiConfiguration, "recommendedSize", Calamares::getString( configurationMap, "efiSystemPartitionSize" ) ); - if ( !efiRecommendedSize.isEmpty() ) - { - Calamares::Partition::PartitionSize part_size = Calamares::Partition::PartitionSize( efiRecommendedSize ); - if ( part_size.isValid() ) - { - gs->insert( PartUtils::efiFilesystemRecommendedSizeGSKey(), part_size.toBytes() ); - - // Assign long long int to long unsigned int to prevent compilation warning, - // checks for loss-of-precision in the conversion. - auto byte_part_size = part_size.toBytes(); - if ( byte_part_size != PartUtils::efiFilesystemRecommendedSize() ) - { - cWarning() << "EFI partition size" << efiRecommendedSize << "has been adjusted to" - << PartUtils::efiFilesystemRecommendedSize() << "bytes"; - } - } - else - { - cWarning() << "EFI partition size" << efiRecommendedSize << "is invalid, ignored"; - } - } - - const auto efiMinimumSize = Calamares::getString( efiConfiguration, "minimumSize" ); - if ( !efiMinimumSize.isEmpty() ) - { - Calamares::Partition::PartitionSize part_size = Calamares::Partition::PartitionSize( efiMinimumSize ); - if ( part_size.isValid() ) - { - if ( part_size.toBytes() > PartUtils::efiFilesystemRecommendedSize() ) - { - cWarning() << "EFI minimum size" << efiMinimumSize << "is larger than the recommended size" - << efiRecommendedSize << ", ignored."; - } - else - { - gs->insert( PartUtils::efiFilesystemMinimumSizeGSKey(), part_size.toBytes() ); - } - } - } - } - - // Name (label) of partition - { - const auto efiLabel = Calamares::getString( - efiConfiguration, "label", Calamares::getString( configurationMap, "efiSystemPartitionName" ) ); - - if ( !efiLabel.isEmpty() ) - { - gs->insert( "efiSystemPartitionName", efiLabel ); - } - } -} - -void -Config::fillConfigurationFSTypes( const QVariantMap& configurationMap ) -{ - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - - // The defaultFileSystemType setting needs a bit more processing, - // as we want to cover various cases (such as different cases) - QString fsName = Calamares::getString( configurationMap, "defaultFileSystemType" ); - QString fsRealName; - FileSystem::Type fsType = FileSystem::Type::Unknown; - if ( fsName.isEmpty() ) - { - cWarning() << "Partition-module setting *defaultFileSystemType* is missing, will use ext4"; - fsRealName = PartUtils::canonicalFilesystemName( QStringLiteral( "ext4" ), &fsType ); - } - else - { - fsRealName = PartUtils::canonicalFilesystemName( fsName, &fsType ); - if ( fsType == FileSystem::Type::Unknown ) - { - cWarning() << "Partition-module setting *defaultFileSystemType* is bad (" << fsName - << ") using ext4 instead"; - fsRealName = PartUtils::canonicalFilesystemName( QStringLiteral( "ext4" ), &fsType ); - } - else if ( fsRealName != fsName ) - { - cWarning() << "Partition-module setting *defaultFileSystemType* changed to" << fsRealName; - } - } - Q_ASSERT( fsType != FileSystem::Type::Unknown ); - m_defaultFsType = fsType; - gs->insert( "defaultFileSystemType", fsRealName ); - - // TODO: canonicalize the names? How is translation supposed to work? - m_eraseFsTypes = Calamares::getStringList( configurationMap, "availableFileSystemTypes" ); - if ( !m_eraseFsTypes.contains( fsRealName ) ) - { - if ( !m_eraseFsTypes.isEmpty() ) - { - // Explicitly set, and doesn't include the default - cWarning() << "Partition-module *availableFileSystemTypes* does not contain the default" << fsRealName; - m_eraseFsTypes.prepend( fsRealName ); - } - else - { - // Not explicitly set, so it's empty; don't complain - m_eraseFsTypes = QStringList { fsRealName }; - } - } - - // Set LUKS file system based on luksGeneration provided, defaults to 'luks'. - bool nameFound = false; - Config::LuksGeneration luksGeneration - = luksGenerationNames().find( Calamares::getString( configurationMap, "luksGeneration" ), nameFound ); - if ( !nameFound ) - { - cWarning() << "Partition-module setting *luksGeneration* not found or invalid. Defaulting to luks1."; - luksGeneration = Config::LuksGeneration::Luks1; - } - m_luksFileSystemType = luksGeneration; - gs->insert( "luksFileSystemType", luksGenerationNames().find( luksGeneration ) ); - - Q_ASSERT( !m_eraseFsTypes.isEmpty() ); - Q_ASSERT( m_eraseFsTypes.contains( fsRealName ) ); - m_eraseFsTypeChoice = fsRealName; - m_replaceFileSystemChoice = fsRealName; - Q_EMIT eraseModeFilesystemChanged( m_eraseFsTypeChoice ); - Q_EMIT replaceModeFilesystemChanged( m_replaceFileSystemChoice ); -} - -void -Config::setConfigurationMap( const QVariantMap& configurationMap ) -{ - // Settings that overlap with the Welcome module - m_requiredStorageGiB = Calamares::getDouble( configurationMap, "requiredStorage", -1.0 ); - m_swapChoices = getSwapChoices( configurationMap ); - - bool nameFound = false; // In the name table (ignored, falls back to first entry in table) - m_initialInstallChoice - = installChoiceNames().find( Calamares::getString( configurationMap, "initialPartitioningChoice" ), nameFound ); - setInstallChoice( m_initialInstallChoice ); - - m_initialSwapChoice - = swapChoiceNames().find( Calamares::getString( configurationMap, "initialSwapChoice" ), nameFound ); - if ( !m_swapChoices.contains( m_initialSwapChoice ) ) - { - cWarning() << "Configuration for *initialSwapChoice* is not one of the *userSwapChoices*"; - if ( nameFound ) - { - cWarning() << Logger::SubEntry << "Choice" << swapChoiceNames().find( m_initialSwapChoice ) << "added."; - m_swapChoices.insert( m_initialSwapChoice ); - } - m_initialSwapChoice = pickOne( m_swapChoices ); - } - setSwapChoice( m_initialSwapChoice ); - - m_allowZfsEncryption = Calamares::getBool( configurationMap, "allowZfsEncryption", true ); - - m_allowManualPartitioning = Calamares::getBool( configurationMap, "allowManualPartitioning", true ); - m_showNotEncryptedBootMessage = Calamares::getBool( configurationMap, "showNotEncryptedBootMessage", true ); - m_requiredPartitionTableType = Calamares::getStringList( configurationMap, "requiredPartitionTableType" ); - - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - gs->insert( "armInstall", Calamares::getBool( configurationMap, "armInstall", false ) ); - fillGSConfigurationEFI( gs, configurationMap ); - fillConfigurationFSTypes( configurationMap ); -} - -void -Config::fillGSSecondaryConfiguration() const -{ - // If there's no setting (e.g. from the welcome page) for required storage - // then use ours, if it was set. - auto* gs = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; - if ( m_requiredStorageGiB >= 0.0 && gs && !gs->contains( "requiredStorageGiB" ) ) - { - gs->insert( "requiredStorageGiB", m_requiredStorageGiB ); - } -} diff --git a/src/modules/partition/Config.h b/src/modules/partition/Config.h deleted file mode 100644 index d8d68c6d29..0000000000 --- a/src/modules/partition/Config.h +++ /dev/null @@ -1,214 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef PARTITION_CONFIG_H -#define PARTITION_CONFIG_H - -#include "utils/NamedEnum.h" - -#include -#include - -#include -#include - -class Config : public QObject -{ - Q_OBJECT - ///@brief The installation choice (Erase, Alongside, ...) - Q_PROPERTY( InstallChoice installChoice READ installChoice WRITE setInstallChoice NOTIFY installChoiceChanged ) - - ///@brief The swap choice (None, Small, Hibernate, ...) which only makes sense when Erase is chosen - Q_PROPERTY( SwapChoice swapChoice READ swapChoice WRITE setSwapChoice NOTIFY swapChoiceChanged ) - - ///@brief Name of the FS that will be used when erasing type disk (e.g. "default filesystem") - Q_PROPERTY( - QString eraseModeFilesystem READ eraseFsType WRITE setEraseFsTypeChoice NOTIFY eraseModeFilesystemChanged ) - - Q_PROPERTY( QString replaceModeFilesystem READ replaceModeFilesystem WRITE setReplaceFilesystemChoice NOTIFY - replaceModeFilesystemChanged ) - - Q_PROPERTY( bool allowManualPartitioning READ allowManualPartitioning CONSTANT FINAL ) - - Q_PROPERTY( bool showNotEncryptedBootMessage READ showNotEncryptedBootMessage CONSTANT FINAL ) - -public: - Config( QObject* parent ); - ~Config() override = default; - - enum InstallChoice - { - NoChoice, - Alongside, - Erase, - Replace, - Manual - }; - Q_ENUM( InstallChoice ) - static const NamedEnumTable< InstallChoice >& installChoiceNames(); - - /** @brief Choice of swap (size and type) */ - enum SwapChoice - { - NoSwap, // don't create any swap, don't use any - ReuseSwap, // don't create, but do use existing - SmallSwap, // up to 8GiB of swap - FullSwap, // ensureSuspendToDisk -- at least RAM size - SwapFile // use a file (if supported) - }; - Q_ENUM( SwapChoice ) - static const NamedEnumTable< SwapChoice >& swapChoiceNames(); - using SwapChoiceSet = QSet< SwapChoice >; - - using EraseFsTypesSet = QStringList; - - /** @brief Choice of LUKS disk encryption generation */ - enum class LuksGeneration - { - Luks1, // First generation of LUKS - Luks2, // Second generation of LUKS, default since cryptsetup >= 2.1.0 - }; - Q_ENUM( LuksGeneration ) - static const NamedEnumTable< LuksGeneration >& luksGenerationNames(); - - void setConfigurationMap( const QVariantMap& ); - /** @brief Set GS values where other modules configuration has priority - * - * Some "required" values are duplicated between modules; if some - * othe module hasn't already set the GS value, take a value from - * the partitioning configuration. - * - * Applicable GS keys: - * - requiredStorageGiB - */ - void fillGSSecondaryConfiguration() const; - - /** @brief What kind of installation (partitioning) is requested **initially**? - * - * @return the partitioning choice (may be @c NoChoice) - */ - InstallChoice initialInstallChoice() const { return m_initialInstallChoice; } - - /** @brief What kind of installation (partition) is requested **now**? - * - * This changes depending on what the user selects (unlike the initial choice, - * which is fixed by the configuration). - * - * @return the partitioning choice (may be @c NoChoice) - */ - InstallChoice installChoice() const { return m_installChoice; } - - /** @brief The set of swap choices enabled for this install - * - * Not all swap choices are supported by each distro, so they - * can choose to enable or disable them. This method - * returns a set (hopefully non-empty) of configured swap choices. - */ - SwapChoiceSet swapChoices() const { return m_swapChoices; } - - /** @brief What kind of swap selection is requested **initially**? - * - * @return The swap choice (may be @c NoSwap ) - */ - SwapChoice initialSwapChoice() const { return m_initialSwapChoice; } - - /** @brief What kind of swap selection is requested **now**? - * - * A choice of swap only makes sense when install choice Erase is made. - * - * @return The swap choice (may be @c NoSwap). - */ - SwapChoice swapChoice() const { return m_swapChoice; } - - /** @brief Get the list of configured FS types to use with *erase* mode - * - * This list is not empty. - */ - EraseFsTypesSet eraseFsTypes() const { return m_eraseFsTypes; } - - /** @brief Currently-selected FS type for *erase* mode - */ - QString eraseFsType() const { return m_eraseFsTypeChoice; } - - /// @brief Currently-selected FS type for *replace* mode - QString replaceModeFilesystem() const { return m_replaceFileSystemChoice; } - - /** @brief Configured default FS type (for other modes than erase) - * - * This is not "Unknown" or "Unformatted" - */ - FileSystem::Type defaultFsType() const { return m_defaultFsType; } - - /// @brief Is manual partitioning allowed (not explicitly disabled in the config file)? - bool allowManualPartitioning() const { return m_allowManualPartitioning; } - - /// @brief Show "Boot partition not encrypted" warning (not explicitly disabled in the config file)? - bool showNotEncryptedBootMessage() const { return m_showNotEncryptedBootMessage; } - - /** @brief Will @p tableType be ok? - * - * If no required types are specified, it's ok, otherwise the - * type must be named in the list of required types. - */ - bool acceptPartitionTableType( PartitionTable::TableType tableType ) const; - /// @brief Returns list of acceptable types. May be empty. - QStringList partitionTableTypes() const { return m_requiredPartitionTableType; } - - /** @brief The configured LUKS generation (1 or 2) - */ - LuksGeneration luksFileSystemType() const { return m_luksFileSystemType; } - - /// @brief If zfs encryption should be allowed - bool allowZfsEncryption() const { return m_allowZfsEncryption; } - -public Q_SLOTS: - void setInstallChoice( int ); ///< Translates a button ID or so to InstallChoice - void setInstallChoice( InstallChoice ); - void setSwapChoice( int ); ///< Translates a button ID or so to SwapChoice - void setSwapChoice( SwapChoice ); - void setEraseFsTypeChoice( const QString& filesystemName ); ///< See property eraseModeFilesystem - void setReplaceFilesystemChoice( const QString& filesystemName ); - -Q_SIGNALS: - void installChoiceChanged( InstallChoice ); - void swapChoiceChanged( SwapChoice ); - void eraseModeFilesystemChanged( const QString& ); - void replaceModeFilesystemChanged( const QString& ); - -private: - /** @brief Handle FS-type configuration, for erase and default */ - void fillConfigurationFSTypes( const QVariantMap& configurationMap ); - EraseFsTypesSet m_eraseFsTypes; - QString m_eraseFsTypeChoice; - QString m_replaceFileSystemChoice; - FileSystem::Type m_defaultFsType; - - SwapChoiceSet m_swapChoices; - SwapChoice m_initialSwapChoice = NoSwap; - SwapChoice m_swapChoice = NoSwap; - LuksGeneration m_luksFileSystemType = LuksGeneration::Luks1; - InstallChoice m_initialInstallChoice = NoChoice; - InstallChoice m_installChoice = NoChoice; - qreal m_requiredStorageGiB = 0.0; // May duplicate setting in the welcome module - QStringList m_requiredPartitionTableType; - bool m_allowZfsEncryption = true; - bool m_allowManualPartitioning = true; - bool m_showNotEncryptedBootMessage = true; -}; - -/** @brief Given a set of swap choices, return a sensible value from it. - * - * "Sensible" here means: if there is one value, use it; otherwise, use - * NoSwap if there are no choices, or if NoSwap is one of the choices, in the set. - * If that's not possible, any value from the set. - */ -Config::SwapChoice pickOne( const Config::SwapChoiceSet& s ); - - -#endif diff --git a/src/modules/partition/PartitionViewStep.cpp b/src/modules/partition/PartitionViewStep.cpp deleted file mode 100644 index 8b7225da3a..0000000000 --- a/src/modules/partition/PartitionViewStep.cpp +++ /dev/null @@ -1,763 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2014-2017 Teo Mrnjavac - * SPDX-FileCopyrightText: 2018-2019 2020, Adriaan de Groot - * SPDX-FileCopyrightText: 2019 Collabora Ltd - * SPDX-FileCopyrightText: 2020 Anke Boersma - -#include -#include -#include -#include - -PartitionViewStep::PartitionViewStep( QObject* parent ) - : Calamares::ViewStep( parent ) - , m_config( new Config( this ) ) - , m_core( nullptr ) - , m_widget( new QStackedWidget() ) - , m_choicePage( nullptr ) - , m_manualPartitionPage( nullptr ) -{ - m_widget->setContentsMargins( 0, 0, 0, 0 ); - - m_waitingWidget = new WaitingWidget( QString() ); - m_widget->addWidget( m_waitingWidget ); - CALAMARES_RETRANSLATE( - if ( m_waitingWidget ) { m_waitingWidget->setText( tr( "Gathering system information…", "@status" ) ); } ); - - m_core = new PartitionCoreModule( this ); // Unusable before init is complete! - // We're not done loading, but we need the configuration map first. -} - -void -PartitionViewStep::initPartitionCoreModule() -{ - Q_ASSERT( m_core ); - m_core->init(); -} - -void -PartitionViewStep::continueLoading() -{ - Q_ASSERT( !m_choicePage ); - m_choicePage = new ChoicePage( m_config ); - m_choicePage->init( m_core ); - m_widget->addWidget( m_choicePage ); - - // Instantiate the manual partitioning page as needed. - // - Q_ASSERT( !m_manualPartitionPage ); - // m_manualPartitionPage = new PartitionPage( m_core ); - // m_widget->addWidget( m_manualPartitionPage ); - - m_widget->removeWidget( m_waitingWidget ); - m_waitingWidget->deleteLater(); - m_waitingWidget = nullptr; - - connect( m_core, &PartitionCoreModule::hasRootMountPointChanged, this, &PartitionViewStep::nextPossiblyChanged ); - connect( m_choicePage, &ChoicePage::nextStatusChanged, this, &PartitionViewStep::nextPossiblyChanged ); -} - -PartitionViewStep::~PartitionViewStep() -{ - if ( m_choicePage && m_choicePage->parent() == nullptr ) - { - m_choicePage->deleteLater(); - } - if ( m_manualPartitionPage && m_manualPartitionPage->parent() == nullptr ) - { - m_manualPartitionPage->deleteLater(); - } - delete m_core; -} - -QString -PartitionViewStep::prettyName() const -{ - return tr( "Partitions", "@label" ); -} - -/** @brief Gather the pretty descriptions of all the partitioning jobs - * - * Returns a QStringList of each job's pretty description, including - * empty strings and duplicates. The list is in-order of how the - * jobs will be run. - */ -static QStringList -jobDescriptions( const Calamares::JobList& jobs ) -{ - QStringList jobsLines; - for ( const Calamares::job_ptr& job : qAsConst( jobs ) ) - { - if ( !job->prettyDescription().isEmpty() ) - { - jobsLines.append( job->prettyDescription() ); - } - } - return jobsLines; -} - -/** @brief A top-level description of what @p choice does - * - * Returns a translated string describing what @p choice will do. - * Includes branding information. - */ -static QString -modeDescription( Config::InstallChoice choice ) -{ - const auto* branding = Calamares::Branding::instance(); - - switch ( choice ) - { - case Config::InstallChoice::Alongside: - return QCoreApplication::translate( - "PartitionViewStep", "Install %1 alongside another operating system", "@label" ) - .arg( branding->shortVersionedName() ); - case Config::InstallChoice::Erase: - return QCoreApplication::translate( - "PartitionViewStep", "Erase disk and install %1", "@label" ) - .arg( branding->shortVersionedName() ); - case Config::InstallChoice::Replace: - return QCoreApplication::translate( - "PartitionViewStep", "Replace a partition with %1", "@label" ) - .arg( branding->shortVersionedName() ); - case Config::InstallChoice::NoChoice: - case Config::InstallChoice::Manual: - return QCoreApplication::translate( "PartitionViewStep", "Manual partitioning", "@label" ); - } - return QString(); -} - -/** @brief A top-level description of what @p choice does to disk @p info - * - * Returns a translated string, with branding and device information, describing what - * will be done to device @p info when @p choice is made. The @p listLength - * is used to provide context; when more than one disk is in use, the description - * works differently. - */ -static QString -diskDescription( int listLength, const PartitionCoreModule::SummaryInfo& info, Config::InstallChoice choice ) -{ - const auto* branding = Calamares::Branding::instance(); - - if ( listLength == 1 ) // this is the only disk preview - { - switch ( choice ) - { - case Config::Alongside: - return QCoreApplication::translate( - "PartitionViewStep", - "Install %1 alongside another operating system on disk " - "%2 (%3)", - "@info" ) - .arg( branding->shortVersionedName() ) - .arg( info.deviceNode ) - .arg( info.deviceName ); - case Config::Erase: - return QCoreApplication::translate( "PartitionViewStep", - "Erase disk %2 (%3) and install %1", - "@info" ) - .arg( branding->shortVersionedName() ) - .arg( info.deviceNode ) - .arg( info.deviceName ); - case Config::Replace: - return QCoreApplication::translate( - "PartitionViewStep", - "Replace a partition on disk %2 (%3) with %1", - "@info" ) - .arg( branding->shortVersionedName() ) - .arg( info.deviceNode ) - .arg( info.deviceName ); - case Config::NoChoice: - case Config::Manual: - return QCoreApplication::translate( "PartitionViewStep", - "Manual partitioning on disk %1 (%2)", - "@info" ) - .arg( info.deviceNode ) - .arg( info.deviceName ); - } - return QString(); - } - else // multiple disk previews! - { - return QCoreApplication::translate( "PartitionViewStep", "Disk %1 (%2)", "@info" ) - .arg( info.deviceNode ) - .arg( info.deviceName ); - } -} - -QString -PartitionViewStep::prettyStatus() const -{ - const Config::InstallChoice choice = m_config->installChoice(); - const QList< PartitionCoreModule::SummaryInfo > list = m_core->createSummaryInfo(); - - cDebug() << "Summary for Partition" << list.length() << choice; - auto joinDiskInfo = [ choice = choice ]( QString& s, const PartitionCoreModule::SummaryInfo& i ) - { return s + diskDescription( 1, i, choice ); }; - const QString diskInfoLabel = std::accumulate( list.begin(), list.end(), QString(), joinDiskInfo ); - const QString jobsLabel = jobDescriptions( jobs() ).join( QStringLiteral( "
" ) ); - return diskInfoLabel + "
" + jobsLabel; -} - -QWidget* -PartitionViewStep::createSummaryWidget() const -{ - QWidget* widget = new QWidget; - QVBoxLayout* mainLayout = new QVBoxLayout; - widget->setLayout( mainLayout ); - Calamares::unmarginLayout( mainLayout ); - - Config::InstallChoice choice = m_config->installChoice(); - - QFormLayout* formLayout = new QFormLayout( widget ); - const int MARGIN = Calamares::defaultFontHeight() / 2; - formLayout->setContentsMargins( MARGIN, 0, MARGIN, MARGIN ); - mainLayout->addLayout( formLayout ); - -#if defined( DEBUG_PARTITION_UNSAFE ) || defined( DEBUG_PARTITION_BAIL_OUT ) || defined( DEBUG_PARTITION_SKIP ) - auto specialRow = [ = ]( Calamares::ImageType t, const QString& s ) - { - QLabel* icon = new QLabel; - icon->setPixmap( Calamares::defaultPixmap( t ) ); - formLayout->addRow( icon, new QLabel( s ) ); - }; -#endif -#if defined( DEBUG_PARTITION_UNSAFE ) - specialRow( Calamares::ImageType::StatusWarning, tr( "Unsafe partition actions are enabled." ) ); -#endif -#if defined( DEBUG_PARTITION_BAIL_OUT ) - specialRow( Calamares::ImageType::Information, tr( "Partitioning is configured to always fail." ) ); -#endif -#if defined( DEBUG_PARTITION_SKIP ) - specialRow( Calamares::ImageType::Information, tr( "No partitions will be changed." ) ); -#endif - - const QList< PartitionCoreModule::SummaryInfo > list = m_core->createSummaryInfo(); - if ( list.length() > 1 ) // There are changes on more than one disk - { - //NOTE: all of this should only happen when Manual partitioning is active. - // Any other choice should result in a list.length() == 1. - QLabel* modeLabel = new QLabel; - formLayout->addRow( modeLabel ); - modeLabel->setText( modeDescription( choice ) ); - } - for ( const auto& info : list ) - { - QLabel* diskInfoLabel = new QLabel; - diskInfoLabel->setText( diskDescription( list.length(), info, choice ) ); - formLayout->addRow( diskInfoLabel ); - - PartitionBarsView* preview; - PartitionLabelsView* previewLabels; - QVBoxLayout* field; - - PartitionBarsView::NestedPartitionsMode mode - = Calamares::JobQueue::instance()->globalStorage()->value( "drawNestedPartitions" ).toBool() - ? PartitionBarsView::DrawNestedPartitions - : PartitionBarsView::NoNestedPartitions; - preview = new PartitionBarsView; - preview->setNestedPartitionsMode( mode ); - previewLabels = new PartitionLabelsView; - previewLabels->setExtendedPartitionHidden( mode == PartitionBarsView::NoNestedPartitions ); - preview->setModel( info.partitionModelBefore ); - previewLabels->setModel( info.partitionModelBefore ); - preview->setSelectionMode( QAbstractItemView::NoSelection ); - previewLabels->setSelectionMode( QAbstractItemView::NoSelection ); - info.partitionModelBefore->setParent( widget ); - field = new QVBoxLayout; - Calamares::unmarginLayout( field ); - field->setSpacing( 6 ); - field->addWidget( preview ); - field->addWidget( previewLabels ); - formLayout->addRow( tr( "Current:", "@label" ), field ); - - preview = new PartitionBarsView; - preview->setNestedPartitionsMode( mode ); - previewLabels = new PartitionLabelsView; - previewLabels->setExtendedPartitionHidden( mode == PartitionBarsView::NoNestedPartitions ); - preview->setModel( info.partitionModelAfter ); - previewLabels->setModel( info.partitionModelAfter ); - preview->setSelectionMode( QAbstractItemView::NoSelection ); - previewLabels->setSelectionMode( QAbstractItemView::NoSelection ); - previewLabels->setCustomNewRootLabel( - Calamares::Branding::instance()->string( Calamares::Branding::BootloaderEntryName ) ); - info.partitionModelAfter->setParent( widget ); - field = new QVBoxLayout; - Calamares::unmarginLayout( field ); - field->setSpacing( 6 ); - field->addWidget( preview ); - field->addWidget( previewLabels ); - formLayout->addRow( tr( "After:", "@label" ), field ); - } - const QStringList jobsLines = jobDescriptions( jobs() ); - if ( !jobsLines.isEmpty() ) - { - QLabel* jobsLabel = new QLabel( widget ); - mainLayout->addWidget( jobsLabel ); - jobsLabel->setText( jobsLines.join( "
" ) ); - jobsLabel->setMargin( Calamares::defaultFontHeight() / 2 ); - QPalette pal; - pal.setColor( WindowBackground, pal.window().color().lighter( 108 ) ); - jobsLabel->setAutoFillBackground( true ); - jobsLabel->setPalette( pal ); - } - return widget; -} - -QWidget* -PartitionViewStep::widget() -{ - return m_widget; -} - -void -PartitionViewStep::next() -{ - if ( m_choicePage == m_widget->currentWidget() ) - { - if ( m_config->installChoice() == Config::InstallChoice::Manual ) - { - if ( !m_manualPartitionPage ) - { - m_manualPartitionPage = new PartitionPage( m_core ); - m_widget->addWidget( m_manualPartitionPage ); - } - - m_widget->setCurrentWidget( m_manualPartitionPage ); - m_manualPartitionPage->selectDeviceByIndex( m_choicePage->lastSelectedDeviceIndex() ); - if ( m_core->isDirty() ) - { - m_manualPartitionPage->onRevertClicked(); - } - } - cDebug() << "Choice applied: " << m_config->installChoice(); - } -} - -void -PartitionViewStep::back() -{ - if ( m_widget->currentWidget() != m_choicePage ) - { - m_widget->setCurrentWidget( m_choicePage ); - m_choicePage->setLastSelectedDeviceIndex( m_manualPartitionPage->selectedDeviceIndex() ); - - if ( m_manualPartitionPage ) - { - m_manualPartitionPage->deleteLater(); - m_manualPartitionPage = nullptr; - } - } -} - -bool -PartitionViewStep::isNextEnabled() const -{ - if ( m_choicePage && m_widget->currentWidget() == m_choicePage ) - { - return m_choicePage->isNextEnabled(); - } - - if ( m_manualPartitionPage && m_widget->currentWidget() == m_manualPartitionPage ) - { - return m_core->hasRootMountPoint(); - } - - return false; -} - -void -PartitionViewStep::nextPossiblyChanged( bool ) -{ - Q_EMIT nextStatusChanged( isNextEnabled() ); -} - -bool -PartitionViewStep::isBackEnabled() const -{ - return true; -} - -bool -PartitionViewStep::isAtBeginning() const -{ - if ( m_widget->currentWidget() != m_choicePage ) - { - return false; - } - return true; -} - -bool -PartitionViewStep::isAtEnd() const -{ - if ( m_widget->currentWidget() == m_choicePage ) - { - auto choice = m_config->installChoice(); - if ( Config::InstallChoice::Erase == choice || Config::InstallChoice::Replace == choice - || Config::InstallChoice::Alongside == choice ) - { - return true; - } - return false; - } - return true; -} - -void -PartitionViewStep::onActivate() -{ - m_config->fillGSSecondaryConfiguration(); - - // if we're coming back to PVS from the next VS - if ( m_widget->currentWidget() == m_choicePage && m_config->installChoice() == Config::InstallChoice::Alongside ) - { - m_choicePage->applyActionChoice( Config::InstallChoice::Alongside ); - // m_choicePage->reset(); - } -} - -static bool -shouldWarnForGPTOnBIOS( const PartitionCoreModule* core ) -{ - if ( PartUtils::isEfiSystem() ) - { - return false; - } - - const QString biosFlagName = PartitionTable::flagName( KPM_PARTITION_FLAG( BiosGrub ) ); - - auto [ r, device ] = core->bootLoaderModel()->findBootLoader( core->bootLoaderInstallPath() ); - Q_UNUSED( r ); - if ( device ) - { - auto* table = device->partitionTable(); - cDebug() << "Found device for bootloader" << device->deviceNode(); - if ( table && table->type() == PartitionTable::TableType::gpt ) - { - // So this is a BIOS system, and the bootloader will be installed on a GPT system - for ( const auto& partition : qAsConst( table->children() ) ) - { - using Calamares::Units::operator""_MiB; - if ( ( partition->activeFlags() & KPM_PARTITION_FLAG( BiosGrub ) ) - && ( partition->fileSystem().type() == FileSystem::Unformatted ) - && ( partition->capacity() >= 8_MiB ) ) - { - cDebug() << Logger::SubEntry << "Partition" << partition->devicePath() << partition->partitionPath() - << "is a suitable" << biosFlagName << "partition"; - return false; - } - } - } - cDebug() << Logger::SubEntry << "No suitable partition for" << biosFlagName << "found"; - } - else - { - cDebug() << "Found no device for" << core->bootLoaderInstallPath(); - } - return true; -} - -static bool -shouldWarnForNotEncryptedBoot( const Config* config, const PartitionCoreModule* core ) -{ - if ( config->showNotEncryptedBootMessage() ) - { - Partition* root_p = core->findPartitionByMountPoint( "/" ); - Partition* boot_p = core->findPartitionByMountPoint( "/boot" ); - - if ( root_p and boot_p ) - { - if ( ( root_p->fileSystem().type() == FileSystem::Luks && boot_p->fileSystem().type() != FileSystem::Luks ) - || ( root_p->fileSystem().type() == FileSystem::Luks2 - && boot_p->fileSystem().type() != FileSystem::Luks2 ) ) - { - return true; - } - } - } - return false; -} - -void -PartitionViewStep::onLeave() -{ - if ( m_widget->currentWidget() == m_choicePage ) - { - m_choicePage->onLeave(); - return; - } - - const auto* branding = Calamares::Branding::instance(); - if ( m_widget->currentWidget() == m_manualPartitionPage ) - { - if ( PartUtils::isEfiSystem() ) - { - const QString espMountPoint - = Calamares::JobQueue::instance()->globalStorage()->value( "efiSystemPartition" ).toString(); - Partition* esp = m_core->findPartitionByMountPoint( espMountPoint ); - - QString message; - QString description; - - Logger::Once o; - - const bool okType = esp && PartUtils::isEfiFilesystemSuitableType( esp ); - const bool okRecommendedSize = esp && PartUtils::isEfiFilesystemRecommendedSize( esp ); - const bool okMinimumSize = esp && PartUtils::isEfiFilesystemMinimumSize( esp ); - const bool okFlag = esp && PartUtils::isEfiBootable( esp ); - - const bool espExistsButIsWrong = esp && !( okType && okMinimumSize && okFlag ); - - const QString genericWrongnessMessage = tr( "An EFI system partition is necessary to start %1." - "

" - "To configure an EFI system partition, go back and " - "select or create a suitable filesystem." ) - .arg( branding->shortProductName() ); - const QString genericRecommendationMessage - = tr( "An EFI system partition is necessary to start %1." - "

" - "The EFI system partition does not meet recommendations. It is " - "recommended to go back and " - "select or create a suitable filesystem." ) - .arg( branding->shortProductName() ); - - const QString wrongMountPointMessage - = tr( "The filesystem must be mounted on %1." ).arg( espMountPoint ); - const QString wrongTypeMessage = tr( "The filesystem must have type FAT32." ); - const QString wrongFlagMessage = tr( "The filesystem must have flag %1 set." ) - .arg( PartitionTable::flagName( PartitionTable::Flag::Boot ) ); - - const auto recommendedMiB = Calamares::BytesToMiB( PartUtils::efiFilesystemRecommendedSize() ); - const auto minimumMiB = Calamares::BytesToMiB( PartUtils::efiFilesystemMinimumSize() ); - - // Three flavors of size-is-wrong - const QString requireConfiguredSize - = tr( "The filesystem must be at least %1 MiB in size." ).arg( recommendedMiB ); - const QString requiredMinimumSize - = tr( "The filesystem must be at least %1 MiB in size." ).arg( minimumMiB ); - const QString suggestConfiguredSize - = tr( "The minimum recommended size for the filesystem is %1 MiB." ).arg( recommendedMiB ); - - const QString mayFail = tr( "You can continue without setting up an EFI system " - "partition but your system may fail to start." ); - const QString possibleFail = tr( "You can continue with this EFI system " - "partition configuration but your system may fail to start." ); - - const QString startList = QStringLiteral( "

    " ); - const QString endList = QStringLiteral( "


" ); - - auto listItem = []( QString s ) -> QString - { return s.prepend( QStringLiteral( "
  • " ) ).append( QStringLiteral( "
  • " ) ); }; - - if ( !esp ) - { - cDebug() << o << "No ESP mounted"; - message = tr( "No EFI system partition configured" ); - - description = genericWrongnessMessage + startList + listItem( wrongMountPointMessage ) - + listItem( requireConfiguredSize ) + listItem( wrongTypeMessage ) + listItem( wrongFlagMessage ) - + endList + mayFail; - } - else if ( espExistsButIsWrong ) - { - message = tr( "EFI system partition configured incorrectly" ); - - description = genericWrongnessMessage + startList; - if ( !okMinimumSize ) - { - description.append( listItem( requiredMinimumSize ) ); - } - if ( !okType ) - { - description.append( listItem( wrongTypeMessage ) ); - } - if ( !okFlag ) - { - description.append( listItem( wrongFlagMessage ) ); - } - description.append( endList ); - description.append( mayFail ); - } - else if ( !okRecommendedSize ) - { - message = tr( "EFI system partition recommendation" ); - description = genericRecommendationMessage + suggestConfiguredSize + possibleFail; - } - - if ( !message.isEmpty() ) - { - QMessageBox mb( QMessageBox::Warning, message, description, QMessageBox::Ok, m_manualPartitionPage ); - Calamares::fixButtonLabels( &mb ); - mb.exec(); - } - } - else - { - - cDebug() << "device: BIOS"; - - if ( shouldWarnForGPTOnBIOS( m_core ) ) - { - const QString biosFlagName = PartitionTable::flagName( KPM_PARTITION_FLAG( BiosGrub ) ); - QString message = tr( "Option to use GPT on BIOS" ); - QString description = tr( "A GPT partition table is the best option for all " - "systems. This installer supports such a setup for " - "BIOS systems too." - "

    " - "To configure a GPT partition table on BIOS, " - "(if not done so already) go back " - "and set the partition table to GPT, next create a 8 MB " - "unformatted partition with the " - "%2 flag enabled.

    " - "An unformatted 8 MB partition is necessary " - "to start %1 on a BIOS system with GPT." ) - .arg( branding->shortProductName(), biosFlagName ); - - QMessageBox mb( - QMessageBox::Information, message, description, QMessageBox::Ok, m_manualPartitionPage ); - Calamares::fixButtonLabels( &mb ); - mb.exec(); - } - } - - if ( shouldWarnForNotEncryptedBoot( m_config, m_core ) ) - { - QString message = tr( "Boot partition not encrypted" ); - QString description = tr( "A separate boot partition was set up together with " - "an encrypted root partition, but the boot partition " - "is not encrypted." - "

    " - "There are security concerns with this kind of " - "setup, because important system files are kept " - "on an unencrypted partition.
    " - "You may continue if you wish, but filesystem " - "unlocking will happen later during system startup." - "
    To encrypt the boot partition, go back and " - "recreate it, selecting Encrypt " - "in the partition creation window." ); - - QMessageBox mb( QMessageBox::Warning, message, description, QMessageBox::Ok, m_manualPartitionPage ); - Calamares::fixButtonLabels( &mb ); - mb.exec(); - } - } -} - -void -PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap ) -{ - m_config->setConfigurationMap( configurationMap ); - - // Copy the efiSystemPartition setting to the global storage. It is needed not only in - // the EraseDiskPage, but also in the bootloader configuration modules (grub, bootloader). - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - - // Read and parse key swapPartitionName - if ( configurationMap.contains( "swapPartitionName" ) ) - { - gs->insert( "swapPartitionName", Calamares::getString( configurationMap, "swapPartitionName" ) ); - } - - // OTHER SETTINGS - // - gs->insert( "drawNestedPartitions", Calamares::getBool( configurationMap, "drawNestedPartitions", false ) ); - gs->insert( "alwaysShowPartitionLabels", - Calamares::getBool( configurationMap, "alwaysShowPartitionLabels", true ) ); - gs->insert( "enableLuksAutomatedPartitioning", - Calamares::getBool( configurationMap, "enableLuksAutomatedPartitioning", true ) ); - - QString partitionTableName = Calamares::getString( configurationMap, "defaultPartitionTableType" ); - if ( partitionTableName.isEmpty() ) - { - cWarning() << "Partition-module setting *defaultPartitionTableType* is unset, " - "will use gpt for efi or msdos for bios"; - } - gs->insert( "defaultPartitionTableType", partitionTableName ); - - // Now that we have the config, we load the PartitionCoreModule in the background - // because it could take a while. Then when it's done, we can set up the widgets - // and remove the spinner. - m_future = new QFutureWatcher< void >(); - connect( m_future, - &QFutureWatcher< void >::finished, - this, - [ this ] - { - continueLoading(); - this->m_future->deleteLater(); - this->m_future = nullptr; - } ); - -#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) - QFuture< void > future = QtConcurrent::run( this, &PartitionViewStep::initPartitionCoreModule ); -#else - QFuture< void > future = QtConcurrent::run( &PartitionViewStep::initPartitionCoreModule, this ); -#endif - m_future->setFuture( future ); - - m_core->partitionLayout().init( m_config->defaultFsType(), configurationMap.value( "partitionLayout" ).toList() ); -} - -Calamares::JobList -PartitionViewStep::jobs() const -{ - return m_core->jobs( m_config ); -} - -Calamares::RequirementsList -PartitionViewStep::checkRequirements() -{ - if ( m_future ) - { - m_future->waitForFinished(); - } - - Calamares::RequirementsList l; - l.append( { - QLatin1String( "partitions" ), - [] { return tr( "has at least one disk device available." ); }, - [] { return tr( "There are no partitions to install on." ); }, - m_core->deviceModel()->rowCount() > 0, // satisfied -#ifdef DEBUG_PARTITION_UNSAFE - false // optional -#else - true // required -#endif - } ); - - return l; -} - -CALAMARES_PLUGIN_FACTORY_DEFINITION( PartitionViewStepFactory, registerPlugin< PartitionViewStep >(); ) diff --git a/src/modules/partition/PartitionViewStep.h b/src/modules/partition/PartitionViewStep.h deleted file mode 100644 index ecba73f45e..0000000000 --- a/src/modules/partition/PartitionViewStep.h +++ /dev/null @@ -1,89 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2014-2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef PARTITIONVIEWSTEP_H -#define PARTITIONVIEWSTEP_H - -#include "utils/PluginFactory.h" -#include "viewpages/ViewStep.h" - -#include "DllMacro.h" - -#include -#include - -class ChoicePage; -class Config; -class PartitionPage; -class PartitionCoreModule; -class QStackedWidget; -class WaitingWidget; - -template < typename T > -class QFutureWatcher; - -/** - * The starting point of the module. Instantiates PartitionCoreModule, - * ChoicePage and PartitionPage, then connects them. - */ -class PLUGINDLLEXPORT PartitionViewStep : public Calamares::ViewStep -{ - Q_OBJECT - -public: - explicit PartitionViewStep( QObject* parent = nullptr ); - ~PartitionViewStep() override; - - QString prettyName() const override; - QString prettyStatus() const override; - QWidget* createSummaryWidget() const override; - - QWidget* widget() override; - - void next() override; - void back() override; - - bool isNextEnabled() const override; - bool isBackEnabled() const override; - - bool isAtBeginning() const override; - bool isAtEnd() const override; - - void onActivate() override; - void onLeave() override; - - void setConfigurationMap( const QVariantMap& configurationMap ) override; - - Calamares::JobList jobs() const override; - - Calamares::RequirementsList checkRequirements() override; - -private: - void initPartitionCoreModule(); - void continueLoading(); - - /// "slot" for changes to next-status from the KPMCore and ChoicePage - void nextPossiblyChanged( bool ); - - Config* m_config; - - PartitionCoreModule* m_core; - QStackedWidget* m_widget; - ChoicePage* m_choicePage; - PartitionPage* m_manualPartitionPage; - - WaitingWidget* m_waitingWidget; - QFutureWatcher< void >* m_future; -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( PartitionViewStepFactory ) - -#endif // PARTITIONVIEWSTEP_H diff --git a/src/modules/partition/README.md b/src/modules/partition/README.md deleted file mode 100644 index d9d0d87d9d..0000000000 --- a/src/modules/partition/README.md +++ /dev/null @@ -1,96 +0,0 @@ -#Architecture - - - -## Overview - -The heart of the module is the PartitionCoreModule class. It holds Qt models for -the various elements and can create Calamares jobs representing the changes to -be performed at install time. - -PartitionPage is the main UI class. It represents the module main page, the one -with the device combo box, partition list and action buttons. It reacts to the -buttons by creating various dialogs (the (...)Dialog classes) and tell -PartitionCoreModule what to do. - - -## Use of KPMcore - -This module depends on KPMcore, the same library used by [KDE Partition Manager][kpm]. - -[kpm]: http://sourceforge.net/projects/partitionman/ - - -## Partition and PartitionInfo - -Calamares needs to store some information about partitions which is not -available in Partition Manager's Partition class. - -This includes the install mount point and a boolean to mark whether an existing -partition should be formatted. - -Reusing the existing `Partition::mountPoint` property was not an option because -it stores the directory where a partition is currently mounted, which is a -different concept from the directory where the user wants the partition to be -mounted on the installed system. We can't hijack this to store our install mount -point because whether the partition is currently mounted is an important -information which should be taken into account later to prevent any modification -on an installed partition. - -The way this extra information is stored is a bit unusual: the functions in the -PartitionInfo namespace takes advantage of Qt dynamic properties methods to add -Calamares-specific properties to the Partition instances: setting the install -mount point is done with `PartitionInfo::setMountPoint(partition, "/")`, -retrieving it is done with `mountPoint = PartitionInfo::mountPoint(partition)`. - -The rationale behind this unusual design is simplicity: the alternative would -have been to keep a separate PartitionInfo object and a map linking each -Partition to its PartitionInfo instance. Such a design makes things more -complicated. It complicates memory management: if a Partition goes away, its -matching PartitionInfo must be removed. It also leads to uglier APIs: code which -needs access to extra partition information must be passed both Partition and -PartitionInfo instances or know a way to get a PartitionInfo from a Partition. - -The other alternative would have been to add Calamares-specific information to -the real Partition object. This would have worked and would have made for a less -surprising API, but it would mean more Calamares-specific patches on KPMcore. - - -#Tests - -The module comes with unit tests for the partition jobs. Those tests need to -run on storage device which does not contain any data you care about. - -To build them: - - cd $top_build_dir - make buildtests - -To run them you need to define the `CALAMARES_TEST_DISK` environment variable. -It should contain the device path to the test disk. For example, assuming you -plugged a test USB stick identified as `/dev/sdb`, you would run the tests like -this: - - sudo CALAMARES_TEST_DISK=/dev/sdb $top_build_dir/partitionjobtests - - -#TODO - -- Support resizing extended partitions. ResizePartitionJob should already - support this but the UI prevents editing of extended partitions for now. - -- Use os-prober to find out the installed OS. This information could then be - used in PartitionModel and in the partition views. - -- PartitionBarsView - - Show used space - - Highlight selected partition - - Make the partitions clickable - - Match appearance with PartResizerWidget appearance - -- Expose PartitionInfo::format in PartitionModel and add a column for it in the - tree view diff --git a/src/modules/partition/core/BootLoaderModel.cpp b/src/modules/partition/core/BootLoaderModel.cpp deleted file mode 100644 index 1e5e75f073..0000000000 --- a/src/modules/partition/core/BootLoaderModel.cpp +++ /dev/null @@ -1,215 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-FileCopyrightText: 2021 Anubhav Choudhary - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "core/BootLoaderModel.h" - -#include "core/KPMHelpers.h" -#include "core/PartitionInfo.h" - -#include "utils/Logger.h" - -// KPMcore -#include -#include - -#include - -static QStandardItem* -createBootLoaderItem( const QString& description, const QString& path, bool isPartition ) -{ - QStandardItem* item = new QStandardItem( description ); - item->setData( path, BootLoaderModel::BootLoaderPathRole ); - item->setData( isPartition, BootLoaderModel::IsPartitionRole ); - return item; -} - -BootLoaderModel::BootLoaderModel( QObject* parent ) - : QStandardItemModel( parent ) -{ -} - -BootLoaderModel::~BootLoaderModel() {} - -void -BootLoaderModel::init( const QList< Device* >& devices ) -{ - beginResetModel(); - blockSignals( true ); - - m_devices = devices; - updateInternal(); - - blockSignals( false ); - endResetModel(); -} - -void -BootLoaderModel::createMbrItems() -{ - for ( auto device : m_devices ) - { - QString text = tr( "Master Boot Record of %1", "@info" ).arg( device->name() ); - appendRow( createBootLoaderItem( text, device->deviceNode(), false ) ); - } -} - -void -BootLoaderModel::update() -{ - beginResetModel(); - blockSignals( true ); - updateInternal(); - blockSignals( false ); - endResetModel(); -} - - -void -BootLoaderModel::updateInternal() -{ - QMutexLocker lock( &m_lock ); - clear(); - createMbrItems(); - - // An empty model is possible if you don't have permissions: don't crash though. - if ( rowCount() < 1 ) - { - return; - } - - QString partitionText; - Partition* partition = KPMHelpers::findPartitionByMountPoint( m_devices, "/boot" ); - if ( partition ) - { - partitionText = tr( "Boot Partition", "@info" ); - } - else - { - partition = KPMHelpers::findPartitionByMountPoint( m_devices, "/" ); - if ( partition ) - { - partitionText = tr( "System Partition", "@info" ); - } - } - - Q_ASSERT( rowCount() > 0 ); - QStandardItem* last = item( rowCount() - 1 ); - Q_ASSERT( last ); - bool lastIsPartition = last->data( IsPartitionRole ).toBool(); - - if ( !partition ) - { - if ( lastIsPartition ) - { - takeRow( rowCount() - 1 ); - } - } - else - { - QString mountPoint = PartitionInfo::mountPoint( partition ); - if ( lastIsPartition ) - { - last->setText( partitionText ); - last->setData( mountPoint, BootLoaderPathRole ); - } - else - { - appendRow( createBootLoaderItem( partitionText, PartitionInfo::mountPoint( partition ), true ) ); - } - } - // Create "don't install bootloader" item. This is always available, - // also if there was no /boot or / partition found. - appendRow( createBootLoaderItem( tr( "Do not install a boot loader", "@label" ), QString(), false ) ); -} - - -QVariant -BootLoaderModel::data( const QModelIndex& index, int role ) const -{ - QMutexLocker lock( &m_lock ); - if ( role == Qt::DisplayRole ) - { - QString displayRole = QStandardItemModel::data( index, Qt::DisplayRole ).toString(); - QString pathRole = QStandardItemModel::data( index, BootLoaderModel::BootLoaderPathRole ).toString(); - if ( pathRole.isEmpty() ) - { - return displayRole; - } - - return tr( "%1 (%2)" ).arg( displayRole, pathRole ); - } - return QStandardItemModel::data( index, role ); -} - -std::pair< int, Device* > -BootLoaderModel::findBootLoader( const QString& path ) const -{ - int r = 0; - for ( Device* d : m_devices ) - { - if ( d && d->deviceNode() == path ) - { - return std::make_pair( r, d ); - } - r++; - } - - Partition* partition = KPMHelpers::findPartitionByMountPoint( m_devices, path ); - if ( partition ) - { - const QString partition_device_path = partition->deviceNode(); - r = 0; - for ( Device* d : m_devices ) - { - if ( d && d->deviceNode() == partition_device_path ) - { - return std::make_pair( r, d ); - } - r++; - } - } - return std::make_pair( -1, nullptr ); -} - - -namespace Calamares -{ -void -restoreSelectedBootLoader( QComboBox& combo, const QString& path ) -{ - const auto* model = combo.model(); - if ( model->rowCount() < 1 ) - { - cDebug() << "No items in BootLoaderModel"; - return; - } - - if ( path.isEmpty() ) - { - cDebug() << "No path to restore, choosing default"; - combo.setCurrentIndex( 0 ); - return; - } - - const BootLoaderModel* bmodel = qobject_cast< const BootLoaderModel* >( model ); - int r = bmodel ? bmodel->findBootLoader( path ).first : -1; - if ( r >= 0 ) - { - combo.setCurrentIndex( r ); - } - else - { - combo.setCurrentIndex( 0 ); - } -} - -} // namespace Calamares diff --git a/src/modules/partition/core/BootLoaderModel.h b/src/modules/partition/core/BootLoaderModel.h deleted file mode 100644 index e640d4d7c7..0000000000 --- a/src/modules/partition/core/BootLoaderModel.h +++ /dev/null @@ -1,75 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ -#ifndef BOOTLOADERMODEL_H -#define BOOTLOADERMODEL_H - -#include -#include -#include - -class Device; -class QComboBox; - -/** - * This model contains one entry for each device MBR plus one entry for the - * /boot or / partition - */ -class BootLoaderModel : public QStandardItemModel -{ - Q_OBJECT -public: - using DeviceList = QList< Device* >; - - enum - { - BootLoaderPathRole = Qt::UserRole + 1, - IsPartitionRole - }; - - BootLoaderModel( QObject* parent = nullptr ); - ~BootLoaderModel() override; - - /** - * Init the model with the list of devices. Does *not* take ownership of the - * devices. - */ - void init( const DeviceList& devices ); - - void update(); - - QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const override; - - /** @brief Looks up a boot-loader by device-name @p path (e.g. /dev/sda) - * - * Returns a row number (index) in the model and a Device*: if there **is** a - * device for the given @p path, index will be in range of the model and - * Device* non-null. Returns (-1, nullptr) otherwise. - */ - std::pair< int, Device* > findBootLoader( const QString& path ) const; - -private: - DeviceList m_devices; - mutable QMutex m_lock; - - void createMbrItems(); - void updateInternal(); -}; - -namespace Calamares -{ -/** @brief Tries to set @p path as selected item in @p combo - * - * Matches a boot-loader install path (e.g. /dev/sda) with a model - * row and sets that as the current row. - */ -void restoreSelectedBootLoader( QComboBox& combo, const QString& path ); -} // namespace Calamares -#endif /* BOOTLOADERMODEL_H */ diff --git a/src/modules/partition/core/ColorUtils.cpp b/src/modules/partition/core/ColorUtils.cpp deleted file mode 100644 index 6dc17be113..0000000000 --- a/src/modules/partition/core/ColorUtils.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "core/ColorUtils.h" - -#include "core/KPMHelpers.h" - -#include "partition/PartitionIterator.h" -#include "partition/PartitionQuery.h" -#include "utils/Logger.h" - -// KPMcore -#include -#include - -// Qt -#include -#include - -using Calamares::Partition::isPartitionFreeSpace; -using Calamares::Partition::isPartitionNew; -using Calamares::Partition::PartitionIterator; - -static const int NUM_PARTITION_COLORS = 5; -static const int NUM_NEW_PARTITION_COLORS = 4; -//Let's try to use the Breeze palette -static const QColor PARTITION_COLORS[ NUM_PARTITION_COLORS ] = { - "#2980b9", //Dark Plasma Blue - "#27ae60", //Dark Icon Green - "#c9ce3b", //Dirty Yellow - "#3daee9", //Plasma Blue - "#9b59b6", //Purple -}; -static const QColor NEW_PARTITION_COLORS[ NUM_NEW_PARTITION_COLORS ] = { - "#c0392b", //Dark Icon Red - "#f39c1f", //Dark Icon Yellow - "#f1b7bc", //Light Salmon - "#fed999", //Light Orange -}; -static QColor FREE_SPACE_COLOR = "#777777"; -static QColor EXTENDED_COLOR = "#aaaaaa"; -static QColor UNKNOWN_DISKLABEL_COLOR = "#4d4151"; - -static QMap< QString, QColor > s_partitionColorsCache; - - -namespace ColorUtils -{ - -QColor -freeSpaceColor() -{ - return FREE_SPACE_COLOR; -} - -QColor -unknownDisklabelColor() -{ - return UNKNOWN_DISKLABEL_COLOR; -} - -PartitionNode* -_findRootForPartition( PartitionNode* partition ) -{ - if ( partition->isRoot() || !partition->parent() ) - { - return partition; - } - - return _findRootForPartition( partition->parent() ); -} - -QColor -colorForPartition( Partition* partition ) -{ - if ( !partition ) - { - cWarning() << "NULL partition"; - return FREE_SPACE_COLOR; - } - - if ( isPartitionFreeSpace( partition ) ) - { - return FREE_SPACE_COLOR; - } - if ( partition->roles().has( PartitionRole::Extended ) ) - { - return EXTENDED_COLOR; - } - - if ( partition->fileSystem().supportGetUUID() != FileSystem::cmdSupportNone - && !partition->fileSystem().uuid().isEmpty() ) - { - if ( partition->fileSystem().type() == FileSystem::Luks || partition->fileSystem().type() == FileSystem::Luks2 ) - { - FS::luks& luksFs = dynamic_cast< FS::luks& >( partition->fileSystem() ); - if ( !luksFs.outerUuid().isEmpty() && s_partitionColorsCache.contains( luksFs.outerUuid() ) ) - { - return s_partitionColorsCache[ luksFs.outerUuid() ]; - } - } - - if ( s_partitionColorsCache.contains( partition->fileSystem().uuid() ) ) - { - return s_partitionColorsCache[ partition->fileSystem().uuid() ]; - } - } - - // No partition-specific color needed, pick one from our list, but skip - // free space: we don't want a partition to change colors if space before - // it is inserted or removed - PartitionNode* parent = _findRootForPartition( partition ); - PartitionTable* table = dynamic_cast< PartitionTable* >( parent ); - Q_ASSERT( table ); - int colorIdx = 0; - int newColorIdx = 0; - for ( PartitionIterator it = PartitionIterator::begin( table ); it != PartitionIterator::end( table ); ++it ) - { - Partition* child = *it; - if ( child == partition ) - { - break; - } - if ( !isPartitionFreeSpace( child ) && !child->hasChildren() ) - { - if ( isPartitionNew( child ) ) - { - ++newColorIdx; - } - ++colorIdx; - } - } - - if ( isPartitionNew( partition ) ) - { - return NEW_PARTITION_COLORS[ newColorIdx % NUM_NEW_PARTITION_COLORS ]; - } - - if ( partition->fileSystem().supportGetUUID() != FileSystem::cmdSupportNone - && !partition->fileSystem().uuid().isEmpty() ) - { - if ( partition->fileSystem().type() == FileSystem::Luks || partition->fileSystem().type() == FileSystem::Luks2 ) - { - FS::luks& luksFs = dynamic_cast< FS::luks& >( partition->fileSystem() ); - if ( !luksFs.outerUuid().isEmpty() ) - { - s_partitionColorsCache.insert( luksFs.outerUuid(), - PARTITION_COLORS[ colorIdx % NUM_PARTITION_COLORS ] ); - } - } - else - { - s_partitionColorsCache.insert( partition->fileSystem().uuid(), - PARTITION_COLORS[ colorIdx % NUM_PARTITION_COLORS ] ); - } - } - return PARTITION_COLORS[ colorIdx % NUM_PARTITION_COLORS ]; -} - - -QColor -colorForPartitionInFreeSpace( Partition* partition ) -{ - PartitionNode* parent = _findRootForPartition( partition ); - PartitionTable* table = dynamic_cast< PartitionTable* >( parent ); - Q_ASSERT( table ); - int newColorIdx = 0; - for ( PartitionIterator it = PartitionIterator::begin( table ); it != PartitionIterator::end( table ); ++it ) - { - Partition* child = *it; - if ( child == partition ) - { - break; - } - if ( !isPartitionFreeSpace( child ) && !child->hasChildren() && isPartitionNew( child ) ) - { - ++newColorIdx; - } - } - return NEW_PARTITION_COLORS[ newColorIdx % NUM_NEW_PARTITION_COLORS ]; -} - - -void -invalidateCache() -{ - s_partitionColorsCache.clear(); -} - -} // namespace ColorUtils diff --git a/src/modules/partition/core/ColorUtils.h b/src/modules/partition/core/ColorUtils.h deleted file mode 100644 index 9ebce580b3..0000000000 --- a/src/modules/partition/core/ColorUtils.h +++ /dev/null @@ -1,49 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2016 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ -#ifndef COLORUTILS_H -#define COLORUTILS_H - -class QColor; - -class Partition; - -/** - * Helper functions to define colors for partitions. It ensures no consecutive - * partitions have the same color. - */ -namespace ColorUtils -{ - -QColor freeSpaceColor(); - -QColor unknownDisklabelColor(); - -/** - * @brief colorForPartition iterates over partitions, caches their colors and returns - * a color for the given partition. - * @param partition the partition for which to return a color. - * @return a color for the partition. - */ -QColor colorForPartition( Partition* partition ); - -/** - * This is similar to colorForPartition() but returns the color of a partition - * which would be created in freeSpacePartition - */ -QColor colorForPartitionInFreeSpace( Partition* freeSpacePartition ); - -/** - * @brief invalidateCache clears the partition colors cache. - */ -void invalidateCache(); - -} // namespace ColorUtils - -#endif /* COLORUTILS_H */ diff --git a/src/modules/partition/core/DeviceList.cpp b/src/modules/partition/core/DeviceList.cpp deleted file mode 100644 index 16723c750a..0000000000 --- a/src/modules/partition/core/DeviceList.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2018-2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "DeviceList.h" - -#include "partition/PartitionIterator.h" -#include "utils/Logger.h" -#include "utils/System.h" - -#include -#include -#include -#include - -#include - -using Calamares::Partition::PartitionIterator; - -namespace PartUtils -{ - -/** - * Does the given @p device contain the root filesystem? This is true if - * the device contains a partition which is currently mounted at / . - */ -static bool -hasRootPartition( Device* device ) -{ - for ( auto it = PartitionIterator::begin( device ); it != PartitionIterator::end( device ); ++it ) - { - if ( ( *it )->mountPoint() == "/" ) - { - return true; - } - } - return false; -} - -/** @brief Check if @p path holds an iso9660 filesystem - * - * The @p path should point to a device; blkid is used to check the FS type. - */ -static bool -blkIdCheckIso9660( const QString& path ) -{ - // If blkid fails, there's no output, but we don't care - auto r = Calamares::System::runCommand( { "blkid", path }, std::chrono::seconds( 30 ) ); - return r.getOutput().contains( "iso9660" ); -} - -/// @brief Convenience to check if @p partition holds an iso9660 filesystem -static bool -blkIdCheckIso9660P( const Partition* partition ) -{ - return blkIdCheckIso9660( partition->partitionPath() ); -} - -/** @brief Check if the @p device is an iso9660 device - * - * An iso9660 device is **probably** a CD-ROM. If the device holds an - * iso9660 FS, or any of its partitions do, then we call it an iso9660 device. - */ -static bool -isIso9660( const Device* device ) -{ - const QString path = device->deviceNode(); - if ( path.isEmpty() ) - { - return false; - } - if ( blkIdCheckIso9660( path ) ) - { - return true; - } - - if ( device->partitionTable() && !device->partitionTable()->children().isEmpty() ) - { - const auto& p = device->partitionTable()->children(); - return std::any_of( p.cbegin(), p.cend(), blkIdCheckIso9660P ); - } - return false; -} - -static inline bool -isZRam( const Device* device ) -{ - const QString path = device->deviceNode(); - return path.startsWith( "/dev/zram" ); -} - -static inline bool -isFloppyDrive( const Device* device ) -{ - const QString path = device->deviceNode(); - return path.startsWith( "/dev/fd" ) || path.startsWith( "/dev/floppy" ); -} - -static inline QDebug& -operator<<( QDebug& s, QList< Device* >::iterator& it ) -{ - s << ( ( *it ) ? ( *it )->deviceNode() : QString( "" ) ); - return s; -} - -using DeviceList = QList< Device* >; - -static inline DeviceList::iterator -erase( DeviceList& l, DeviceList::iterator& it ) -{ - Device* p = *it; - auto r = l.erase( it ); - delete p; - return r; -} - -QList< Device* > -getDevices( DeviceType which ) -{ - CoreBackend* backend = CoreBackendManager::self()->backend(); - if ( !backend ) - { - cWarning() << "No KPM backend found."; - return {}; - } - DeviceList devices = backend->scanDevices( /* not includeReadOnly, not includeLoopback */ ScanFlag( 0 ) ); - - /* The list of devices is cleaned up for use: - * - some devices can **never** be used (e.g. floppies, nullptr) - * - some devices can be used if unsafe mode is on, but not in normal operation - * Two lambda's are defined, - * - removeInAllModes() - * - removeInSafeMode() - * To handle the difference. - */ -#ifdef DEBUG_PARTITION_UNSAFE - cWarning() << "Allowing unsafe partitioning choices." << devices.count() << "candidates."; -#ifdef DEBUG_PARTITION_BAIL_OUT - cDebug() << Logger::SubEntry << "unsafe partitioning has been lamed, and will fail."; -#endif - - // Unsafe partitioning - auto removeInAllModes = []( DeviceList& l, DeviceList::iterator& it ) { return erase( l, it ); }; - auto removeInSafeMode = []( DeviceList&, DeviceList::iterator& it ) { return ++it; }; -#else - // Safe partitioning - auto removeInAllModes = []( DeviceList& l, DeviceList::iterator& it ) { return erase( l, it ); }; - auto& removeInSafeMode = removeInAllModes; -#endif - - cDebug() << "Removing unsuitable devices:" << devices.count() << "candidates."; - - bool writableOnly = ( which == DeviceType::WritableOnly ); - // Remove the device which contains / from the list - for ( DeviceList::iterator it = devices.begin(); it != devices.end(); ) - { - if ( !( *it ) ) - { - cDebug() << Logger::SubEntry << "Skipping nullptr device"; - it = removeInAllModes( devices, it ); - } - else if ( isZRam( *it ) ) - { - cDebug() << Logger::SubEntry << "Removing zram" << it; - it = removeInAllModes( devices, it ); - } - else if ( isFloppyDrive( ( *it ) ) ) - { - cDebug() << Logger::SubEntry << "Removing floppy disk" << it; - it = removeInAllModes( devices, it ); - } - else if ( writableOnly && hasRootPartition( *it ) ) - { - cDebug() << Logger::SubEntry << "Removing device with root filesystem (/) on it" << it; - it = removeInSafeMode( devices, it ); - } - else if ( writableOnly && isIso9660( *it ) ) - { - cDebug() << Logger::SubEntry << "Removing device with iso9660 filesystem (probably a CD) on it" << it; - it = removeInSafeMode( devices, it ); - } - else - { - ++it; - } - } - cDebug() << Logger::SubEntry << "there are" << devices.count() << "devices left."; - return devices; -} - -} // namespace PartUtils diff --git a/src/modules/partition/core/DeviceList.h b/src/modules/partition/core/DeviceList.h deleted file mode 100644 index b76a31a6bc..0000000000 --- a/src/modules/partition/core/DeviceList.h +++ /dev/null @@ -1,40 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2017 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef DEVICELIST_H -#define DEVICELIST_H - -#include -#include - -class Device; - -namespace PartUtils -{ - -enum class DeviceType -{ - All, - WritableOnly -}; - -/** - * @brief Gets a list of storage devices. - * @param which Can be used to select from all the devices in - * the system, filtering out those that do not meet a criterium. - * If set to WritableOnly, only devices which can be overwritten - * safely are returned (e.g. RO-media are ignored, as are mounted partitions). - * @return a list of Devices meeting this criterium. - */ -QList< Device* > getDevices( DeviceType which = DeviceType::All ); - -} // namespace PartUtils - -#endif // DEVICELIST_H diff --git a/src/modules/partition/core/DeviceModel.cpp b/src/modules/partition/core/DeviceModel.cpp deleted file mode 100644 index 160cc7ba72..0000000000 --- a/src/modules/partition/core/DeviceModel.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2014 Teo Mrnjavac - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ -#include "DeviceModel.h" - -#include "core/PartitionModel.h" -#include "core/SizeUtils.h" - -#include "utils/Gui.h" -#include "utils/Logger.h" - -// KPMcore -#include - -#include -#include - -// STL -#include - -static void -sortDevices( DeviceModel::DeviceList& l ) -{ - std::sort( l.begin(), - l.end(), - []( const Device* dev1, const Device* dev2 ) { return dev1->deviceNode() < dev2->deviceNode(); } ); -} - -DeviceModel::DeviceModel( QObject* parent ) - : QAbstractListModel( parent ) -{ -} - -DeviceModel::~DeviceModel() {} - -void -DeviceModel::init( const DeviceList& devices ) -{ - beginResetModel(); - m_devices = devices; - sortDevices( m_devices ); - endResetModel(); -} - -int -DeviceModel::rowCount( const QModelIndex& parent ) const -{ - return parent.isValid() ? 0 : m_devices.count(); -} - -QVariant -DeviceModel::data( const QModelIndex& index, int role ) const -{ - int row = index.row(); - if ( row < 0 || row >= m_devices.count() ) - { - return QVariant(); - } - - Device* device = m_devices.at( row ); - - switch ( role ) - { - case Qt::DisplayRole: - case Qt::ToolTipRole: - if ( device->name().isEmpty() ) - { - return device->deviceNode(); - } - else - { - if ( device->logicalSize() >= 0 && device->totalLogical() >= 0 ) - { - //: device[name] - size[number] (device-node[name]) - return tr( "%1 - %2 (%3)" ) - .arg( device->name() ) - .arg( formatByteSize( device->capacity() ) ) - .arg( device->deviceNode() ); - } - else - { - // Newly LVM VGs don't have capacity property yet (i.e. - // always has 1B capacity), so don't show it for a while. - // - //: device[name] - (device-node[name]) - return tr( "%1 - (%2)" ).arg( device->name() ).arg( device->deviceNode() ); - } - } - case Qt::DecorationRole: - return Calamares::defaultPixmap( - Calamares::PartitionDisk, - Calamares::Original, - QSize( Calamares::defaultIconSize().width() * 2, Calamares::defaultIconSize().height() * 2 ) ); - default: - return QVariant(); - } -} - -Device* -DeviceModel::deviceForIndex( const QModelIndex& index ) const -{ - int row = index.row(); - if ( row < 0 || row >= m_devices.count() ) - { - return nullptr; - } - return m_devices.at( row ); -} - -void -DeviceModel::swapDevice( Device* oldDevice, Device* newDevice ) -{ - Q_ASSERT( oldDevice ); - Q_ASSERT( newDevice ); - - int indexOfOldDevice = m_devices.indexOf( oldDevice ); - if ( indexOfOldDevice < 0 ) - { - return; - } - - m_devices[ indexOfOldDevice ] = newDevice; - - Q_EMIT dataChanged( index( indexOfOldDevice ), index( indexOfOldDevice ) ); -} - -void -DeviceModel::addDevice( Device* device ) -{ - beginResetModel(); - m_devices << device; - sortDevices( m_devices ); - endResetModel(); -} - -void -DeviceModel::removeDevice( Device* device ) -{ - beginResetModel(); - m_devices.removeAll( device ); - sortDevices( m_devices ); - endResetModel(); -} diff --git a/src/modules/partition/core/DeviceModel.h b/src/modules/partition/core/DeviceModel.h deleted file mode 100644 index 71918f64dd..0000000000 --- a/src/modules/partition/core/DeviceModel.h +++ /dev/null @@ -1,53 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2017 2019, Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ -#ifndef DEVICEMODEL_H -#define DEVICEMODEL_H - -#include -#include -#include - -class Device; -class PartitionModel; - -/** - * A Qt model which exposes a list of Devices. - */ -class DeviceModel : public QAbstractListModel -{ - Q_OBJECT -public: - DeviceModel( QObject* parent = nullptr ); - ~DeviceModel() override; - - using DeviceList = QList< Device* >; - - /** - * Init the model with the list of devices. Does *not* take ownership of the - * devices. - */ - void init( const DeviceList& devices ); - - int rowCount( const QModelIndex& parent = QModelIndex() ) const override; - QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const override; - - Device* deviceForIndex( const QModelIndex& index ) const; - - void swapDevice( Device* oldDevice, Device* newDevice ); - - void addDevice( Device* device ); - - void removeDevice( Device* device ); - -private: - DeviceList m_devices; -}; - -#endif /* DEVICEMODEL_H */ diff --git a/src/modules/partition/core/KPMHelpers.cpp b/src/modules/partition/core/KPMHelpers.cpp deleted file mode 100644 index 50fd11d674..0000000000 --- a/src/modules/partition/core/KPMHelpers.cpp +++ /dev/null @@ -1,339 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac - * Copyright 2018-2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "core/KPMHelpers.h" - -#include "core/PartitionInfo.h" - -#include "partition/PartitionIterator.h" -#include "utils/Logger.h" -#include "utils/String.h" - -#include -#include -#include -#include -#include -#include -#include - -#include - -using Calamares::Partition::PartitionIterator; - -namespace KPMHelpers -{ - -Partition* -findPartitionByMountPoint( const QList< Device* >& devices, const QString& mountPoint ) -{ - for ( auto device : devices ) - { - for ( auto it = PartitionIterator::begin( device ); it != PartitionIterator::end( device ); ++it ) - { - if ( PartitionInfo::mountPoint( *it ) == mountPoint ) - { - return *it; - } - } - } - return nullptr; -} - - -Partition* -createNewPartition( PartitionNode* parent, - const Device& device, - const PartitionRole& role, - FileSystem::Type fsType, - const QString& fsLabel, - qint64 firstSector, - qint64 lastSector, - PartitionTable::Flags flags ) -{ - FileSystem* fs = FileSystemFactory::create( fsType, firstSector, lastSector, device.logicalSize() ); - fs->setLabel( fsLabel ); - return new Partition( parent, - device, - role, - fs, - fs->firstSector(), - fs->lastSector(), - QString() /* path */, - KPM_PARTITION_FLAG( None ) /* availableFlags */, - QString() /* mountPoint */, - false /* mounted */, - flags /* activeFlags */, - KPM_PARTITION_STATE( New ) ); -} - - -Partition* -createNewEncryptedPartition( PartitionNode* parent, - const Device& device, - const PartitionRole& role, - FileSystem::Type fsType, - const QString& fsLabel, - qint64 firstSector, - qint64 lastSector, - Config::LuksGeneration luksFsType, - const QString& passphrase, - PartitionTable::Flags flags ) -{ - PartitionRole::Roles newRoles = role.roles(); - if ( !role.has( PartitionRole::Luks ) ) - { - newRoles |= PartitionRole::Luks; - } - - FileSystem::Type luksType = luksGenerationToFSName( luksFsType ); - - FS::luks* fs = dynamic_cast< FS::luks* >( - FileSystemFactory::create( luksType, firstSector, lastSector, device.logicalSize() ) ); - if ( !fs ) - { - cError() << "cannot create LUKS filesystem. Giving up."; - return nullptr; - } - - fs->createInnerFileSystem( fsType ); - fs->setPassphrase( passphrase ); - fs->setLabel( fsLabel ); - Partition* p = new Partition( parent, - device, - PartitionRole( newRoles ), - fs, - fs->firstSector(), - fs->lastSector(), - QString() /* path */, - KPM_PARTITION_FLAG( None ) /* availableFlags */, - QString() /* mountPoint */, - false /* mounted */, - flags /* activeFlags */, - KPM_PARTITION_STATE( New ) ); - return p; -} - - -Partition* -clonePartition( Device* device, Partition* partition ) -{ - FileSystem* fs = FileSystemFactory::create( - partition->fileSystem().type(), partition->firstSector(), partition->lastSector(), device->logicalSize() ); - return new Partition( partition->parent(), - *device, - partition->roles(), - fs, - fs->firstSector(), - fs->lastSector(), - partition->partitionPath(), - partition->activeFlags() ); -} - -SavePassphraseValue -savePassphrase( Partition* partition, const QString& passphrase ) -{ - - if ( passphrase.isEmpty() ) - { - return SavePassphraseValue::EmptyPassphrase; - } - - FS::luks* luksFs = dynamic_cast< FS::luks* >( &partition->fileSystem() ); - if ( luksFs == nullptr ) - { - // No luks device - return SavePassphraseValue::NotLuksPartition; - } - - // Test the given passphrase - if ( !luksFs->testPassphrase( partition->partitionPath(), passphrase ) ) - { - // Save the existing passphrase - luksFs->setPassphrase( passphrase ); - } - else - { - return SavePassphraseValue::IncorrectPassphrase; - } - return SavePassphraseValue::NoError; -} - -// Adapted from src/fs/luks.cpp cryptOpen which always opens a dialog to ask for a passphrase -QString -cryptOpen( Partition* partition ) -{ - FS::luks* luksFs = dynamic_cast< FS::luks* >( &partition->fileSystem() ); - if ( luksFs == nullptr ) - { - // No luks device - return QString(); - } - - if ( luksFs->isCryptOpen() ) - { - if ( !luksFs->mapperName().isEmpty() ) - { - // Already decrypted - return luksFs->mapperName(); - } - else - { - cDebug() << Logger::SubEntry << "No mapper node found - reset cryptOpen"; - luksFs->setCryptOpen( false ); - } - } - - if ( luksFs->passphrase().isEmpty() ) - { - // No passphrase for decryption - return QString(); - } - - // Decrypt the partition - const QString deviceNode = partition->partitionPath(); - ExternalCommand openCmd( QStringLiteral( "cryptsetup" ), - { QStringLiteral( "open" ), deviceNode, luksFs->suggestedMapperName( deviceNode ) } ); - if ( ( openCmd.write( luksFs->passphrase().toLocal8Bit() + '\n' ) && openCmd.start( -1 ) - && openCmd.exitCode() == 0 ) ) - { - luksFs->scan( deviceNode ); - if ( luksFs->mapperName().isEmpty() ) - { - return QString(); - } - luksFs->loadInnerFileSystem( luksFs->mapperName() ); - luksFs->setCryptOpen( luksFs->innerFS() != nullptr ); - if ( !luksFs->isCryptOpen() ) - { - return QString(); - } - return luksFs->mapperName(); - } - return QString(); -} - -void -cryptClose( Partition* partition ) -{ - FS::luks* luksFs = dynamic_cast< FS::luks* >( &partition->fileSystem() ); - if ( luksFs == nullptr ) - { - // No luks device - return; - } - - if ( luksFs->mapperName().isEmpty() ) - { - // Not opened - return; - } - - // Close the partition - luksFs->cryptClose( partition->partitionPath() ); -} - -bool -cryptLabel( Partition* partition, const QString& label ) -{ - int version = cryptVersion( partition ); - if ( version == 0 || label.isEmpty() ) - { - return false; - } - - if ( version == 1 ) - { - QString mappedDevice = cryptOpen( partition ); - if ( !mappedDevice.isEmpty() ) - { - // Label mapped device - ExternalCommand openCmd( QStringLiteral( "e2label" ), { mappedDevice, label } ); - openCmd.start( -1 ); - cryptClose( partition ); - return true; - } - } - else - { - ExternalCommand openCmd( - QStringLiteral( "cryptsetup" ), - { QStringLiteral( "config" ), partition->partitionPath(), QStringLiteral( "--label" ), label } ); - if ( openCmd.start( -1 ) && openCmd.exitCode() == 0 ) - { - return true; - } - } - return false; -} - -int -cryptVersion( Partition* partition ) -{ - if ( partition->fileSystem().type() != FileSystem::Luks ) - { - return 0; - } - - // Get luks version from header information - int luksVersion = 1; - ExternalCommand openCmd( QStringLiteral( "cryptsetup" ), - { QStringLiteral( "luksDump" ), partition->partitionPath() } ); - if ( openCmd.start( -1 ) && openCmd.exitCode() == 0 ) - { - QRegularExpression re( QStringLiteral( R"(version:\s+(\d))" ), QRegularExpression::CaseInsensitiveOption ); - QRegularExpressionMatch rem = re.match( openCmd.output() ); - if ( rem.hasMatch() ) - { - luksVersion = rem.captured( 1 ).toInt(); - } - } - return luksVersion; -} - -FileSystem::Type -luksGenerationToFSName( Config::LuksGeneration luksGeneration ) -{ - // Convert luksGenerationChoice from partition.conf into its - // corresponding file system type from KPMCore. - switch ( luksGeneration ) - { - case Config::LuksGeneration::Luks2: - return FileSystem::Type::Luks2; - case Config::LuksGeneration::Luks1: - return FileSystem::Type::Luks; - default: - cWarning() << "luksGeneration not supported, defaulting to \"luks\""; - return FileSystem::Type::Luks; - } -} - - -Calamares::JobResult -execute( Operation& operation, const QString& failureMessage ) -{ - operation.setStatus( Operation::StatusRunning ); - - Report report( nullptr ); - if ( operation.execute( report ) ) - { - return Calamares::JobResult::ok(); - } - - // Remove the === lines from the report by trimming them to empty - QStringList l = report.toText().split( '\n' ); - std::for_each( l.begin(), l.end(), []( QString& s ) { Calamares::String::removeLeading( s, '=' ); } ); - - return Calamares::JobResult::error( failureMessage, l.join( '\n' ) ); -} - - -} // namespace KPMHelpers diff --git a/src/modules/partition/core/KPMHelpers.h b/src/modules/partition/core/KPMHelpers.h deleted file mode 100644 index 3ceafb003d..0000000000 --- a/src/modules/partition/core/KPMHelpers.h +++ /dev/null @@ -1,154 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ -#ifndef KPMHELPERS_H -#define KPMHELPERS_H - -#include "Config.h" -#include "Job.h" - -#include -#include -#include -#include - -#include - -#include - -class Device; -class Partition; -class PartitionNode; -class PartitionRole; - -// TODO:3.3: Remove defines, expand in-place -#define KPM_PARTITION_FLAG( x ) PartitionTable::Flag::x -#define KPM_PARTITION_STATE( x ) Partition::State::x -#define KPM_PARTITION_FLAG_ESP PartitionTable::Flag::Boot - -/** - * Helper functions to manipulate partitions - */ -namespace KPMHelpers -{ - -/** @brief Return (errors) for savePassphrase() - * - * There's a handful of things that can go wrong when - * saving a passphrase for a given partition; this - * expresses clearly which ones are wrong. - * - * @c NoError is "Ok" when saving the passphrase succeeds. - */ -enum class SavePassphraseValue -{ - NoError, - EmptyPassphrase, - NotLuksPartition, - IncorrectPassphrase, - CryptsetupError, - NoMapperNode, - DeviceNotDecrypted -}; - -/** - * Iterates on all devices and return the first partition which is associated - * with mountPoint. This uses PartitionInfo::mountPoint(), not Partition::mountPoint() - */ -Partition* findPartitionByMountPoint( const QList< Device* >& devices, const QString& mountPoint ); - -/** - * Helper function to create a new Partition object (does not create anything - * on the disk) associated with a FileSystem. - */ -Partition* createNewPartition( PartitionNode* parent, - const Device& device, - const PartitionRole& role, - FileSystem::Type fsType, - const QString& fsLabel, - qint64 firstSector, - qint64 lastSector, - PartitionTable::Flags flags ); - -Partition* createNewEncryptedPartition( PartitionNode* parent, - const Device& device, - const PartitionRole& role, - FileSystem::Type fsType, - const QString& fsLabel, - qint64 firstSector, - qint64 lastSector, - Config::LuksGeneration luksFsType, - const QString& passphrase, - PartitionTable::Flags flags ); - -Partition* clonePartition( Device* device, Partition* partition ); - -/** @brief Save an existing passphrase for a previously encrypted partition. - * - * Tries to apply the passphrase to the partition; this checks if the - * @p partition is one that can have a passphrase applied, and - * runs `cryptsetup` to check that the passphrase actually works - * for the partition. Returns `NoError` on success, or an explanatory - * other value if it fails. - */ -SavePassphraseValue savePassphrase( Partition* partition, const QString& passphrase ); - -/** @brief Decrypt an encrypted partition. - * - * Uses @p partition to decrypt the partition. - * The passphrase saved in @p partition is used. - * Returns the mapped device path or an empty string if it fails. - */ -QString cryptOpen( Partition* partition ); -void cryptClose( Partition* partition ); - -/** @brief Set label of luks encrypted partition. - * - * Returns true on success or false if it fails. - */ -bool cryptLabel( Partition* partition, const QString& label ); - -/** @brief Returns the luks version used to encrypt the partition. - * - * Used by cryptLabel - */ -int cryptVersion( Partition* partition ); - -/** @brief Convert a luksGeneration into its FS type for KPMCore. - * - * Will convert Luks1 into FileSystem::Type::luks and Luks2 into - * FileSystem::Type::luks2 for KPMCore partitioning functions. - * - * @return The LUKS FS type (default @c luks ) - */ -FileSystem::Type luksGenerationToFSName( Config::LuksGeneration luksGeneration ); - - -/** @brief Return a result for an @p operation - * - * Executes the operation, and if successful, returns a success result. - * Otherwise returns an error using @p failureMessage as the primary part - * of the error, and details obtained from the operation. - */ -Calamares::JobResult execute( Operation& operation, const QString& failureMessage ); -/** @brief Return a result for an @p operation - * - * It's acceptable to use an rvalue: the operation-running is the effect - * you're interested in, rather than keeping the temporary around. - */ -static inline Calamares::JobResult -execute( Operation&& operation, const QString& failureMessage ) -{ - return execute( operation, failureMessage ); -} - -} // namespace KPMHelpers - -#endif /* KPMHELPERS_H */ diff --git a/src/modules/partition/core/OsproberEntry.h b/src/modules/partition/core/OsproberEntry.h deleted file mode 100644 index 86b7691b89..0000000000 --- a/src/modules/partition/core/OsproberEntry.h +++ /dev/null @@ -1,54 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef OSPROBERENTRY_H -#define OSPROBERENTRY_H - -#include - -struct FstabEntry -{ - QString partitionNode; - QString mountPoint; - QString fsType; - QString options; - int dump; - int pass; - - /// Does this entry make sense and is it complete? - bool isValid() const; // implemented in Partutils.cpp - - /** @brief Create an entry from a live of /etc/fstab - * - * Splits the given string (which ought to follow the format - * of /etc/fstab) and returns a corresponding Fstab entry. - * If the string isn't valid (e.g. comment-line, or broken - * fstab entry) then the entry that is returned is invalid. - */ - static FstabEntry fromEtcFstab( const QString& ); // implemented in Partutils.cpp -}; - -typedef QList< FstabEntry > FstabEntryList; - -struct OsproberEntry -{ - QString prettyName; - QString path; - QString file; - QString uuid; - bool canBeResized; - QStringList line; - FstabEntryList fstab; - QString homePath; -}; - -typedef QList< OsproberEntry > OsproberEntryList; - -#endif // OSPROBERENTRY_H diff --git a/src/modules/partition/core/PartUtils.cpp b/src/modules/partition/core/PartUtils.cpp deleted file mode 100644 index bc3e6f5a02..0000000000 --- a/src/modules/partition/core/PartUtils.cpp +++ /dev/null @@ -1,681 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2018-2019 Adriaan de Groot - * SPDX-FileCopyrightText: 2019 Collabora Ltd - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "PartUtils.h" - -#include "core/DeviceModel.h" -#include "core/KPMHelpers.h" -#include "core/PartitionInfo.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "partition/Mount.h" -#include "partition/PartitionIterator.h" -#include "partition/PartitionQuery.h" -#include "utils/Logger.h" -#include "utils/RAII.h" -#include "utils/System.h" - -#include -#include -#include -#include - -#include -#include - -using Calamares::Partition::isPartitionFreeSpace; -using Calamares::Partition::isPartitionNew; - -using Calamares::Units::operator""_MiB; - -static constexpr qint64 efiSpecificationHardMinimumSize = 32_MiB; - -namespace PartUtils -{ - -QString -convenienceName( const Partition* const candidate ) -{ - if ( !candidate->mountPoint().isEmpty() ) - { - return candidate->mountPoint(); - } - if ( !candidate->partitionPath().isEmpty() ) - { - return candidate->partitionPath(); - } - if ( !candidate->devicePath().isEmpty() ) - { - return candidate->devicePath(); - } - if ( !candidate->deviceNode().isEmpty() ) - { - return candidate->devicePath(); - } - - QString p; - QTextStream s( &p ); - s << static_cast< const void* >( candidate ); // No good name available, use pointer address - - return p; -} - -/** @brief Get the globalStorage setting for required space. */ -static double -getRequiredStorageGiB( bool& ok ) -{ - return Calamares::JobQueue::instance()->globalStorage()->value( "requiredStorageGiB" ).toDouble( &ok ); -} - -bool -canBeReplaced( Partition* candidate, const Logger::Once& o ) -{ - if ( !candidate ) - { - cDebug() << o << "Partition* is NULL"; - return false; - } - - cDebug() << o << "Checking if" << convenienceName( candidate ) << "can be replaced."; - if ( candidate->isMounted() ) - { - cDebug() << Logger::SubEntry << "NO, it is mounted."; - return false; - } - - bool ok = false; - double requiredStorageGiB = getRequiredStorageGiB( ok ); - if ( !ok ) - { - cDebug() << Logger::SubEntry << "NO, requiredStorageGiB is not set correctly."; - return false; - } - - qint64 availableStorageB = candidate->capacity(); - qint64 requiredStorageB = Calamares::GiBtoBytes( requiredStorageGiB + 0.5 ); - - if ( availableStorageB > requiredStorageB ) - { - cDebug() << o << "Partition" << convenienceName( candidate ) << "authorized for replace install."; - return true; - } - else - { - Logger::CDebug deb; - deb << Logger::SubEntry << "NO, insufficient storage"; - deb << Logger::Continuation << "Required storage B:" << requiredStorageB - << QString( "(%1GiB)" ).arg( requiredStorageGiB ); - deb << Logger::Continuation << "Available storage B:" << availableStorageB - << QString( "(%1GiB)" ).arg( Calamares::BytesToGiB( availableStorageB ) ); - return false; - } -} - -bool -canBeResized( Partition* candidate, const Logger::Once& o ) -{ - if ( !candidate ) - { - cDebug() << o << "Partition* is NULL"; - return false; - } - - if ( !candidate->fileSystem().supportGrow() || !candidate->fileSystem().supportShrink() ) - { - cDebug() << o << "Can not resize" << convenienceName( candidate ) << ", filesystem" - << candidate->fileSystem().name() << "does not support resize."; - return false; - } - - if ( isPartitionFreeSpace( candidate ) ) - { - cDebug() << o << "Can not resize" << convenienceName( candidate ) << ", partition is free space"; - return false; - } - - if ( candidate->isMounted() ) - { - cDebug() << o << "Can not resize" << convenienceName( candidate ) << ", partition is mounted"; - return false; - } - - if ( candidate->roles().has( PartitionRole::Primary ) ) - { - PartitionTable* table = dynamic_cast< PartitionTable* >( candidate->parent() ); - if ( !table ) - { - cDebug() << o << "Can not resize" << convenienceName( candidate ) << ", no partition table found"; - return false; - } - - if ( table->numPrimaries() >= table->maxPrimaries() ) - { - cDebug() << o << "Can not resize" << convenienceName( candidate ) << ", partition table already has" - << table->maxPrimaries() << "primary partitions."; - return false; - } - } - - bool ok = false; - double requiredStorageGiB = getRequiredStorageGiB( ok ); - if ( !ok ) - { - cDebug() << o << "Can not resize" << convenienceName( candidate ) - << ", requiredStorageGiB is not set correctly."; - return false; - } - - // We require a little more for partitioning overhead and swap file - double advisedStorageGiB = requiredStorageGiB + 0.5 + 2.0; - qint64 availableStorageB = candidate->available(); - qint64 advisedStorageB = Calamares::GiBtoBytes( advisedStorageGiB ); - - if ( availableStorageB > advisedStorageB ) - { - cDebug() << o << "Partition" << convenienceName( candidate ) - << "authorized for resize + autopartition install."; - return true; - } - else - { - Logger::CDebug deb; - deb << Logger::SubEntry << "NO, insufficient storage"; - deb << Logger::Continuation << "Required storage B:" << advisedStorageB - << QString( "(%1GiB)" ).arg( advisedStorageGiB ); - deb << Logger::Continuation << "Available storage B:" << availableStorageB - << QString( "(%1GiB)" ).arg( Calamares::BytesToGiB( availableStorageB ) ) << "for" - << convenienceName( candidate ) << "length:" << candidate->length() - << "sectorsUsed:" << candidate->sectorsUsed() << "fsType:" << candidate->fileSystem().name(); - return false; - } -} - -bool -canBeResized( DeviceModel* dm, const QString& partitionPath, const Logger::Once& o ) -{ - if ( partitionPath.startsWith( "/dev/" ) ) - { - for ( int i = 0; i < dm->rowCount(); ++i ) - { - Device* dev = dm->deviceForIndex( dm->index( i ) ); - Partition* candidate = Calamares::Partition::findPartitionByPath( { dev }, partitionPath ); - if ( candidate ) - { - return canBeResized( candidate, o ); - } - } - cWarning() << "Can not resize" << partitionPath << ", no Partition* found."; - return false; - } - else - { - cWarning() << "Can not resize" << partitionPath << ", does not start with /dev"; - return false; - } -} - -static FstabEntryList -lookForFstabEntries( const QString& partitionPath ) -{ - QStringList mountOptions { "ro" }; - - auto r = Calamares::System::runCommand( Calamares::System::RunLocation::RunInHost, - { "blkid", "-s", "TYPE", "-o", "value", partitionPath } ); - if ( r.getExitCode() ) - { - cWarning() << "blkid on" << partitionPath << "failed."; - } - else - { - QString fstype = r.getOutput().trimmed(); - if ( ( fstype == "ext3" ) || ( fstype == "ext4" ) ) - { - mountOptions.append( "noload" ); - } - } - - cDebug() << "Checking device" << partitionPath << "for fstab (fs=" << r.getOutput() << ')'; - - FstabEntryList fstabEntries; - - Calamares::Partition::TemporaryMount mount( partitionPath, QString(), mountOptions.join( ',' ) ); - if ( mount.isValid() ) - { - QFile fstabFile( mount.path() + "/etc/fstab" ); - - if ( fstabFile.open( QIODevice::ReadOnly | QIODevice::Text ) ) - { - const QStringList fstabLines = QString::fromLocal8Bit( fstabFile.readAll() ).split( '\n' ); - - for ( const QString& rawLine : fstabLines ) - { - fstabEntries.append( FstabEntry::fromEtcFstab( rawLine ) ); - } - fstabFile.close(); - const int lineCount = fstabEntries.count(); - std::remove_if( - fstabEntries.begin(), fstabEntries.end(), []( const FstabEntry& x ) { return !x.isValid(); } ); - cDebug() << Logger::SubEntry << "got" << fstabEntries.count() << "fstab entries from" << lineCount - << "lines in" << fstabFile.fileName(); - } - else - { - cWarning() << "Could not read fstab from mounted fs"; - } - } - else - { - cWarning() << "Could not mount existing fs"; - } - - return fstabEntries; -} - -static QString -findPartitionPathForMountPoint( const FstabEntryList& fstab, const QString& mountPoint ) -{ - if ( fstab.isEmpty() ) - { - return QString(); - } - - for ( const FstabEntry& entry : fstab ) - { - if ( entry.mountPoint == mountPoint ) - { - QProcess readlink; - QString partPath; - - if ( entry.partitionNode.startsWith( "/dev" ) ) // plain dev node - { - partPath = entry.partitionNode; - } - else if ( entry.partitionNode.startsWith( "LABEL=" ) ) - { - partPath = entry.partitionNode.mid( 6 ); - partPath.remove( "\"" ); - partPath.replace( "\\040", "\\ " ); - partPath.prepend( "/dev/disk/by-label/" ); - } - else if ( entry.partitionNode.startsWith( "UUID=" ) ) - { - partPath = entry.partitionNode.mid( 5 ); - partPath.remove( "\"" ); - partPath = partPath.toLower(); - partPath.prepend( "/dev/disk/by-uuid/" ); - } - else if ( entry.partitionNode.startsWith( "PARTLABEL=" ) ) - { - partPath = entry.partitionNode.mid( 10 ); - partPath.remove( "\"" ); - partPath.replace( "\\040", "\\ " ); - partPath.prepend( "/dev/disk/by-partlabel/" ); - } - else if ( entry.partitionNode.startsWith( "PARTUUID=" ) ) - { - partPath = entry.partitionNode.mid( 9 ); - partPath.remove( "\"" ); - partPath = partPath.toLower(); - partPath.prepend( "/dev/disk/by-partuuid/" ); - } - - // At this point we either have /dev/sda1, or /dev/disk/by-something/... - - if ( partPath.startsWith( "/dev/disk/by-" ) ) // we got a fancy node - { - readlink.start( "readlink", { "-en", partPath } ); - if ( !readlink.waitForStarted( 1000 ) ) - { - return QString(); - } - if ( !readlink.waitForFinished( 1000 ) ) - { - return QString(); - } - if ( readlink.exitCode() != 0 || readlink.exitStatus() != QProcess::NormalExit ) - { - return QString(); - } - partPath = QString::fromLocal8Bit( readlink.readAllStandardOutput() ).trimmed(); - } - - return partPath; - } - } - - return QString(); -} - -OsproberEntryList -runOsprober( DeviceModel* dm ) -{ - Logger::Once o; - - QString osproberOutput; - QProcess osprober; - osprober.setProgram( "os-prober" ); - osprober.setProcessChannelMode( QProcess::SeparateChannels ); - osprober.start(); - if ( !osprober.waitForStarted() ) - { - cError() << "os-prober cannot start."; - } - else if ( !osprober.waitForFinished( 60000 ) ) - { - cError() << "os-prober timed out."; - } - else - { - osproberOutput.append( QString::fromLocal8Bit( osprober.readAllStandardOutput() ).trimmed() ); - } - - QStringList osproberCleanLines; - OsproberEntryList osproberEntries; - const auto lines = osproberOutput.split( '\n' ); - for ( const QString& line : lines ) - { - if ( !line.simplified().isEmpty() ) - { - QStringList lineColumns = line.split( ':' ); - QString prettyName; - if ( !lineColumns.value( 1 ).simplified().isEmpty() ) - { - prettyName = lineColumns.value( 1 ).simplified(); - } - else if ( !lineColumns.value( 2 ).simplified().isEmpty() ) - { - prettyName = lineColumns.value( 2 ).simplified(); - } - - QString file, path = lineColumns.value( 0 ).simplified(); - if ( !path.startsWith( "/dev/" ) ) //basic sanity check - { - continue; - } - - // strip extra file after device: /dev/name@/path/to/file - int index = path.indexOf( '@' ); - if ( index != -1 ) - { - file = path.right( path.length() - index - 1 ); - path = path.left( index ); - } - - FstabEntryList fstabEntries = lookForFstabEntries( path ); - QString homePath = findPartitionPathForMountPoint( fstabEntries, "/home" ); - - osproberEntries.append( { prettyName, - path, - file, - QString(), - canBeResized( dm, path, o ), - lineColumns, - fstabEntries, - homePath } ); - osproberCleanLines.append( line ); - } - } - - if ( osproberCleanLines.count() > 0 ) - { - cDebug() << o << "os-prober lines after cleanup:" << Logger::DebugList( osproberCleanLines ); - } - else - { - cDebug() << o << "os-prober gave no output."; - } - - Calamares::JobQueue::instance()->globalStorage()->insert( "osproberLines", osproberCleanLines ); - - return osproberEntries; -} - -bool -isArmSystem() -{ - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - return gs->contains( "armInstall" ) && gs->value( "armInstall" ).toBool(); -} - -bool -isEfiSystem() -{ - return isArmSystem() || QDir( "/sys/firmware/efi/efivars" ).exists(); -} - -bool -isEfiFilesystemSuitableType( const Partition* candidate ) -{ - auto type = candidate->fileSystem().type(); - - QT_WARNING_PUSH - QT_WARNING_DISABLE_CLANG( "-Wswitch-enum" ) - switch ( type ) - { - case FileSystem::Type::Fat32: - return true; - case FileSystem::Type::Fat12: - case FileSystem::Type::Fat16: - cWarning() << "FAT12 and FAT16 are probably not supported by EFI"; - return false; - default: - cWarning() << "EFI boot partition must be FAT32"; - return false; - } - QT_WARNING_POP -} - -bool -isEfiFilesystemRecommendedSize( const Partition* candidate ) -{ - auto size = candidate->capacity(); // bytes - if ( size <= 0 ) - { - return false; - } - - if ( size >= efiFilesystemRecommendedSize() ) - { - return true; - } - else - { - cWarning() << "Filesystem for EFI is smaller than recommended (" << size << "bytes)"; - return false; - } -} - -bool -isEfiFilesystemMinimumSize( const Partition* candidate ) -{ - using Calamares::Units::operator""_MiB; - - auto size = candidate->capacity(); // bytes - if ( size <= 0 ) - { - return false; - } - if ( size < efiSpecificationHardMinimumSize ) - { - return false; - } - - if ( size >= efiFilesystemMinimumSize() ) - { - return true; - } - else - { - cWarning() << "Filesystem for EFI is below minimum (" << size << "bytes)"; - return false; - } -} - -bool -isEfiBootable( const Partition* candidate ) -{ - const auto flags = PartitionInfo::flags( candidate ); - - // In KPMCore4, the flags are remapped, and the ESP flag is the same as Boot. - static_assert( KPM_PARTITION_FLAG_ESP == KPM_PARTITION_FLAG( Boot ), "KPMCore API enum changed" ); - return flags.testFlag( KPM_PARTITION_FLAG_ESP ); -} - -QString -efiFilesystemRecommendedSizeGSKey() -{ - return QStringLiteral( "efiSystemPartitionSize_i" ); -} - -qint64 -efiFilesystemRecommendedSize() -{ - const QString key = efiFilesystemRecommendedSizeGSKey(); - - qint64 uefisys_part_sizeB = 300_MiB; - - // The default can be overridden; the key used here comes - // from the partition module Config.cpp - auto* gs = Calamares::JobQueue::instance()->globalStorage(); - if ( gs->contains( key ) ) - { - qint64 v = gs->value( key ).toLongLong(); - uefisys_part_sizeB = v > 0 ? v : 0; - } - // There is a lower limit of what can be configured - if ( uefisys_part_sizeB < efiSpecificationHardMinimumSize ) - { - uefisys_part_sizeB = efiSpecificationHardMinimumSize; - } - return uefisys_part_sizeB; -} - -QString -efiFilesystemMinimumSizeGSKey() -{ - return QStringLiteral( "efiSystemPartitionMinimumSize_i" ); -} - -qint64 -efiFilesystemMinimumSize() -{ - const QString key = efiFilesystemMinimumSizeGSKey(); - - qint64 uefisys_part_sizeB = efiFilesystemRecommendedSize(); - - // The default can be overridden; the key used here comes - // from the partition module Config.cpp - auto* gs = Calamares::JobQueue::instance()->globalStorage(); - if ( gs->contains( key ) ) - { - qint64 v = gs->value( key ).toLongLong(); - uefisys_part_sizeB = v > 0 ? v : 0; - } - // There is a lower limit of what can be configured - if ( uefisys_part_sizeB < efiSpecificationHardMinimumSize ) - { - uefisys_part_sizeB = efiSpecificationHardMinimumSize; - } - return uefisys_part_sizeB; - return efiSpecificationHardMinimumSize; -} - -QString -canonicalFilesystemName( const QString& fsName, FileSystem::Type* fsType ) -{ - cScopedAssignment type( fsType ); - if ( fsName.isEmpty() ) - { - type = FileSystem::Ext4; - return QStringLiteral( "ext4" ); - } - - QStringList fsLanguage { QLatin1String( "C" ) }; // Required language list to turn off localization - - if ( ( type = FileSystem::typeForName( fsName, fsLanguage ) ) != FileSystem::Unknown ) - { - return fsName; - } - - // Second pass: try case-insensitive - const auto fstypes = FileSystem::types(); - for ( FileSystem::Type t : fstypes ) - { - if ( 0 == QString::compare( fsName, FileSystem::nameForType( t, fsLanguage ), Qt::CaseInsensitive ) ) - { - QString fsRealName = FileSystem::nameForType( t, fsLanguage ); - if ( fsType ) - { - *fsType = t; - } - return fsRealName; - } - } - - cWarning() << "Filesystem" << fsName << "not found, using ext4"; - // fsType can be used to check whether fsName was a valid filesystem. - if ( fsType ) - { - *fsType = FileSystem::Unknown; - } -#ifdef DEBUG_FILESYSTEMS - // This bit is for distro's debugging their settings, and shows - // all the strings that KPMCore is matching against for FS type. - { - Logger::CDebug d; - using TR = Logger::DebugRow< int, QString >; - const auto fstypes = FileSystem::types(); - d << "Available types (" << fstypes.count() << ')'; - for ( FileSystem::Type t : fstypes ) - { - d << TR( static_cast< int >( t ), FileSystem::nameForType( t, fsLanguage ) ); - } - } -#endif - type = FileSystem::Unknown; - return QStringLiteral( "ext4" ); -} - -} // namespace PartUtils - -/* Implementation of methods for FstabEntry, from OsproberEntry.h */ - -bool -FstabEntry::isValid() const -{ - return !partitionNode.isEmpty() && !mountPoint.isEmpty() && !fsType.isEmpty(); -} - -FstabEntry -FstabEntry::fromEtcFstab( const QString& rawLine ) -{ - QString line = rawLine.simplified(); - if ( line.startsWith( '#' ) ) - { - return FstabEntry { QString(), QString(), QString(), QString(), 0, 0 }; - } - - QStringList splitLine = line.split( ' ' ); - if ( splitLine.length() != 6 ) - { - return FstabEntry { QString(), QString(), QString(), QString(), 0, 0 }; - } - - return FstabEntry { - splitLine.at( 0 ), // path, or UUID, or LABEL, etc. - splitLine.at( 1 ), // mount point - splitLine.at( 2 ), // fs type - splitLine.at( 3 ), // options - splitLine.at( 4 ).toInt(), //dump - splitLine.at( 5 ).toInt() //pass - }; -} diff --git a/src/modules/partition/core/PartUtils.h b/src/modules/partition/core/PartUtils.h deleted file mode 100644 index 7813a98c47..0000000000 --- a/src/modules/partition/core/PartUtils.h +++ /dev/null @@ -1,154 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2018-2019 Adriaan de Groot - * SPDX-FileCopyrightText: 2019 Collabora Ltd - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef PARTUTILS_H -#define PARTUTILS_H - -#include "OsproberEntry.h" -#include "utils/NamedSuffix.h" -#include "utils/Units.h" - -// KPMcore -#include - -// Qt -#include - -class DeviceModel; -class Partition; -namespace Logger -{ -class Once; -} // namespace Logger - -namespace PartUtils -{ - -/** - * @brief Provides a nice human-readable name for @p candidate - * - * The most-specific human-readable name for the partition @p candidate - * is returned (e.g. device name, or partition path). In the worst - * case, a string representation of (void *)candidate is returned. - */ -QString convenienceName( const Partition* const candidate ); - -/** - * @brief canBeReplaced checks whether the given Partition satisfies the criteria - * for replacing it with the new OS. - * @param candidate the candidate partition to replace. - * @param o applied to debug-logging. - * @return true if the criteria are met, otherwise false. - */ -bool canBeReplaced( Partition* candidate, const Logger::Once& o ); - -/** - * @brief canBeReplaced checks whether the given Partition satisfies the criteria - * for resizing (shrinking) it to make room for a new OS. - * @param candidate the candidate partition to resize. - * @param o applied to debug-logging. - * @return true if the criteria are met, otherwise false. - */ -bool canBeResized( Partition* candidate, const Logger::Once& o ); - -/** - * @brief canBeReplaced checks whether the given Partition satisfies the criteria - * for resizing (shrinking) it to make room for a new OS. - * @param dm the DeviceModel instance. - * @param partitionPath the device path of the candidate partition to resize. - * @param o applied to debug-logging. - * @return true if the criteria are met, otherwise false. - */ -bool canBeResized( DeviceModel* dm, const QString& partitionPath, const Logger::Once& o ); - -/** - * @brief runOsprober executes os-prober, parses the output and writes relevant - * data to GlobalStorage. - * @param dm the DeviceModel instance. - * @return a list of os-prober entries, parsed. - */ -OsproberEntryList runOsprober( DeviceModel* dm ); - -/** - * @brief Is this an ARM-based system? Set in the configuration file - */ -bool isArmSystem(); - -/** - * @brief Is this system EFI-enabled? Decides based on /sys/firmware/efi - */ -bool isEfiSystem(); - -/** - * @brief Is the @p partition suitable as an EFI boot partition? - * Checks for filesystem type (FAT32). - */ -bool isEfiFilesystemSuitableType( const Partition* candidate ); - -/** - * @brief Is the @p partition suitable as an EFI boot partition? - * Checks for filesystem size (300MiB, see efi.recommendedSize). - */ -bool isEfiFilesystemRecommendedSize( const Partition* candidate ); - -/** - * @brief Is the @p candidate suitable as an EFI boot partition? - * Checks for filesystem size (32MiB at least, see efi.minimumSize). - */ -bool isEfiFilesystemMinimumSize( const Partition* candidate ); - -/** @brief Returns the minimum size of an EFI boot partition in bytes. - * - * This is determined as 300MiB, based on the FAT32 standard - * and EFI documentation (and not a little discussion in Calamares - * issues about what works, what is effective, and what is mandated - * by the standard and how all of those are different). - * - * This can be configured through the `partition.conf` file, - * key *efi.recommendedSize*, which will then apply to both - * automatic partitioning **and** the warning for manual partitioning. - * - * A minimum of 32MiB (which is bonkers-small) is enforced. - */ -qint64 efiFilesystemRecommendedSize(); - -// Helper for consistency: the GS key used to share the recommended size -QString efiFilesystemRecommendedSizeGSKey(); - -/** @brief Returns the hard-minimum size of an EFI boot partition in bytes. - * - * This is 32MiB, based on the FAT32 standard and EFI documentation. - */ -qint64 efiFilesystemMinimumSize(); - -// Helper for consistency: the GS key used to share the minimum size -QString efiFilesystemMinimumSizeGSKey(); - -/** - * @brief Is the given @p partition bootable in EFI? Depending on - * the partition table layout, this may mean different flags. - */ -bool isEfiBootable( const Partition* candidate ); - -/** @brief translate @p fsName into a recognized name and type - * - * Makes several attempts to translate the string into a - * name that KPMCore will recognize. Returns the canonical - * filesystem name (e.g. asking for "EXT4" will return "ext4"). - * - * The corresponding filesystem type is stored in @p fsType, and - * its value is FileSystem::Unknown if @p fsName is not recognized. - */ -QString canonicalFilesystemName( const QString& fsName, FileSystem::Type* fsType ); - -} // namespace PartUtils - -#endif // PARTUTILS_H diff --git a/src/modules/partition/core/PartitionActions.cpp b/src/modules/partition/core/PartitionActions.cpp deleted file mode 100644 index b5fb0cafb0..0000000000 --- a/src/modules/partition/core/PartitionActions.cpp +++ /dev/null @@ -1,258 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2017 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017-2019 Adriaan de Groot - * SPDX-FileCopyrightText: 2019 Collabora Ltd - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "PartitionActions.h" - -#include "core/KPMHelpers.h" -#include "core/PartUtils.h" -#include "core/PartitionCoreModule.h" -#include "core/PartitionInfo.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "utils/Logger.h" -#include "utils/NamedEnum.h" -#include "utils/System.h" -#include "utils/Units.h" - -#include -#include - -#include - -using namespace Calamares::Units; - -static quint64 -swapSuggestion( const quint64 availableSpaceB, Config::SwapChoice swap ) -{ - if ( ( swap != Config::SwapChoice::SmallSwap ) && ( swap != Config::SwapChoice::FullSwap ) ) - { - return 0; - } - - // See partition.conf for explanation - quint64 suggestedSwapSizeB = 0; - auto [ availableRamB, overestimationFactor ] = Calamares::System::instance()->getTotalMemoryB(); - - bool ensureSuspendToDisk = swap == Config::SwapChoice::FullSwap; - - // Ramp up quickly to 8GiB, then follow memory size - if ( availableRamB <= 4_GiB ) - { - suggestedSwapSizeB = availableRamB * 2; - } - else if ( availableRamB <= 8_GiB ) - { - suggestedSwapSizeB = 8_GiB; - } - else - { - suggestedSwapSizeB = availableRamB; - } - - // .. top out at 8GiB if we don't care about suspend - if ( !ensureSuspendToDisk ) - { - // TODO: make the _GiB operator return unsigned - suggestedSwapSizeB = qMin( quint64( 8_GiB ), suggestedSwapSizeB ); - } - - // Allow for a fudge factor - suggestedSwapSizeB = quint64( qRound64( qreal( suggestedSwapSizeB ) * overestimationFactor ) ); - - // don't use more than 10% of available space - if ( !ensureSuspendToDisk ) - { - suggestedSwapSizeB = qMin( suggestedSwapSizeB, availableSpaceB / 10 /* 10% is 0.1 */ ); - } - - // TODO: make Units functions work on unsigned - cDebug() << "Suggested swap size:" << Calamares::BytesToGiB( suggestedSwapSizeB ) << "GiB"; - - return suggestedSwapSizeB; -} - -namespace PartitionActions -{ - -void -doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionOptions o ) -{ - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - - const bool isEfi = PartUtils::isEfiSystem(); - - // Partition sizes are expressed in MiB, should be multiples of - // the logical sector size (usually 512B). EFI starts with 2MiB - // empty and a EFI boot partition, while BIOS starts at - // the 1MiB boundary (usually sector 2048). - // ARM empty sectors are 16 MiB in size. - const int empty_space_sizeB = PartUtils::isArmSystem() ? 16_MiB : ( isEfi ? 2_MiB : 1_MiB ); - - // Since sectors count from 0, if the space is 2048 sectors in size, - // the first free sector has number 2048 (and there are 2048 sectors - // before that one, numbered 0..2047). - qint64 firstFreeSector = Calamares::bytesToSectors( empty_space_sizeB, dev->logicalSize() ); - - PartitionTable::TableType partType = PartitionTable::nameToTableType( o.defaultPartitionTableType ); - if ( partType == PartitionTable::unknownTableType ) - { - partType = isEfi ? PartitionTable::gpt : PartitionTable::msdos; - } - - // Looking up the defaultFsType (which should name a filesystem type) - // will log an error and set the type to Unknown if there's something wrong. - FileSystem::Type type = FileSystem::Unknown; - PartUtils::canonicalFilesystemName( o.defaultFsType, &type ); - core->partitionLayout().setDefaultFsType( type == FileSystem::Unknown ? FileSystem::Ext4 : type ); - - core->createPartitionTable( dev, partType ); - - if ( isEfi ) - { - qint64 uefisys_part_sizeB = PartUtils::efiFilesystemRecommendedSize(); - qint64 efiSectorCount = Calamares::bytesToSectors( uefisys_part_sizeB, dev->logicalSize() ); - Q_ASSERT( efiSectorCount > 0 ); - - // Since sectors count from 0, and this partition is created starting - // at firstFreeSector, we need efiSectorCount sectors, numbered - // firstFreeSector..firstFreeSector+efiSectorCount-1. - qint64 lastSector = firstFreeSector + efiSectorCount - 1; - Partition* efiPartition = KPMHelpers::createNewPartition( dev->partitionTable(), - *dev, - PartitionRole( PartitionRole::Primary ), - FileSystem::Fat32, - QString(), - firstFreeSector, - lastSector, - KPM_PARTITION_FLAG( None ) ); - PartitionInfo::setFormat( efiPartition, true ); - PartitionInfo::setMountPoint( efiPartition, o.efiPartitionMountPoint ); - if ( gs->contains( "efiSystemPartitionName" ) ) - { - efiPartition->setLabel( gs->value( "efiSystemPartitionName" ).toString() ); - } - core->createPartition( dev, efiPartition, KPM_PARTITION_FLAG_ESP ); - firstFreeSector = lastSector + 1; - } - - const bool mayCreateSwap - = ( o.swap == Config::SwapChoice::SmallSwap ) || ( o.swap == Config::SwapChoice::FullSwap ); - bool shouldCreateSwap = false; - quint64 suggestedSwapSizeB = 0; - - const quint64 sectorSize = quint64( dev->logicalSize() ); - if ( mayCreateSwap ) - { - quint64 availableSpaceB = quint64( dev->totalLogical() - firstFreeSector ) * sectorSize; - suggestedSwapSizeB = swapSuggestion( availableSpaceB, o.swap ); - // Space required by this installation is what the distro claims is needed - // (via global configuration) plus the swap size plus a fudge factor of - // 0.6GiB (this was 2.1GiB up to Calamares 3.2.2). - quint64 requiredSpaceB = o.requiredSpaceB + 600_MiB + suggestedSwapSizeB; - - // If there is enough room for ESP + root + swap, create swap, otherwise don't. - shouldCreateSwap = availableSpaceB > requiredSpaceB; - } - - qint64 lastSectorForRoot = dev->totalLogical() - 1; //last sector of the device - if ( shouldCreateSwap ) - { - lastSectorForRoot -= suggestedSwapSizeB / sectorSize + 1; - } - - core->layoutApply( dev, firstFreeSector, lastSectorForRoot, o.luksFsType, o.luksPassphrase ); - - if ( shouldCreateSwap ) - { - Partition* swapPartition = nullptr; - if ( o.luksPassphrase.isEmpty() ) - { - swapPartition = KPMHelpers::createNewPartition( dev->partitionTable(), - *dev, - PartitionRole( PartitionRole::Primary ), - FileSystem::LinuxSwap, - QStringLiteral( "swap" ), - lastSectorForRoot + 1, - dev->totalLogical() - 1, - KPM_PARTITION_FLAG( None ) ); - } - else - { - swapPartition = KPMHelpers::createNewEncryptedPartition( dev->partitionTable(), - *dev, - PartitionRole( PartitionRole::Primary ), - FileSystem::LinuxSwap, - QStringLiteral( "swap" ), - lastSectorForRoot + 1, - dev->totalLogical() - 1, - o.luksFsType, - o.luksPassphrase, - KPM_PARTITION_FLAG( None ) ); - } - PartitionInfo::setFormat( swapPartition, true ); - if ( gs->contains( "swapPartitionName" ) ) - { - swapPartition->setLabel( gs->value( "swapPartitionName" ).toString() ); - } - core->createPartition( dev, swapPartition ); - } - - core->dumpQueue(); -} - -void -doReplacePartition( PartitionCoreModule* core, Device* dev, Partition* partition, Choices::ReplacePartitionOptions o ) -{ - qint64 firstSector, lastSector; - - cDebug() << "doReplacePartition for device" << partition->partitionPath(); - - // Looking up the defaultFsType (which should name a filesystem type) - // will log an error and set the type to Unknown if there's something wrong. - FileSystem::Type type = FileSystem::Unknown; - PartUtils::canonicalFilesystemName( o.defaultFsType, &type ); - core->partitionLayout().setDefaultFsType( type == FileSystem::Unknown ? FileSystem::Ext4 : type ); - - PartitionRole newRoles( partition->roles() ); - if ( partition->roles().has( PartitionRole::Extended ) ) - { - newRoles = PartitionRole( PartitionRole::Primary ); - } - - if ( partition->roles().has( PartitionRole::Unallocated ) ) - { - newRoles = PartitionRole( PartitionRole::Primary ); - cWarning() << "selected partition is free space"; - if ( partition->parent() ) - { - Partition* parent = dynamic_cast< Partition* >( partition->parent() ); - if ( parent && parent->roles().has( PartitionRole::Extended ) ) - { - newRoles = PartitionRole( PartitionRole::Logical ); - } - } - } - - // Save the first and last sector values as the partition will be deleted - firstSector = partition->firstSector(); - lastSector = partition->lastSector(); - if ( !partition->roles().has( PartitionRole::Unallocated ) ) - { - core->deletePartition( dev, partition ); - } - - core->layoutApply( dev, firstSector, lastSector, o.luksFsType, o.luksPassphrase ); - - core->dumpQueue(); -} - -} // namespace PartitionActions diff --git a/src/modules/partition/core/PartitionActions.h b/src/modules/partition/core/PartitionActions.h deleted file mode 100644 index fdf56e56e7..0000000000 --- a/src/modules/partition/core/PartitionActions.h +++ /dev/null @@ -1,95 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2016 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef PARTITIONACTIONS_H -#define PARTITIONACTIONS_H - -#include "Config.h" - -#include -#include - -class PartitionCoreModule; -class Device; -class Partition; - -namespace PartitionActions -{ -/** @brief Namespace for enums - * - * This namespace houses non-class enums..... - */ -namespace Choices -{ -struct ReplacePartitionOptions -{ - QString defaultPartitionTableType; // e.g. "gpt" or "msdos" - QString defaultFsType; // e.g. "ext4" or "btrfs" - Config::LuksGeneration luksFsType = Config::LuksGeneration::Luks1; // optional ("luks", "luks2") - QString luksPassphrase; // optional - - ReplacePartitionOptions( const QString& pt, - const QString& fs, - Config::LuksGeneration luksFs, - const QString& luksPassphrase ) - : defaultPartitionTableType( pt ) - , defaultFsType( fs ) - , luksFsType( luksFs ) - , luksPassphrase( luksPassphrase ) - { - } -}; - -struct AutoPartitionOptions : ReplacePartitionOptions -{ - QString efiPartitionMountPoint; // optional, e.g. "/boot" - quint64 requiredSpaceB; // estimated required space for root partition - Config::SwapChoice swap; - - AutoPartitionOptions( const QString& pt, - const QString& fs, - Config::LuksGeneration luksFs, - const QString& luksPassphrase, - const QString& efi, - qint64 requiredBytes, - Config::SwapChoice s ) - : ReplacePartitionOptions( pt, fs, luksFs, luksPassphrase ) - , efiPartitionMountPoint( efi ) - , requiredSpaceB( requiredBytes > 0 ? quint64( requiredBytes ) : 0U ) - , swap( s ) - { - } -}; - -} // namespace Choices - -/** - * @brief doAutopartition sets up an autopartitioning operation on the given Device. - * @param core a pointer to the PartitionCoreModule instance. - * @param dev the device to wipe. - * @param options settings for autopartitioning. - */ -void doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionOptions options ); - -/** - * @brief doReplacePartition sets up replace-partitioning with the given partition. - * @param core a pointer to the PartitionCoreModule instance. - * @param dev a pointer to the Device on which to replace a partition. - * @param partition a pointer to the Partition to be replaced. - * @param options settings for partitioning (not all fields apply) - * - * @note this function also takes care of requesting PCM to delete the partition. - */ -void doReplacePartition( PartitionCoreModule* core, - Device* dev, - Partition* partition, - Choices::ReplacePartitionOptions options ); -} // namespace PartitionActions - -#endif // PARTITIONACTIONS_H diff --git a/src/modules/partition/core/PartitionCoreModule.cpp b/src/modules/partition/core/PartitionCoreModule.cpp deleted file mode 100644 index 51e99f2d22..0000000000 --- a/src/modules/partition/core/PartitionCoreModule.cpp +++ /dev/null @@ -1,1223 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017-2019 Adriaan de Groot - * SPDX-FileCopyrightText: 2018 Caio Carvalho - * SPDX-FileCopyrightText: 2019 Collabora Ltd - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "core/PartitionCoreModule.h" - -#include "core/BootLoaderModel.h" -#include "core/ColorUtils.h" -#include "core/DeviceList.h" -#include "core/DeviceModel.h" -#include "core/KPMHelpers.h" -#include "core/PartUtils.h" -#include "core/PartitionInfo.h" -#include "core/PartitionModel.h" -#include "jobs/AutoMountManagementJob.h" -#include "jobs/ChangeFilesystemLabelJob.h" -#include "jobs/ClearMountsJob.h" -#include "jobs/ClearTempMountsJob.h" -#include "jobs/CreatePartitionJob.h" -#include "jobs/CreatePartitionTableJob.h" -#include "jobs/CreateVolumeGroupJob.h" -#include "jobs/DeactivateVolumeGroupJob.h" -#include "jobs/DeletePartitionJob.h" -#include "jobs/FillGlobalStorageJob.h" -#include "jobs/FormatPartitionJob.h" -#include "jobs/RemoveVolumeGroupJob.h" -#include "jobs/ResizePartitionJob.h" -#include "jobs/ResizeVolumeGroupJob.h" -#include "jobs/SetPartitionFlagsJob.h" - -#ifdef DEBUG_PARTITION_BAIL_OUT -#include "JobExample.h" -#endif -#include "partition/PartitionIterator.h" -#include "partition/PartitionQuery.h" -#include "utils/Logger.h" -#include "utils/Traits.h" -#include "utils/Variant.h" - -// KPMcore -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// Qt -#include -#include -#include -#include - -using Calamares::Partition::isPartitionFreeSpace; -using Calamares::Partition::isPartitionNew; -using Calamares::Partition::PartitionIterator; - -PartitionCoreModule::RefreshHelper::RefreshHelper( PartitionCoreModule* module ) - : m_module( module ) -{ -} - -PartitionCoreModule::RefreshHelper::~RefreshHelper() -{ - m_module->refreshAfterModelChange(); -} - -class OperationHelper -{ -public: - OperationHelper( PartitionModel* model, PartitionCoreModule* core ) - : m_coreHelper( core ) - , m_modelHelper( model ) - { - } - - OperationHelper( const OperationHelper& ) = delete; - OperationHelper& operator=( const OperationHelper& ) = delete; - -private: - // Keep these in order: first the model needs to finish, - // then refresh is called. Remember that destructors are - // called in *reverse* order of declaration in this class. - PartitionCoreModule::RefreshHelper m_coreHelper; - PartitionModel::ResetHelper m_modelHelper; -}; - - -//- DeviceInfo --------------------------------------------- -// Some jobs have an updatePreview some don't -DECLARE_HAS_METHOD( updatePreview ) - -template < typename Job > -void -updatePreview( Job* job, const std::true_type& ) -{ - job->updatePreview(); -} - -template < typename Job > -void -updatePreview( Job*, const std::false_type& ) -{ -} - -template < typename Job > -void -updatePreview( Job* job ) -{ - updatePreview( job, has_updatePreview< Job > {} ); -} - -/** - * Owns the Device, PartitionModel and the jobs - */ -struct PartitionCoreModule::DeviceInfo -{ - DeviceInfo( Device* ); - ~DeviceInfo(); - QScopedPointer< Device > device; - QScopedPointer< PartitionModel > partitionModel; - const QScopedPointer< Device > immutableDevice; - - // To check if LVM VGs are deactivated - bool isAvailable; - - void forgetChanges(); - bool isDirty() const; - - const Calamares::JobList& jobs() const { return m_jobs; } - - /** @brief Take the jobs of the given type that apply to @p partition - * - * Returns a job pointer to the job that has just been removed. - */ - template < typename Job > - Calamares::job_ptr takeJob( Partition* partition ) - { - for ( auto it = m_jobs.begin(); it != m_jobs.end(); ) - { - Job* job = qobject_cast< Job* >( it->data() ); - if ( job && job->partition() == partition ) - { - Calamares::job_ptr p = *it; - it = m_jobs.erase( it ); - return p; - } - else - { - ++it; - } - } - - return Calamares::job_ptr( nullptr ); - } - - /** @brief Take the jobs of any type that apply to @p partition */ - void takeJobs( Partition* partition ) - { - for ( auto it = m_jobs.begin(); it != m_jobs.end(); ) - { - PartitionJob* job = qobject_cast< PartitionJob* >( it->data() ); - if ( job && job->partition() == partition ) - { - it = m_jobs.erase( it ); - } - else - { - ++it; - } - } - } - - /** @brief Add a job of given type to the job list - */ - template < typename Job, typename... Args > - Calamares::Job* makeJob( Args... a ) - { - auto* job = new Job( device.get(), a... ); - updatePreview( job ); - m_jobs << Calamares::job_ptr( job ); - return job; - } - -private: - Calamares::JobList m_jobs; -}; - - -PartitionCoreModule::DeviceInfo::DeviceInfo( Device* _device ) - : device( _device ) - , partitionModel( new PartitionModel ) - , immutableDevice( new Device( *_device ) ) - , isAvailable( true ) -{ -} - -PartitionCoreModule::DeviceInfo::~DeviceInfo() {} - - -void -PartitionCoreModule::DeviceInfo::forgetChanges() -{ - m_jobs.clear(); - for ( auto it = PartitionIterator::begin( device.data() ); it != PartitionIterator::end( device.data() ); ++it ) - { - PartitionInfo::reset( *it ); - } - partitionModel->revert(); -} - - -bool -PartitionCoreModule::DeviceInfo::isDirty() const -{ - if ( !m_jobs.isEmpty() ) - { - return true; - } - - for ( auto it = PartitionIterator::begin( device.data() ); it != PartitionIterator::end( device.data() ); ++it ) - { - if ( PartitionInfo::isDirty( *it ) ) - { - return true; - } - } - - return false; -} - -//- PartitionCoreModule ------------------------------------ -PartitionCoreModule::PartitionCoreModule( QObject* parent ) - : QObject( parent ) - , m_deviceModel( new DeviceModel( this ) ) - , m_bootLoaderModel( new BootLoaderModel( this ) ) -{ - if ( !m_kpmcore ) - { - qFatal( "Failed to initialize KPMcore backend" ); - } -} - - -void -PartitionCoreModule::init() -{ - QMutexLocker locker( &m_revertMutex ); - doInit(); -} - - -void -PartitionCoreModule::doInit() -{ - FileSystemFactory::init(); - - using DeviceList = QList< Device* >; - DeviceList devices = PartUtils::getDevices( PartUtils::DeviceType::WritableOnly ); - - cDebug() << "LIST OF DETECTED DEVICES:"; - cDebug() << Logger::SubEntry << "node\tcapacity\tname\tprettyName"; - for ( auto device : devices ) - { - if ( device ) - { - // Gives ownership of the Device* to the DeviceInfo object - auto deviceInfo = new DeviceInfo( device ); - m_deviceInfos << deviceInfo; - cDebug() << Logger::SubEntry << device->deviceNode() << device->capacity() - << Logger::RedactedName( "DevName", device->name() ) - << Logger::RedactedName( "DevNamePretty", device->prettyName() ); - } - else - { - cDebug() << Logger::SubEntry << "(skipped null device)"; - } - } - cDebug() << Logger::SubEntry << devices.count() << "devices detected."; - m_deviceModel->init( devices ); - - // The following PartUtils::runOsprober call in turn calls PartUtils::canBeResized, - // which relies on a working DeviceModel. - m_osproberLines = PartUtils::runOsprober( this->deviceModel() ); - - // We perform a best effort of filling out filesystem UUIDs in m_osproberLines - // because we will need them later on in PartitionModel if partition paths - // change. - // It is a known fact that /dev/sda1-style device paths aren't persistent - // across reboots (and this doesn't affect us), but partition numbers can also - // change at runtime against our will just for shits and giggles. - // But why would that ever happen? What system could possibly be so poorly - // designed that it requires a partition path rearrangement at runtime? - // Logical partitions on an MSDOS disklabel of course. - // See DeletePartitionJob::updatePreview. - for ( auto deviceInfo : m_deviceInfos ) - { - for ( auto it = PartitionIterator::begin( deviceInfo->device.data() ); - it != PartitionIterator::end( deviceInfo->device.data() ); - ++it ) - { - Partition* partition = *it; - for ( auto jt = m_osproberLines.begin(); jt != m_osproberLines.end(); ++jt ) - { - if ( jt->path == partition->partitionPath() - && partition->fileSystem().supportGetUUID() != FileSystem::cmdSupportNone - && !partition->fileSystem().uuid().isEmpty() ) - { - jt->uuid = partition->fileSystem().uuid(); - } - } - } - } - - for ( auto deviceInfo : m_deviceInfos ) - { - deviceInfo->partitionModel->init( deviceInfo->device.data(), m_osproberLines ); - } - - DeviceList bootLoaderDevices; - - for ( DeviceList::Iterator it = devices.begin(); it != devices.end(); ++it ) - { - if ( ( *it )->type() != Device::Type::Disk_Device ) - { - cDebug() << "Ignoring device that is not Disk_Device to bootLoaderDevices list."; - continue; - } - else - { - bootLoaderDevices.append( *it ); - } - } - - m_bootLoaderModel->init( bootLoaderDevices ); - - scanForLVMPVs(); - - //FIXME: this should be removed in favor of - // proper KPM support for EFI - if ( PartUtils::isEfiSystem() ) - { - scanForEfiSystemPartitions(); - } -} - -PartitionCoreModule::~PartitionCoreModule() -{ - qDeleteAll( m_deviceInfos ); -} - -DeviceModel* -PartitionCoreModule::deviceModel() const -{ - return m_deviceModel; -} - -BootLoaderModel* -PartitionCoreModule::bootLoaderModel() const -{ - return m_bootLoaderModel; -} - -PartitionModel* -PartitionCoreModule::partitionModelForDevice( const Device* device ) const -{ - DeviceInfo* info = infoForDevice( device ); - Q_ASSERT( info ); - return info->partitionModel.data(); -} - - -Device* -PartitionCoreModule::immutableDeviceCopy( const Device* device ) -{ - Q_ASSERT( device ); - DeviceInfo* info = infoForDevice( device ); - if ( !info ) - { - return nullptr; - } - - return info->immutableDevice.data(); -} - - -void -PartitionCoreModule::createPartitionTable( Device* device, PartitionTable::TableType type ) -{ - auto* deviceInfo = infoForDevice( device ); - if ( deviceInfo ) - { - // Creating a partition table wipes all the disk, so there is no need to - // keep previous changes - deviceInfo->forgetChanges(); - - OperationHelper helper( partitionModelForDevice( device ), this ); - deviceInfo->makeJob< CreatePartitionTableJob >( type ); - } -} - -void -PartitionCoreModule::createPartition( Device* device, Partition* partition, PartitionTable::Flags flags ) -{ - auto* deviceInfo = infoForDevice( device ); - Q_ASSERT( deviceInfo ); - - OperationHelper helper( partitionModelForDevice( device ), this ); - deviceInfo->makeJob< CreatePartitionJob >( partition ); - - if ( flags != KPM_PARTITION_FLAG( None ) ) - { - deviceInfo->makeJob< SetPartFlagsJob >( partition, flags ); - PartitionInfo::setFlags( partition, flags ); - } -} - -void -PartitionCoreModule::createVolumeGroup( QString& vgName, QVector< const Partition* > pvList, qint32 peSize ) -{ - // Appending '_' character in case of repeated VG name - while ( hasVGwithThisName( vgName ) ) - { - vgName.append( '_' ); - } - - LvmDevice* device = new LvmDevice( vgName ); - for ( const Partition* p : pvList ) - { - device->physicalVolumes() << p; - } - - DeviceInfo* deviceInfo = new DeviceInfo( device ); - deviceInfo->partitionModel->init( device, osproberEntries() ); - m_deviceModel->addDevice( device ); - m_deviceInfos << deviceInfo; - - deviceInfo->makeJob< CreateVolumeGroupJob >( vgName, pvList, peSize ); - refreshAfterModelChange(); -} - -void -PartitionCoreModule::resizeVolumeGroup( LvmDevice* device, QVector< const Partition* >& pvList ) -{ - auto* deviceInfo = infoForDevice( device ); - Q_ASSERT( deviceInfo ); - deviceInfo->makeJob< ResizeVolumeGroupJob >( device, pvList ); - refreshAfterModelChange(); -} - -void -PartitionCoreModule::deactivateVolumeGroup( LvmDevice* device ) -{ - auto* deviceInfo = infoForDevice( device ); - Q_ASSERT( deviceInfo ); - - deviceInfo->isAvailable = false; - - // TODO: this leaks - DeactivateVolumeGroupJob* job = new DeactivateVolumeGroupJob( device ); - - // DeactivateVolumeGroupJob needs to be immediately called - job->exec(); - - refreshAfterModelChange(); -} - -void -PartitionCoreModule::removeVolumeGroup( LvmDevice* device ) -{ - auto* deviceInfo = infoForDevice( device ); - Q_ASSERT( deviceInfo ); - deviceInfo->makeJob< RemoveVolumeGroupJob >( device ); - refreshAfterModelChange(); -} - -void -PartitionCoreModule::deletePartition( Device* device, Partition* partition ) -{ - auto* deviceInfo = infoForDevice( device ); - Q_ASSERT( deviceInfo ); - - OperationHelper helper( partitionModelForDevice( device ), this ); - - if ( partition->roles().has( PartitionRole::Extended ) ) - { - // Delete all logical partitions first - // I am not sure if we can iterate on Partition::children() while - // deleting them, so let's play it safe and keep our own list. - QList< Partition* > lst; - for ( auto childPartition : partition->children() ) - { - if ( !isPartitionFreeSpace( childPartition ) ) - { - lst << childPartition; - } - } - - for ( auto childPartition : lst ) - { - deletePartition( device, childPartition ); - } - } - - if ( partition->state() == KPM_PARTITION_STATE( New ) ) - { - // Take all the SetPartFlagsJob from the list and delete them - do - { - auto job_ptr = deviceInfo->takeJob< SetPartFlagsJob >( partition ); - if ( job_ptr.data() ) - { - continue; - } - } while ( false ); - - - // Find matching CreatePartitionJob - auto job_ptr = deviceInfo->takeJob< CreatePartitionJob >( partition ); - if ( !job_ptr.data() ) - { - cDebug() << "Failed to find a CreatePartitionJob matching the partition to remove"; - return; - } - // Remove it - if ( !partition->parent()->remove( partition ) ) - { - cDebug() << "Failed to remove partition from preview"; - return; - } - - device->partitionTable()->updateUnallocated( *device ); - // The partition is no longer referenced by either a job or the device - // partition list, so we have to delete it - delete partition; - } - else - { - // Remove any PartitionJob on this partition - do - { - auto job_ptr = deviceInfo->takeJob< PartitionJob >( partition ); - if ( job_ptr.data() ) - { - continue; - } - } while ( false ); - - deviceInfo->makeJob< DeletePartitionJob >( partition ); - } -} - -void -PartitionCoreModule::formatPartition( Device* device, Partition* partition ) -{ - auto* deviceInfo = infoForDevice( device ); - Q_ASSERT( deviceInfo ); - OperationHelper helper( partitionModelForDevice( device ), this ); - deviceInfo->makeJob< FormatPartitionJob >( partition ); -} - -void -PartitionCoreModule::setFilesystemLabel( Device* device, Partition* partition, const QString& newLabel ) -{ - if ( newLabel == PartitionInfo::label( partition ) ) - { - return; - } - - auto deviceInfo = infoForDevice( device ); - Q_ASSERT( deviceInfo ); - - OperationHelper helper( partitionModelForDevice( device ), this ); - PartitionInfo::setLabel( partition, newLabel ); - deviceInfo->takeJob< ChangeFilesystemLabelJob >( partition ); - deviceInfo->makeJob< ChangeFilesystemLabelJob >( partition, newLabel ); -} - -void -PartitionCoreModule::resizePartition( Device* device, Partition* partition, qint64 first, qint64 last ) -{ - auto* deviceInfo = infoForDevice( device ); - Q_ASSERT( deviceInfo ); - OperationHelper helper( partitionModelForDevice( device ), this ); - deviceInfo->makeJob< ResizePartitionJob >( partition, first, last ); -} - -void -PartitionCoreModule::setPartitionFlags( Device* device, Partition* partition, PartitionTable::Flags flags ) -{ - auto* deviceInfo = infoForDevice( device ); - Q_ASSERT( deviceInfo ); - OperationHelper( partitionModelForDevice( device ), this ); - deviceInfo->makeJob< SetPartFlagsJob >( partition, flags ); - PartitionInfo::setFlags( partition, flags ); -} - -STATICTEST QStringList -findEssentialLVs( const QList< PartitionCoreModule::DeviceInfo* >& infos ) -{ - QStringList doNotClose; - cDebug() << "Checking LVM use on" << infos.count() << "devices"; - for ( const auto* info : infos ) - { - if ( info->device->type() != Device::Type::LVM_Device ) - { - continue; - } - - for ( const auto& j : qAsConst( info->jobs() ) ) - { - FormatPartitionJob* format = dynamic_cast< FormatPartitionJob* >( j.data() ); - if ( format ) - { - // device->deviceNode() is /dev/ - // partition()->partitionPath() is /dev// - const auto* partition = format->partition(); - const QString partPath = partition->partitionPath(); - const QString devicePath = info->device->deviceNode() + '/'; - const bool isLvm = partition->roles().has( PartitionRole::Lvm_Lv ); - if ( isLvm && partPath.startsWith( devicePath ) ) - { - cDebug() << Logger::SubEntry << partPath - << "is an essential LV filesystem=" << partition->fileSystem().type(); - QString lvName = partPath.right( partPath.length() - devicePath.length() ); - doNotClose.append( info->device->name() + '-' + lvName ); - } - } - } - } - return doNotClose; -} - -Calamares::JobList -PartitionCoreModule::jobs( const Config* config ) const -{ - Calamares::JobList lst; - QList< Device* > devices; - -#ifdef DEBUG_PARTITION_UNSAFE -#ifdef DEBUG_PARTITION_BAIL_OUT - cDebug() << "Unsafe partitioning is enabled."; - cDebug() << Logger::SubEntry << "it has been lamed, and will fail."; - lst << Calamares::job_ptr( new Calamares::FailJob( QStringLiteral( "Partition" ) ) ); -#else - cWarning() << "Unsafe partitioning is enabled."; - cWarning() << Logger::SubEntry << "the unsafe actions will be executed."; -#endif -#endif - - // The automountControl job goes in the list twice: the first - // time it runs, it disables automount and remembers the old setting - // for automount; the second time it restores that old setting. - Calamares::job_ptr automountControl( new AutoMountManagementJob( true /* disable automount */ ) ); - lst << automountControl; - lst << Calamares::job_ptr( new ClearTempMountsJob() ); - -#ifdef DEBUG_PARTITION_SKIP - cWarning() << "Partitioning actions are skipped."; -#else - const QStringList doNotClose = findEssentialLVs( m_deviceInfos ); - - for ( const auto* info : m_deviceInfos ) - { - if ( info->isDirty() ) - { - auto* job = new ClearMountsJob( info->device.data() ); - job->setMapperExceptions( doNotClose ); - lst << Calamares::job_ptr( job ); - } - } -#endif - - for ( const auto* info : m_deviceInfos ) - { -#ifdef DEBUG_PARTITION_SKIP - cWarning() << Logger::SubEntry << "Skipping jobs for" << info->device.data()->deviceNode(); -#else - lst << info->jobs(); -#endif - devices << info->device.data(); - } - lst << Calamares::job_ptr( new FillGlobalStorageJob( config, devices, m_bootLoaderInstallPath ) ); - lst << automountControl; - - return lst; -} - -bool -PartitionCoreModule::hasRootMountPoint() const -{ - return m_hasRootMountPoint; -} - -QList< Partition* > -PartitionCoreModule::efiSystemPartitions() const -{ - return m_efiSystemPartitions; -} - -QVector< const Partition* > -PartitionCoreModule::lvmPVs() const -{ - return m_lvmPVs; -} - -bool -PartitionCoreModule::hasVGwithThisName( const QString& name ) const -{ - auto condition = [ name ]( DeviceInfo* d ) - { return dynamic_cast< LvmDevice* >( d->device.data() ) && d->device.data()->name() == name; }; - - return std::find_if( m_deviceInfos.begin(), m_deviceInfos.end(), condition ) != m_deviceInfos.end(); -} - -bool -PartitionCoreModule::isInVG( const Partition* partition ) const -{ - auto condition = [ partition ]( DeviceInfo* d ) - { - LvmDevice* vg = dynamic_cast< LvmDevice* >( d->device.data() ); - return vg && vg->physicalVolumes().contains( partition ); - }; - - return std::find_if( m_deviceInfos.begin(), m_deviceInfos.end(), condition ) != m_deviceInfos.end(); -} - -void -PartitionCoreModule::dumpQueue() const -{ - cDebug() << "# Queue:"; - for ( auto info : m_deviceInfos ) - { - cDebug() << Logger::SubEntry << "## Device:" << info->device->deviceNode(); - for ( const auto& job : info->jobs() ) - { - cDebug() << Logger::SubEntry << "-" << job->metaObject()->className(); - } - } -} - - -const OsproberEntryList -PartitionCoreModule::osproberEntries() const -{ - return m_osproberLines; -} - -void -PartitionCoreModule::refreshPartition( Device* device, Partition* ) -{ - // Keep it simple for now: reset the model. This can be improved to cause - // the model to Q_EMIT dataChanged() for the affected row instead, avoiding - // the loss of the current selection. - auto model = partitionModelForDevice( device ); - Q_ASSERT( model ); - OperationHelper helper( model, this ); -} - -void -PartitionCoreModule::refreshAfterModelChange() -{ - updateHasRootMountPoint(); - updateIsDirty(); - m_bootLoaderModel->update(); - - scanForLVMPVs(); - - //FIXME: this should be removed in favor of - // proper KPM support for EFI - if ( PartUtils::isEfiSystem() ) - { - scanForEfiSystemPartitions(); - } -} - -void -PartitionCoreModule::updateHasRootMountPoint() -{ - bool oldValue = m_hasRootMountPoint; - m_hasRootMountPoint = findPartitionByMountPoint( "/" ); - - if ( oldValue != m_hasRootMountPoint ) - { - hasRootMountPointChanged( m_hasRootMountPoint ); - } -} - -void -PartitionCoreModule::updateIsDirty() -{ - bool oldValue = m_isDirty; - m_isDirty = false; - for ( auto info : m_deviceInfos ) - { - if ( info->isDirty() ) - { - m_isDirty = true; - break; - } - } - if ( oldValue != m_isDirty ) - { - isDirtyChanged( m_isDirty ); - } -} - -void -PartitionCoreModule::scanForEfiSystemPartitions() -{ - const bool wasEmpty = m_efiSystemPartitions.isEmpty(); - - m_efiSystemPartitions.clear(); - - QList< Device* > devices; - for ( int row = 0; row < deviceModel()->rowCount(); ++row ) - { - Device* device = deviceModel()->deviceForIndex( deviceModel()->index( row ) ); - devices.append( device ); - } - - QList< Partition* > efiSystemPartitions = Calamares::Partition::findPartitions( devices, PartUtils::isEfiBootable ); - - if ( efiSystemPartitions.isEmpty() ) - { - cWarning() << "system is EFI but no EFI system partitions found."; - } - else if ( wasEmpty ) - { - // But it isn't empty anymore, so whatever problem has been solved - cDebug() << "system is EFI and new EFI system partition has been found."; - } - - m_efiSystemPartitions = efiSystemPartitions; -} - -void -PartitionCoreModule::scanForLVMPVs() -{ - m_lvmPVs.clear(); - - QList< Device* > physicalDevices; - QList< LvmDevice* > vgDevices; - - for ( DeviceInfo* deviceInfo : m_deviceInfos ) - { - if ( deviceInfo->device.data()->type() == Device::Type::Disk_Device ) - { - physicalDevices << deviceInfo->device.data(); - } - else if ( deviceInfo->device.data()->type() == Device::Type::LVM_Device ) - { - LvmDevice* device = dynamic_cast< LvmDevice* >( deviceInfo->device.data() ); - - // Restoring physical volume list - device->physicalVolumes().clear(); - - vgDevices << device; - } - } - - VolumeManagerDevice::scanDevices( physicalDevices ); - for ( auto p : LVM::pvList::list() ) - { - m_lvmPVs << p.partition().data(); - - for ( LvmDevice* device : vgDevices ) - { - if ( p.vgName() == device->name() ) - { - // Adding scanned VG to PV list - device->physicalVolumes() << p.partition(); - break; - } - } - } - - for ( DeviceInfo* d : m_deviceInfos ) - { - for ( const auto& job : d->jobs() ) - { - // Including new LVM PVs - CreatePartitionJob* partJob = dynamic_cast< CreatePartitionJob* >( job.data() ); - if ( partJob ) - { - Partition* p = partJob->partition(); - - if ( p->fileSystem().type() == FileSystem::Type::Lvm2_PV ) - { - m_lvmPVs << p; - } - else if ( p->fileSystem().type() == FileSystem::Type::Luks ) - { - // Encrypted LVM PVs - FileSystem* innerFS = static_cast< const FS::luks* >( &p->fileSystem() )->innerFS(); - - if ( innerFS && innerFS->type() == FileSystem::Type::Lvm2_PV ) - { - m_lvmPVs << p; - } - } - else if ( p->fileSystem().type() == FileSystem::Type::Luks2 ) - { - // Encrypted LVM PVs - FileSystem* innerFS = static_cast< const FS::luks* >( &p->fileSystem() )->innerFS(); - - if ( innerFS && innerFS->type() == FileSystem::Type::Lvm2_PV ) - { - m_lvmPVs << p; - } - } - } - } - } -} - -PartitionCoreModule::DeviceInfo* -PartitionCoreModule::infoForDevice( const Device* device ) const -{ - for ( auto it = m_deviceInfos.constBegin(); it != m_deviceInfos.constEnd(); ++it ) - { - if ( ( *it )->device.data() == device ) - { - return *it; - } - if ( ( *it )->immutableDevice.data() == device ) - { - return *it; - } - } - return nullptr; -} - -Partition* -PartitionCoreModule::findPartitionByMountPoint( const QString& mountPoint ) const -{ - for ( auto deviceInfo : m_deviceInfos ) - { - Device* device = deviceInfo->device.data(); - for ( auto it = PartitionIterator::begin( device ); it != PartitionIterator::end( device ); ++it ) - { - if ( PartitionInfo::mountPoint( *it ) == mountPoint ) - { - return *it; - } - } - } - return nullptr; -} - -void -PartitionCoreModule::setBootLoaderInstallPath( const QString& path ) -{ - cDebug() << "PCM::setBootLoaderInstallPath" << path; - m_bootLoaderInstallPath = path; -} - -static void -applyDefaultLabel( Partition* p, bool ( *predicate )( const Partition* ), const QString& label ) -{ - if ( p->label().isEmpty() && predicate( p ) ) - { - p->setLabel( label ); - } -} - -void -PartitionCoreModule::layoutApply( Device* dev, - qint64 firstSector, - qint64 lastSector, - Config::LuksGeneration luksFsType, - QString luksPassphrase, - PartitionNode* parent, - const PartitionRole& role ) -{ - const bool isEfi = PartUtils::isEfiSystem(); - QList< Partition* > partList - = m_partLayout.createPartitions( dev, firstSector, lastSector, luksFsType, luksPassphrase, parent, role ); - - // Partition::mountPoint() tells us where it is mounted **now**, while - // PartitionInfo::mountPoint() says where it will be mounted in the target system. - // .. the latter is more interesting. - // - // If we have a separate /boot, mark that one as bootable, - // otherwise mark the root / as bootable. - // - // If the layout hasn't applied a label to the partition, - // apply a default label (to boot and root, at least). - const auto is_boot = []( const Partition* p ) -> bool - { - const QString boot = QStringLiteral( "/boot" ); - return PartitionInfo::mountPoint( p ) == boot || p->mountPoint() == boot; - }; - const auto is_root = []( const Partition* p ) -> bool - { - const QString root = QStringLiteral( "/" ); - return PartitionInfo::mountPoint( p ) == root || p->mountPoint() == root; - }; - - const bool separate_boot_partition - = std::find_if( partList.constBegin(), partList.constEnd(), is_boot ) != partList.constEnd(); - for ( Partition* part : partList ) - { - applyDefaultLabel( part, is_root, QStringLiteral( "root" ) ); - applyDefaultLabel( part, is_boot, QStringLiteral( "boot" ) ); - if ( ( separate_boot_partition && is_boot( part ) ) || ( !separate_boot_partition && is_root( part ) ) ) - { - createPartition( - dev, part, part->activeFlags() | ( isEfi ? KPM_PARTITION_FLAG( None ) : KPM_PARTITION_FLAG( Boot ) ) ); - } - else - { - createPartition( dev, part ); - } - } -} - -void -PartitionCoreModule::layoutApply( Device* dev, - qint64 firstSector, - qint64 lastSector, - Config::LuksGeneration luksFsType, - QString luksPassphrase ) -{ - layoutApply( dev, - firstSector, - lastSector, - luksFsType, - luksPassphrase, - dev->partitionTable(), - PartitionRole( PartitionRole::Primary ) ); -} - -void -PartitionCoreModule::revert() -{ - QMutexLocker locker( &m_revertMutex ); - qDeleteAll( m_deviceInfos ); - m_deviceInfos.clear(); - doInit(); - updateIsDirty(); - Q_EMIT reverted(); -} - - -void -PartitionCoreModule::revertAllDevices() -{ - for ( auto it = m_deviceInfos.begin(); it != m_deviceInfos.end(); ) - { - // In new VGs device info, there will be always a CreateVolumeGroupJob as the first job in jobs list - if ( dynamic_cast< LvmDevice* >( ( *it )->device.data() ) ) - { - ( *it )->isAvailable = true; - - if ( !( *it )->jobs().empty() ) - { - CreateVolumeGroupJob* vgJob = dynamic_cast< CreateVolumeGroupJob* >( ( *it )->jobs().first().data() ); - - if ( vgJob ) - { - vgJob->undoPreview(); - - ( *it )->forgetChanges(); - - m_deviceModel->removeDevice( ( *it )->device.data() ); - - it = m_deviceInfos.erase( it ); - - continue; - } - } - } - - revertDevice( ( *it )->device.data(), false ); - ++it; - } - - refreshAfterModelChange(); -} - - -void -PartitionCoreModule::revertDevice( Device* dev, bool individualRevert ) -{ - QMutexLocker locker( &m_revertMutex ); - DeviceInfo* devInfo = infoForDevice( dev ); - - if ( !devInfo ) - { - return; - } - devInfo->forgetChanges(); - CoreBackend* backend = CoreBackendManager::self()->backend(); - Device* newDev = backend->scanDevice( devInfo->device->deviceNode() ); - devInfo->device.reset( newDev ); - devInfo->partitionModel->init( newDev, m_osproberLines ); - - m_deviceModel->swapDevice( dev, newDev ); - - QList< Device* > devices; - for ( DeviceInfo* const info : m_deviceInfos ) - { - if ( info && !info->device.isNull() && info->device->type() == Device::Type::Disk_Device ) - { - devices.append( info->device.data() ); - } - } - - m_bootLoaderModel->init( devices ); - - if ( individualRevert ) - { - refreshAfterModelChange(); - } - Q_EMIT deviceReverted( newDev ); -} - - -void -PartitionCoreModule::asyncRevertDevice( Device* dev, std::function< void() > callback ) -{ - QFutureWatcher< void >* watcher = new QFutureWatcher< void >(); - connect( watcher, - &QFutureWatcher< void >::finished, - this, - [ watcher, callback ] - { - callback(); - watcher->deleteLater(); - } ); - -#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) - QFuture< void > future = QtConcurrent::run( this, &PartitionCoreModule::revertDevice, dev, true ); -#else - QFuture< void > future = QtConcurrent::run( &PartitionCoreModule::revertDevice, this, dev, true ); -#endif - watcher->setFuture( future ); -} - - -void -PartitionCoreModule::clearJobs() -{ - foreach ( DeviceInfo* deviceInfo, m_deviceInfos ) - { - deviceInfo->forgetChanges(); - } - updateIsDirty(); -} - -void -PartitionCoreModule::clearJobs( Device* device, Partition* partition ) -{ - DeviceInfo* devInfo = infoForDevice( device ); - - if ( devInfo ) - { - devInfo->takeJobs( partition ); - } -} - - -bool -PartitionCoreModule::isDirty() -{ - return m_isDirty; -} - -bool -PartitionCoreModule::isVGdeactivated( LvmDevice* device ) -{ - for ( DeviceInfo* deviceInfo : m_deviceInfos ) - { - if ( device == deviceInfo->device.data() && !deviceInfo->isAvailable ) - { - return true; - } - } - - return false; -} - -QList< PartitionCoreModule::SummaryInfo > -PartitionCoreModule::createSummaryInfo() const -{ - QList< SummaryInfo > lst; - for ( auto deviceInfo : m_deviceInfos ) - { - if ( !deviceInfo->isDirty() ) - { - continue; - } - SummaryInfo summaryInfo; - summaryInfo.deviceName = deviceInfo->device->name(); - summaryInfo.deviceNode = deviceInfo->device->deviceNode(); - - Device* deviceBefore = deviceInfo->immutableDevice.data(); - summaryInfo.partitionModelBefore = new PartitionModel; - summaryInfo.partitionModelBefore->init( deviceBefore, m_osproberLines ); - // Make deviceBefore a child of partitionModelBefore so that it is not - // leaked (as long as partitionModelBefore is deleted) - deviceBefore->setParent( summaryInfo.partitionModelBefore ); - - summaryInfo.partitionModelAfter = new PartitionModel; - summaryInfo.partitionModelAfter->init( deviceInfo->device.data(), m_osproberLines ); - - lst << summaryInfo; - } - return lst; -} diff --git a/src/modules/partition/core/PartitionCoreModule.h b/src/modules/partition/core/PartitionCoreModule.h deleted file mode 100644 index 40a1916a9c..0000000000 --- a/src/modules/partition/core/PartitionCoreModule.h +++ /dev/null @@ -1,279 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2014-2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef PARTITIONCOREMODULE_H -#define PARTITIONCOREMODULE_H - -#include "Config.h" -#include "core/KPMHelpers.h" -#include "core/PartitionLayout.h" -#include "core/PartitionModel.h" -#include "jobs/PartitionJob.h" - -#include "Job.h" -#include "partition/KPMManager.h" - -// KPMcore -#include -#include - -// Qt -#include -#include -#include - -#include - -class BootLoaderModel; -class Config; -class CreatePartitionJob; -class Device; -class DeviceModel; -class FileSystem; -class Partition; - -class QStandardItemModel; - -/** - * The core of the module. - * - * It has two responsibilities: - * - Listing the devices and partitions, creating Qt models for them. - * - Creating jobs for any changes requested by the user interface. - */ -class PartitionCoreModule : public QObject -{ - Q_OBJECT -public: - /** - * This helper class calls refresh() on the module - * on destruction (nothing else). It is used as - * part of the model-consistency objects, along with - * PartitionModel::ResetHelper. - */ - class RefreshHelper - { - public: - RefreshHelper( PartitionCoreModule* module ); - ~RefreshHelper(); - - RefreshHelper( const RefreshHelper& ) = delete; - RefreshHelper& operator=( const RefreshHelper& ) = delete; - - private: - PartitionCoreModule* m_module; - }; - - /** - * @brief The SummaryInfo struct is a wrapper for PartitionModel instances for - * a given Device. - * Each Device gets a mutable "after" model and an immutable "before" model. - */ - struct SummaryInfo - { - QString deviceName; - QString deviceNode; - PartitionModel* partitionModelBefore; - PartitionModel* partitionModelAfter; - }; - - struct DeviceInfo; - - PartitionCoreModule( QObject* parent = nullptr ); - ~PartitionCoreModule() override; - - /** - * @brief init performs a devices scan and initializes all KPMcore data - * structures. - * This function is thread safe. - */ - void init(); - - /** - * @brief deviceModel returns a model which exposes a list of available - * storage devices. - * @return the device model. - */ - DeviceModel* deviceModel() const; - - /** - * @brief partitionModelForDevice returns the PartitionModel for the given device. - * @param device the device for which to get a model. - * @return a PartitionModel which represents the partitions of a device. - */ - PartitionModel* partitionModelForDevice( const Device* device ) const; - - //HACK: all devices change over time, and together make up the state of the CoreModule. - // However this makes it hard to show the *original* state of a device. - // For each DeviceInfo we keep a second Device object that contains the - // current state of a disk regardless of subsequent changes. - // -- Teo 4/2015 - //FIXME: make this horrible method private. -- Teo 12/2015 - Device* immutableDeviceCopy( const Device* device ); - - /** - * @brief bootLoaderModel returns a model which represents the available boot - * loader locations. - * The single BootLoaderModel instance belongs to the PCM. - * @return the BootLoaderModel. - */ - BootLoaderModel* bootLoaderModel() const; - - void createPartitionTable( Device* device, PartitionTable::TableType type ); - - /** - * @brief Add a job to do the actual partition-creation. - * - * If @p flags is not FlagNone, then the given flags are - * applied to the newly-created partition. - */ - void - createPartition( Device* device, Partition* partition, PartitionTable::Flags flags = KPM_PARTITION_FLAG( None ) ); - - void createVolumeGroup( QString& vgName, QVector< const Partition* > pvList, qint32 peSize ); - - void resizeVolumeGroup( LvmDevice* device, QVector< const Partition* >& pvList ); - - void deactivateVolumeGroup( LvmDevice* device ); - - void removeVolumeGroup( LvmDevice* device ); - - void deletePartition( Device* device, Partition* partition ); - - void formatPartition( Device* device, Partition* partition ); - - void setFilesystemLabel( Device* device, Partition* partition, const QString& newLabel ); - - void resizePartition( Device* device, Partition* partition, qint64 first, qint64 last ); - - void setPartitionFlags( Device* device, Partition* partition, PartitionTable::Flags flags ); - - /// @brief Retrieve the path where the bootloader will be installed - QString bootLoaderInstallPath() const { return m_bootLoaderInstallPath; } - /// @brief Set the path where the bootloader will be installed - void setBootLoaderInstallPath( const QString& path ); - - /** @brief Get the partition layout that will be applied. - * - * Layouts are applied only for erase and replace operations. - */ - PartitionLayout& partitionLayout() { return m_partLayout; } - - void layoutApply( Device* dev, - qint64 firstSector, - qint64 lastSector, - Config::LuksGeneration luksFsType, - QString luksPassphrase ); - void layoutApply( Device* dev, - qint64 firstSector, - qint64 lastSector, - Config::LuksGeneration luksFsType, - QString luksPassphrase, - PartitionNode* parent, - const PartitionRole& role ); - - /** - * @brief jobs creates and returns a list of jobs which can then apply the changes - * requested by the user. - * @return a list of jobs. - */ - Calamares::JobList jobs( const Config* ) const; - - bool hasRootMountPoint() const; - - QList< Partition* > efiSystemPartitions() const; - - QVector< const Partition* > lvmPVs() const; - - bool hasVGwithThisName( const QString& name ) const; - - bool isInVG( const Partition* partition ) const; - - /** - * @brief findPartitionByMountPoint returns a Partition* for a given mount point. - * @param mountPoint the mount point to find a partition for. - * @return a pointer to a Partition object. - * Note that this function looks for partitions in live devices (the "proposed" - * state), not the immutable copies. Comparisons with Partition* objects that - * refer to immutable Device*s will fail. - */ - Partition* findPartitionByMountPoint( const QString& mountPoint ) const; - - void revert(); // full revert, thread safe, calls doInit - void revertAllDevices(); // convenience function, calls revertDevice - /** @brief rescans a single Device and updates DeviceInfo - * - * When @p individualRevert is true, calls refreshAfterModelChange(), - * used to reduce number of refreshes when calling revertAllDevices(). - */ - void revertDevice( Device* dev, bool individualRevert = true ); - void asyncRevertDevice( Device* dev, std::function< void() > callback ); //like revertDevice, but asynchronous - - void clearJobs(); // only clear jobs, the Device* states are preserved - void clearJobs( Device* device, Partition* partition ); // clears all jobs changing @p partition - - bool isDirty(); // true if there are pending changes, otherwise false - - bool isVGdeactivated( LvmDevice* device ); - - /** - * To be called when a partition has been altered, but only for changes - * which do not affect its size, because changes which affect the partition size - * affect the size of other partitions as well. - */ - void refreshPartition( Device* device, Partition* partition ); - - /** - * Returns a list of SummaryInfo for devices which have pending changes. - * Caller is responsible for deleting the partition models - */ - QList< SummaryInfo > createSummaryInfo() const; - - const OsproberEntryList osproberEntries() const; // os-prober data structure, cached - - void dumpQueue() const; // debug output - -Q_SIGNALS: - void hasRootMountPointChanged( bool value ); - void isDirtyChanged( bool value ); - void reverted(); - void deviceReverted( Device* device ); - -private: - void refreshAfterModelChange(); - - void doInit(); - void updateHasRootMountPoint(); - void updateIsDirty(); - void scanForEfiSystemPartitions(); - void scanForLVMPVs(); - - DeviceInfo* infoForDevice( const Device* ) const; - - Calamares::Partition::KPMManager m_kpmcore; - - QList< DeviceInfo* > m_deviceInfos; - QList< Partition* > m_efiSystemPartitions; - QVector< const Partition* > m_lvmPVs; - - DeviceModel* m_deviceModel; - BootLoaderModel* m_bootLoaderModel; - bool m_hasRootMountPoint = false; - bool m_isDirty = false; - QString m_bootLoaderInstallPath; - PartitionLayout m_partLayout; - - OsproberEntryList m_osproberLines; - - QMutex m_revertMutex; -}; - -#endif /* PARTITIONCOREMODULE_H */ diff --git a/src/modules/partition/core/PartitionInfo.cpp b/src/modules/partition/core/PartitionInfo.cpp deleted file mode 100644 index 708c6f3a0d..0000000000 --- a/src/modules/partition/core/PartitionInfo.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "core/PartitionInfo.h" -#include "compat/Variant.h" - -// KPMcore -#include -#include -#include - -// Qt -#include - -namespace PartitionInfo -{ - -static const char MOUNT_POINT_PROPERTY[] = "_calamares_mountPoint"; -static const char FORMAT_PROPERTY[] = "_calamares_format"; -static const char FLAGS_PROPERTY[] = "_calamares_flags"; -static const char LABEL_PROPERTY[] = "_calamares_label"; - -QString -mountPoint( const Partition* partition ) -{ - return partition->property( MOUNT_POINT_PROPERTY ).toString(); -} - -void -setMountPoint( Partition* partition, const QString& value ) -{ - partition->setProperty( MOUNT_POINT_PROPERTY, value ); -} - -bool -format( const Partition* partition ) -{ - return partition->property( FORMAT_PROPERTY ).toBool(); -} - -void -setFormat( Partition* partition, bool value ) -{ - partition->setProperty( FORMAT_PROPERTY, value ); -} - -PartitionTable::Flags -flags( const Partition* partition ) -{ - auto v = partition->property( FLAGS_PROPERTY ); - if ( !v.isValid() ) - { - return partition->activeFlags(); - } - // The underlying type of PartitionTable::Flags can be int or uint - // (see qflags.h) and so setting those flags can create a QVariant - // of those types; we don't just want to check QVariant::canConvert() - // here because that will also accept QByteArray and some other things. - if ( Calamares::typeOf( v ) == Calamares::IntVariantType || Calamares::typeOf( v ) == Calamares::UIntVariantType ) - { - return static_cast< PartitionTable::Flags >( v.toInt() ); - } - return partition->activeFlags(); -} - -void -setFlags( Partition* partition, PartitionTable::Flags f ) -{ - partition->setProperty( FLAGS_PROPERTY, PartitionTable::Flags::Int( f ) ); -} - -QString -label( const Partition* partition ) -{ - auto v = partition->property( LABEL_PROPERTY ); - if ( !v.isValid() ) - { - return partition->fileSystem().label(); - } - return v.toString(); -} - -void -setLabel( Partition* partition, const QString& value ) -{ - partition->setProperty( LABEL_PROPERTY, value ); -} - - -void -reset( Partition* partition ) -{ - // Setting a property to an invalid QVariant is equal to removing it - partition->setProperty( MOUNT_POINT_PROPERTY, QVariant() ); - partition->setProperty( FORMAT_PROPERTY, QVariant() ); - partition->setProperty( FLAGS_PROPERTY, QVariant() ); - partition->setProperty( LABEL_PROPERTY, QVariant() ); -} - -bool -isDirty( Partition* partition ) -{ - if ( LvmDevice::s_DirtyPVs.contains( partition ) ) - { - return true; - } - - return !mountPoint( partition ).isEmpty() || format( partition ) || flags( partition ) != partition->activeFlags(); -} - -} // namespace PartitionInfo diff --git a/src/modules/partition/core/PartitionInfo.h b/src/modules/partition/core/PartitionInfo.h deleted file mode 100644 index b4368f0f58..0000000000 --- a/src/modules/partition/core/PartitionInfo.h +++ /dev/null @@ -1,62 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ -#ifndef PARTITIONINFO_H -#define PARTITIONINFO_H - -#include -#include - -#include - -class Partition; - -/** - * Functions to store Calamares-specific information in the Qt properties of a - * Partition object. - * - * See README.md for the rationale behind this design. Roughly, these - * functions access **intent** while the existing Partition methods - * access current state. - * - * Properties: - * - mountPoint: which directory will a partition be mounted on the installed - * system. This is different from Partition::mountPoint, which is the - * directory on which a partition is *currently* mounted while the installer - * is running. - * - format: whether this partition should be formatted at install time. - * - label: label to apply to the filesystem in the partition - */ -namespace PartitionInfo -{ - -QString mountPoint( const Partition* partition ); -void setMountPoint( Partition* partition, const QString& value ); - -bool format( const Partition* partition ); -void setFormat( Partition* partition, bool value ); - -PartitionTable::Flags flags( const Partition* partition ); -void setFlags( Partition* partition, PartitionTable::Flags f ); - -QString label( const Partition* partition ); -void setLabel( Partition* partition, const QString& value ); - -void reset( Partition* partition ); - -/** - * Returns true if one of the property has been set. This information is used - * by the UI to decide whether the "Revert" button should be enabled or - * disabled. - */ -bool isDirty( Partition* partition ); - -} // namespace PartitionInfo - -#endif /* PARTITIONINFO_H */ diff --git a/src/modules/partition/core/PartitionLayout.cpp b/src/modules/partition/core/PartitionLayout.cpp deleted file mode 100644 index b476a3181a..0000000000 --- a/src/modules/partition/core/PartitionLayout.cpp +++ /dev/null @@ -1,378 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2017 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017-2018 Adriaan de Groot - * SPDX-FileCopyrightText: 2018-2019 Collabora Ltd - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "GlobalStorage.h" -#include "JobQueue.h" - -#include "utils/Logger.h" - -#include "core/PartitionLayout.h" - -#include "core/KPMHelpers.h" -#include "core/PartUtils.h" -#include "core/PartitionActions.h" -#include "core/PartitionInfo.h" - -#include "utils/Variant.h" - -#include -#include -#include - -PartitionLayout::PartitionLayout() {} - -PartitionLayout::PartitionLayout( const PartitionLayout& layout ) - : m_partLayout( layout.m_partLayout ) -{ -} - -PartitionLayout::~PartitionLayout() {} - -PartitionLayout::PartitionEntry::PartitionEntry() - : partAttributes( 0 ) -{ -} - -PartitionLayout::PartitionEntry::PartitionEntry( FileSystem::Type fs, - const QString& mountPoint, - const QString& size, - const QString& minSize, - const QString& maxSize ) - : partAttributes( 0 ) - , partMountPoint( mountPoint ) - , partFileSystem( fs ) - , partSize( size ) - , partMinSize( minSize ) - , partMaxSize( maxSize ) -{ -} - -PartitionLayout::PartitionEntry::PartitionEntry( const QString& label, - const QString& uuid, - const QString& type, - quint64 attributes, - const QString& mountPoint, - const QString& fs, - const bool& noEncrypt, - const QVariantMap& features, - const QString& size, - const QString& minSize, - const QString& maxSize ) - : partLabel( label ) - , partUUID( uuid ) - , partType( type ) - , partAttributes( attributes ) - , partMountPoint( mountPoint ) - , partNoEncrypt( noEncrypt ) - , partFeatures( features ) - , partSize( size ) - , partMinSize( minSize ) - , partMaxSize( maxSize ) -{ - PartUtils::canonicalFilesystemName( fs, &partFileSystem ); -} - -bool -PartitionLayout::addEntry( const PartitionEntry& entry ) -{ - if ( !entry.isValid() ) - { - return false; - } - - m_partLayout.append( entry ); - - return true; -} - -void -PartitionLayout::init( FileSystem::Type defaultFsType, const QVariantList& config ) -{ - bool ok = true; // bogus argument to getSubMap() - - m_partLayout.clear(); - - for ( const auto& r : config ) - { - QVariantMap pentry = r.toMap(); - - if ( !pentry.contains( "name" ) || !pentry.contains( "size" ) ) - { - cError() << "Partition layout entry #" << config.indexOf( r ) - << "lacks mandatory attributes, switching to default layout."; - m_partLayout.clear(); - break; - } - - if ( !addEntry( { Calamares::getString( pentry, "name" ), - Calamares::getString( pentry, "uuid" ), - Calamares::getString( pentry, "type" ), - Calamares::getUnsignedInteger( pentry, "attributes", 0 ), - Calamares::getString( pentry, "mountPoint" ), - Calamares::getString( pentry, "filesystem", "unformatted" ), - Calamares::getBool( pentry, "noEncrypt", false ), - Calamares::getSubMap( pentry, "features", ok ), - Calamares::getString( pentry, "size", QStringLiteral( "0" ) ), - Calamares::getString( pentry, "minSize", QStringLiteral( "0" ) ), - Calamares::getString( pentry, "maxSize", QStringLiteral( "0" ) ) } ) ) - { - cError() << "Partition layout entry #" << config.indexOf( r ) << "is invalid, switching to default layout."; - m_partLayout.clear(); - break; - } - } - - if ( !m_partLayout.count() ) - { - // Unknown will be translated to defaultFsType at apply-time - addEntry( { FileSystem::Type::Unknown, QString( "/" ), QString( "100%" ) } ); - } - - setDefaultFsType( defaultFsType ); -} - -void -PartitionLayout::setDefaultFsType( FileSystem::Type defaultFsType ) -{ - using FileSystem = FileSystem::Type; - QT_WARNING_PUSH - QT_WARNING_DISABLE_CLANG( "-Wswitch-enum" ) - switch ( defaultFsType ) - { - case FileSystem::Unknown: - case FileSystem::Unformatted: - case FileSystem::Extended: - case FileSystem::LinuxSwap: - case FileSystem::Luks: - case FileSystem::Ocfs2: - case FileSystem::Lvm2_PV: - case FileSystem::Udf: - case FileSystem::Iso9660: - case FileSystem::Luks2: - case FileSystem::LinuxRaidMember: - case FileSystem::BitLocker: - // bad bad - cWarning() << "The selected default FS" << defaultFsType << "is not suitable." - << "Using ext4 instead."; - defaultFsType = FileSystem::Ext4; - break; - case FileSystem::Ext2: - case FileSystem::Ext3: - case FileSystem::Ext4: - case FileSystem::Fat32: - case FileSystem::Ntfs: - case FileSystem::Reiser4: - case FileSystem::ReiserFS: - case FileSystem::Xfs: - case FileSystem::Jfs: - case FileSystem::Btrfs: - case FileSystem::Exfat: - case FileSystem::F2fs: - // ok - break; - case FileSystem::Fat16: - case FileSystem::Hfs: - case FileSystem::HfsPlus: - case FileSystem::Ufs: - case FileSystem::Hpfs: - case FileSystem::Zfs: - case FileSystem::Nilfs2: - case FileSystem::Fat12: - case FileSystem::Apfs: - case FileSystem::Minix: - // weird - cWarning() << "The selected default FS" << defaultFsType << "is unusual, but not wrong."; - break; - default: - cWarning() << "The selected default FS" << defaultFsType << "is not known to Calamares." - << "Using ext4 instead."; - defaultFsType = FileSystem::Ext4; - } - QT_WARNING_POP - - m_defaultFsType = defaultFsType; -} - -QList< Partition* > -PartitionLayout::createPartitions( Device* dev, - qint64 firstSector, - qint64 lastSector, - Config::LuksGeneration luksFsType, - QString luksPassphrase, - PartitionNode* parent, - const PartitionRole& role ) -{ - // Make sure the default FS is sensible; warn and use ext4 if not - setDefaultFsType( m_defaultFsType ); - - QList< Partition* > partList; - // Map each partition entry to its requested size (0 when calculated later) - QMap< const PartitionLayout::PartitionEntry*, qint64 > partSectorsMap; - const qint64 totalSectors = lastSector - firstSector + 1; - qint64 currentSector, availableSectors = totalSectors; - - // Let's check if we have enough space for each partitions, using the size - // propery or the min-size property if unit is in percentage. - for ( const auto& entry : qAsConst( m_partLayout ) ) - { - if ( !entry.partSize.isValid() ) - { - cWarning() << "Partition" << entry.partMountPoint << "size is invalid, skipping..."; - continue; - } - - // Calculate partition size: Rely on "possibly uninitialized use" - // warnings to ensure that all the cases are covered below. - // We need to ignore the percent-defined until later - qint64 sectors = 0; - if ( entry.partSize.unit() != Calamares::Partition::SizeUnit::Percent ) - { - sectors = entry.partSize.toSectors( totalSectors, dev->logicalSize() ); - } - else if ( entry.partMinSize.isValid() ) - { - sectors = entry.partMinSize.toSectors( totalSectors, dev->logicalSize() ); - } - partSectorsMap.insert( &entry, sectors ); - availableSectors -= sectors; - } - - // There is not enough space for all partitions, use the min-size property - // and see if we can do better afterward. - if ( availableSectors < 0 ) - { - availableSectors = totalSectors; - for ( const auto& entry : qAsConst( m_partLayout ) ) - { - qint64 sectors = partSectorsMap.value( &entry ); - if ( entry.partMinSize.isValid() ) - { - sectors = entry.partMinSize.toSectors( totalSectors, dev->logicalSize() ); - partSectorsMap.insert( &entry, sectors ); - } - availableSectors -= sectors; - } - } - - // Assign sectors for percentage-defined partitions. - for ( const auto& entry : qAsConst( m_partLayout ) ) - { - if ( entry.partSize.unit() == Calamares::Partition::SizeUnit::Percent ) - { - qint64 sectors - = entry.partSize.toSectors( availableSectors + partSectorsMap.value( &entry ), dev->logicalSize() ); - if ( entry.partMinSize.isValid() ) - { - sectors = std::max( sectors, entry.partMinSize.toSectors( totalSectors, dev->logicalSize() ) ); - } - if ( entry.partMaxSize.isValid() ) - { - sectors = std::min( sectors, entry.partMaxSize.toSectors( totalSectors, dev->logicalSize() ) ); - } - partSectorsMap.insert( &entry, sectors ); - } - } - - auto correctFS = [ d = m_defaultFsType ]( FileSystem::Type t ) { return t == FileSystem::Type::Unknown ? d : t; }; - - // Create the partitions. - currentSector = firstSector; - availableSectors = totalSectors; - for ( const auto& entry : qAsConst( m_partLayout ) ) - { - // Adjust partition size based on available space. - qint64 sectors = partSectorsMap.value( &entry ); - sectors = std::min( sectors, availableSectors ); - if ( sectors == 0 ) - { - continue; - } - - Partition* part = nullptr; - - // Encryption for zfs is handled in the zfs module, skip encryption on noEncrypt partitions - if ( luksPassphrase.isEmpty() || correctFS( entry.partFileSystem ) == FileSystem::Zfs || entry.partNoEncrypt ) - { - part = KPMHelpers::createNewPartition( parent, - *dev, - role, - correctFS( entry.partFileSystem ), - entry.partLabel, - currentSector, - currentSector + sectors - 1, - KPM_PARTITION_FLAG( None ) ); - } - else - { - part = KPMHelpers::createNewEncryptedPartition( parent, - *dev, - role, - correctFS( entry.partFileSystem ), - entry.partLabel, - currentSector, - currentSector + sectors - 1, - luksFsType, - luksPassphrase, - KPM_PARTITION_FLAG( None ) ); - } - - // For zfs, we need to make the passphrase available to later modules - if ( correctFS( entry.partFileSystem ) == FileSystem::Zfs ) - { - Calamares::GlobalStorage* storage = Calamares::JobQueue::instance()->globalStorage(); - QList< QVariant > zfsInfoList; - QVariantMap zfsInfo; - - // Save the information subsequent modules will need - zfsInfo[ "encrypted" ] = !luksPassphrase.isEmpty() && !entry.partNoEncrypt; - zfsInfo[ "passphrase" ] = luksPassphrase; - zfsInfo[ "mountpoint" ] = entry.partMountPoint; - - // Add it to the list and insert it into global storage - zfsInfoList.append( zfsInfo ); - storage->insert( "zfsInfo", zfsInfoList ); - } - - PartitionInfo::setFormat( part, true ); - PartitionInfo::setMountPoint( part, entry.partMountPoint ); - if ( !entry.partLabel.isEmpty() ) - { - part->setLabel( entry.partLabel ); - part->fileSystem().setLabel( entry.partLabel ); - } - if ( !entry.partUUID.isEmpty() ) - { - part->setUUID( entry.partUUID ); - } - if ( !entry.partType.isEmpty() ) - { - part->setType( entry.partType ); - } - if ( entry.partAttributes ) - { - part->setAttributes( entry.partAttributes ); - } - if ( !entry.partFeatures.isEmpty() ) - { - for ( const auto& k : entry.partFeatures.keys() ) - { - part->fileSystem().addFeature( k, entry.partFeatures.value( k ) ); - } - } - // Some buggy (legacy) BIOSes test if the bootflag of at least one partition is set. - // Otherwise they ignore the device in boot-order, so add it here. - partList.append( part ); - currentSector += sectors; - availableSectors -= sectors; - } - - return partList; -} diff --git a/src/modules/partition/core/PartitionLayout.h b/src/modules/partition/core/PartitionLayout.h deleted file mode 100644 index 2ff9c7ddee..0000000000 --- a/src/modules/partition/core/PartitionLayout.h +++ /dev/null @@ -1,131 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2018-2019 Collabora Ltd - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef PARTITIONLAYOUT_H -#define PARTITIONLAYOUT_H - -#include "Config.h" -#include "core/PartUtils.h" -#include "partition/PartitionSize.h" - -// KPMcore -#include -#include - -// Qt -#include -#include -#include - -class Partition; - -class PartitionLayout -{ -public: - struct PartitionEntry - { - QString partLabel; - QString partUUID; - QString partType; - quint64 partAttributes = 0; - QString partMountPoint; - FileSystem::Type partFileSystem = FileSystem::Unknown; - bool partNoEncrypt = false; - QVariantMap partFeatures; - Calamares::Partition::PartitionSize partSize; - Calamares::Partition::PartitionSize partMinSize; - Calamares::Partition::PartitionSize partMaxSize; - - /// @brief All-zeroes PartitionEntry - PartitionEntry(); - /** @brief Parse @p mountPoint, @p size, @p minSize and @p maxSize to their respective member variables - * - * Sets a specific FS type (not parsed from string like the other - * constructor). - */ - PartitionEntry( FileSystem::Type fs, - const QString& mountPoint, - const QString& size, - const QString& minSize = QString(), - const QString& maxSize = QString() ); - /// @brief All-field PartitionEntry - PartitionEntry( const QString& label, - const QString& uuid, - const QString& type, - quint64 attributes, - const QString& mountPoint, - const QString& fs, - const bool& noEncrypt, - const QVariantMap& features, - const QString& size, - const QString& minSize = QString(), - const QString& maxSize = QString() ); - /// @brief Copy PartitionEntry - PartitionEntry( const PartitionEntry& e ) = default; - - bool isValid() const - { - if ( !partSize.isValid() - || ( partMinSize.isValid() && partMaxSize.isValid() && partMinSize > partMaxSize ) ) - { - return false; - } - return true; - } - }; - - PartitionLayout(); - PartitionLayout( const PartitionLayout& layout ); - ~PartitionLayout(); - - /** @brief create the configuration from @p config - * - * @p config is a list of partition entries (in QVariant form, - * read from YAML). If no entries are given, then a single - * partition is created with type Unkown. - * - * Any partitions with FS type Unknown will get the default filesystem - * that is set at **apply** time (e.g. when createPartitions() is - * called as well. - * - * @see setDefaultFsType() - */ - void init( FileSystem::Type defaultFsType, const QVariantList& config ); - /** @brief add an entry as if it had been listed in the config - * - * The same comments about filesystem type apply. - */ - bool addEntry( const PartitionEntry& entry ); - - /** @brief set the default filesystem type - * - * Any partitions in the layout with type Unknown will get - * the default type when createPartitions() is called. - */ - void setDefaultFsType( FileSystem::Type defaultFsType ); - - /** - * @brief Apply the current partition layout to the selected drive space. - * @return A list of Partition objects. - */ - QList< Partition* > createPartitions( Device* dev, - qint64 firstSector, - qint64 lastSector, - Config::LuksGeneration luksFsType, - QString luksPassphrase, - PartitionNode* parent, - const PartitionRole& role ); - -private: - QList< PartitionEntry > m_partLayout; - FileSystem::Type m_defaultFsType = FileSystem::Type::Unknown; -}; - -#endif /* PARTITIONLAYOUT_H */ diff --git a/src/modules/partition/core/PartitionModel.cpp b/src/modules/partition/core/PartitionModel.cpp deleted file mode 100644 index a9d49dc37c..0000000000 --- a/src/modules/partition/core/PartitionModel.cpp +++ /dev/null @@ -1,338 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2018-2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "PartitionModel.h" - -#include "core/ColorUtils.h" -#include "core/KPMHelpers.h" -#include "core/PartitionInfo.h" -#include "core/SizeUtils.h" - -#include "partition/FileSystem.h" -#include "partition/PartitionQuery.h" -#include "utils/Logger.h" - -// CalaPM -#include -#include -#include -#include - -// Qt -#include - -using Calamares::Partition::isPartitionFreeSpace; -using Calamares::Partition::isPartitionNew; - -//- ResetHelper -------------------------------------------- -PartitionModel::ResetHelper::ResetHelper( PartitionModel* model ) - : m_model( model ) -{ - m_model->m_lock.lock(); - m_model->beginResetModel(); -} - -PartitionModel::ResetHelper::~ResetHelper() -{ - // We need to unlock the mutex before emitting the reset signal, - // because the reset will cause clients to start looking at the - // (new) data. - m_model->m_lock.unlock(); - m_model->endResetModel(); -} - -//- PartitionModel ----------------------------------------- -PartitionModel::PartitionModel( QObject* parent ) - : QAbstractItemModel( parent ) - , m_device( nullptr ) -{ -} - -void -PartitionModel::init( Device* device, const OsproberEntryList& osproberEntries ) -{ - QMutexLocker lock( &m_lock ); - beginResetModel(); - m_device = device; - m_osproberEntries = osproberEntries; - endResetModel(); -} - -int -PartitionModel::columnCount( const QModelIndex& ) const -{ - return ColumnCount; -} - -int -PartitionModel::rowCount( const QModelIndex& parent ) const -{ - Partition* parentPartition = partitionForIndex( parent ); - if ( parentPartition ) - { - return parentPartition->children().count(); - } - PartitionTable* table = m_device->partitionTable(); - return table ? table->children().count() : 0; -} - -QModelIndex -PartitionModel::index( int row, int column, const QModelIndex& parent ) const -{ - PartitionNode* parentPartition = parent.isValid() ? static_cast< PartitionNode* >( partitionForIndex( parent ) ) - : static_cast< PartitionNode* >( m_device->partitionTable() ); - if ( !parentPartition ) - { - return QModelIndex(); - } - auto lst = parentPartition->children(); - if ( row < 0 || row >= lst.count() ) - { - return QModelIndex(); - } - if ( column < 0 || column >= ColumnCount ) - { - return QModelIndex(); - } - Partition* partition = parentPartition->children().at( row ); - return createIndex( row, column, partition ); -} - -QModelIndex -PartitionModel::parent( const QModelIndex& child ) const -{ - if ( !child.isValid() ) - { - return QModelIndex(); - } - Partition* partition = partitionForIndex( child ); - if ( !partition ) - { - return QModelIndex(); - } - PartitionNode* parentNode = partition->parent(); - if ( parentNode == m_device->partitionTable() ) - { - return QModelIndex(); - } - - int row = 0; - for ( auto p : m_device->partitionTable()->children() ) - { - if ( parentNode == p ) - { - return createIndex( row, 0, parentNode ); - } - ++row; - } - cWarning() << "No parent found!"; - return QModelIndex(); -} - -QVariant -PartitionModel::data( const QModelIndex& index, int role ) const -{ - Partition* partition = partitionForIndex( index ); - if ( !partition ) - { - return QVariant(); - } - - switch ( role ) - { - case Qt::DisplayRole: - { - int col = index.column(); - if ( col == NameColumn ) - { - if ( isPartitionFreeSpace( partition ) ) - { - return tr( "Free Space", "@title" ); - } - else - { - return isPartitionNew( partition ) ? tr( "New Partition", "@title" ) : partition->partitionPath(); - } - } - if ( col == FileSystemColumn ) - { - return Calamares::Partition::prettyNameForFileSystemType( partition->fileSystem().type() ); - } - if ( col == FileSystemLabelColumn ) - { - return partition->fileSystem().label(); - } - if ( col == MountPointColumn ) - { - return PartitionInfo::mountPoint( partition ); - } - if ( col == SizeColumn ) - { - qint64 size = ( partition->lastSector() - partition->firstSector() + 1 ) * m_device->logicalSize(); - return formatByteSize( size ); - } - cDebug() << "Unknown column" << col; - return QVariant(); - } - case Qt::DecorationRole: - if ( index.column() == NameColumn ) - { - return ColorUtils::colorForPartition( partition ); - } - else - { - return QVariant(); - } - case Qt::ToolTipRole: - { - int col = index.column(); - QString name; - if ( col == NameColumn ) - { - if ( isPartitionFreeSpace( partition ) ) - { - name = tr( "Free Space", "@title" ); - } - else - { - name = isPartitionNew( partition ) ? tr( "New Partition", "@title" ) : partition->partitionPath(); - } - } - QString prettyFileSystem = Calamares::Partition::prettyNameForFileSystemType( partition->fileSystem().type() ); - qint64 size = ( partition->lastSector() - partition->firstSector() + 1 ) * m_device->logicalSize(); - QString prettySize = formatByteSize( size ); - return QVariant( name + " " + prettyFileSystem + " " + prettySize ); - } - case SizeRole: - return ( partition->lastSector() - partition->firstSector() + 1 ) * m_device->logicalSize(); - case IsFreeSpaceRole: - return isPartitionFreeSpace( partition ); - - case IsPartitionNewRole: - return isPartitionNew( partition ); - - case FileSystemLabelRole: - if ( partition->fileSystem().supportGetLabel() != FileSystem::cmdSupportNone - && !partition->fileSystem().label().isEmpty() ) - { - return partition->fileSystem().label(); - } - return QVariant(); - - case FileSystemTypeRole: - return partition->fileSystem().type(); - - case PartitionPathRole: - return partition->partitionPath(); - - case PartitionPtrRole: - return QVariant::fromValue( (void*)partition ); - - // Osprober roles: - case OsproberNameRole: - foreach ( const OsproberEntry& osproberEntry, m_osproberEntries ) - { - if ( partition->fileSystem().supportGetUUID() != FileSystem::cmdSupportNone - && !partition->fileSystem().uuid().isEmpty() && osproberEntry.uuid == partition->fileSystem().uuid() ) - { - return osproberEntry.prettyName; - } - } - return QVariant(); - case OsproberPathRole: - foreach ( const OsproberEntry& osproberEntry, m_osproberEntries ) - { - if ( partition->fileSystem().supportGetUUID() != FileSystem::cmdSupportNone - && !partition->fileSystem().uuid().isEmpty() && osproberEntry.uuid == partition->fileSystem().uuid() ) - { - return osproberEntry.path; - } - } - return QVariant(); - case OsproberCanBeResizedRole: - foreach ( const OsproberEntry& osproberEntry, m_osproberEntries ) - { - if ( partition->fileSystem().supportGetUUID() != FileSystem::cmdSupportNone - && !partition->fileSystem().uuid().isEmpty() && osproberEntry.uuid == partition->fileSystem().uuid() ) - { - return osproberEntry.canBeResized; - } - } - return QVariant(); - case OsproberRawLineRole: - foreach ( const OsproberEntry& osproberEntry, m_osproberEntries ) - { - if ( partition->fileSystem().supportGetUUID() != FileSystem::cmdSupportNone - && !partition->fileSystem().uuid().isEmpty() && osproberEntry.uuid == partition->fileSystem().uuid() ) - { - return osproberEntry.line; - } - } - return QVariant(); - case OsproberHomePartitionPathRole: - foreach ( const OsproberEntry& osproberEntry, m_osproberEntries ) - { - if ( partition->fileSystem().supportGetUUID() != FileSystem::cmdSupportNone - && !partition->fileSystem().uuid().isEmpty() && osproberEntry.uuid == partition->fileSystem().uuid() ) - { - return osproberEntry.homePath; - } - } - return QVariant(); - // end Osprober roles. - - default: - return QVariant(); - } -} - -QVariant -PartitionModel::headerData( int section, Qt::Orientation, int role ) const -{ - if ( role != Qt::DisplayRole ) - { - return QVariant(); - } - - switch ( section ) - { - case NameColumn: - return tr( "Name", "@title" ); - case FileSystemColumn: - return tr( "File System", "@title" ); - case FileSystemLabelColumn: - return tr( "File System Label", "@title" ); - case MountPointColumn: - return tr( "Mount Point", "@title" ); - case SizeColumn: - return tr( "Size", "@title" ); - default: - cDebug() << "Unknown column" << section; - return QVariant(); - } -} - -Partition* -PartitionModel::partitionForIndex( const QModelIndex& index ) const -{ - QMutexLocker lock( &m_lock ); - if ( !index.isValid() ) - { - return nullptr; - } - return reinterpret_cast< Partition* >( index.internalPointer() ); -} - - -void -PartitionModel::update() -{ - Q_EMIT dataChanged( index( 0, 0 ), index( rowCount() - 1, columnCount() - 1 ) ); -} diff --git a/src/modules/partition/core/PartitionModel.h b/src/modules/partition/core/PartitionModel.h deleted file mode 100644 index ba5e258a31..0000000000 --- a/src/modules/partition/core/PartitionModel.h +++ /dev/null @@ -1,116 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2017 2019, Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ -#ifndef PARTITIONMODEL_H -#define PARTITIONMODEL_H - -#include "OsproberEntry.h" - -// Qt -#include -#include - -class Device; -class Partition; -class PartitionNode; - -/** - * A Qt tree model which exposes the partitions of a device. - * - * Its depth is only more than 1 if the device has extended partitions. - * - * Note on updating: - * - * The Device class does not notify the outside world of changes on the - * Partition objects it owns. Since a Qt model must notify its views *before* - * and *after* making changes, it is important to make use of - * the PartitionModel::ResetHelper class to wrap changes. - * - * This is what PartitionCoreModule does when it create jobs. - */ -class PartitionModel : public QAbstractItemModel -{ - Q_OBJECT -public: - /** - * This helper class must be instantiated on the stack *before* making - * changes to the device represented by this model. It will cause the model - * to Q_EMIT modelAboutToBeReset() when instantiated and modelReset() when - * destructed. - */ - class ResetHelper - { - public: - ResetHelper( PartitionModel* model ); - ~ResetHelper(); - - ResetHelper( const ResetHelper& ) = delete; - ResetHelper& operator=( const ResetHelper& ) = delete; - - private: - PartitionModel* m_model; - }; - - enum - { - // The raw size, as a qlonglong. This is different from the DisplayRole of - // SizeColumn, which is a human-readable string. - SizeRole = Qt::UserRole + 1, - IsFreeSpaceRole, - IsPartitionNewRole, - FileSystemLabelRole, - FileSystemTypeRole, - PartitionPathRole, - PartitionPtrRole, // passed as void*, use sparingly - OsproberNameRole, - OsproberPathRole, - OsproberCanBeResizedRole, - OsproberRawLineRole, - OsproberHomePartitionPathRole - }; - - enum Column - { - NameColumn, - FileSystemColumn, - FileSystemLabelColumn, - MountPointColumn, - SizeColumn, - ColumnCount // Must remain last - }; - - PartitionModel( QObject* parent = nullptr ); - /** - * device must remain alive for the life of PartitionModel - */ - void init( Device* device, const OsproberEntryList& osproberEntries ); - - // QAbstractItemModel API - QModelIndex index( int row, int column, const QModelIndex& parent = QModelIndex() ) const override; - QModelIndex parent( const QModelIndex& child ) const override; - int columnCount( const QModelIndex& parent = QModelIndex() ) const override; - int rowCount( const QModelIndex& parent = QModelIndex() ) const override; - QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const override; - QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const override; - - Partition* partitionForIndex( const QModelIndex& index ) const; - - Device* device() const { return m_device; } - - void update(); - -private: - friend class ResetHelper; - - Device* m_device; - OsproberEntryList m_osproberEntries; - mutable QMutex m_lock; -}; - -#endif /* PARTITIONMODEL_H */ diff --git a/src/modules/partition/core/SizeUtils.h b/src/modules/partition/core/SizeUtils.h deleted file mode 100644 index 155cbd9239..0000000000 --- a/src/modules/partition/core/SizeUtils.h +++ /dev/null @@ -1,28 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2021 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef PARTITION_CORE_SIZEUTILS_H -#define PARTITION_CORE_SIZEUTILS_H - -#include - -/** @brief Helper function for printing sizes consistently. - * - * Most of Calamares uses a qint64 for partition sizes, so use that - * parameter type. However, the human-visible formatting doesn't need - * to bother with one-byte accuracy (and anyway, a double has at least 50 bits - * at which point we're printing giga (or gibi) bytes). - */ -static inline QString -formatByteSize( qint64 sizeValue ) -{ - return Capacity::formatByteSize( static_cast< double >( sizeValue ) ); -} - -#endif // PARTITION_CORE_SIZEUTILS_H diff --git a/src/modules/partition/gui/BootInfoWidget.cpp b/src/modules/partition/gui/BootInfoWidget.cpp deleted file mode 100644 index b4339be9ac..0000000000 --- a/src/modules/partition/gui/BootInfoWidget.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "BootInfoWidget.h" -#include "core/PartUtils.h" - -#include "utils/Gui.h" -#include "utils/QtCompat.h" -#include "utils/Retranslator.h" - -#include -#include -#include - -BootInfoWidget::BootInfoWidget( QWidget* parent ) - : QWidget( parent ) - , m_bootIcon( new QLabel ) - , m_bootLabel( new QLabel ) -{ - m_bootIcon->setObjectName( "bootInfoIcon" ); - m_bootLabel->setObjectName( "bootInfoLabel" ); - QHBoxLayout* mainLayout = new QHBoxLayout; - setLayout( mainLayout ); - - Calamares::unmarginLayout( mainLayout ); - - mainLayout->addWidget( m_bootIcon ); - mainLayout->addWidget( m_bootLabel ); - - QSize iconSize = Calamares::defaultIconSize(); - - m_bootIcon->setMargin( 0 ); - m_bootIcon->setFixedSize( iconSize ); - m_bootIcon->setPixmap( Calamares::defaultPixmap( Calamares::BootEnvironment, Calamares::Original, iconSize ) ); - - QFontMetrics fm = QFontMetrics( QFont() ); - m_bootLabel->setMinimumWidth( fm.boundingRect( "BIOS" ).width() + Calamares::defaultFontHeight() / 2 ); - m_bootLabel->setAlignment( Qt::AlignCenter ); - - QPalette palette; - palette.setBrush( WindowText, QColor( "#4D4D4D" ) ); //dark grey - - m_bootIcon->setAutoFillBackground( true ); - m_bootLabel->setAutoFillBackground( true ); - m_bootIcon->setPalette( palette ); - m_bootLabel->setPalette( palette ); - - CALAMARES_RETRANSLATE( retranslateUi(); ); -} - -void -BootInfoWidget::retranslateUi() -{ - m_bootIcon->setToolTip( tr( "The boot environment of this system.

    " - "Older x86 systems only support BIOS.
    " - "Modern systems usually use EFI, but " - "may also show up as BIOS if started in compatibility " - "mode." ) ); - - QString bootToolTip; - if ( PartUtils::isEfiSystem() ) - { - m_bootLabel->setText( "EFI " ); - bootToolTip = tr( "This system was started with an EFI " - "boot environment.

    " - "To configure startup from an EFI environment, this installer " - "must deploy a boot loader application, like GRUB" - " or systemd-boot on an " - "EFI System Partition. This is automatic, unless " - "you choose manual partitioning, in which case you must " - "choose it or create it on your own." ); - } - else - { - m_bootLabel->setText( "BIOS" ); - bootToolTip = tr( "This system was started with a BIOS " - "boot environment.

    " - "To configure startup from a BIOS environment, this installer " - "must install a boot loader, like GRUB" - ", either at the beginning of a partition or " - "on the Master Boot Record near the " - "beginning of the partition table (preferred). " - "This is automatic, unless " - "you choose manual partitioning, in which case you must " - "set it up on your own." ); - } - m_bootLabel->setToolTip( bootToolTip ); -} diff --git a/src/modules/partition/gui/BootInfoWidget.h b/src/modules/partition/gui/BootInfoWidget.h deleted file mode 100644 index 6be3f6e7b1..0000000000 --- a/src/modules/partition/gui/BootInfoWidget.h +++ /dev/null @@ -1,32 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - - -#ifndef BOOTINFOWIDGET_H -#define BOOTINFOWIDGET_H - -#include - -class QLabel; - -class BootInfoWidget : public QWidget -{ - Q_OBJECT -public: - explicit BootInfoWidget( QWidget* parent = nullptr ); - -public slots: - void retranslateUi(); - -private: - QLabel* m_bootIcon; - QLabel* m_bootLabel; -}; - -#endif // BOOTINFOWIDGET_H diff --git a/src/modules/partition/gui/ChoicePage.cpp b/src/modules/partition/gui/ChoicePage.cpp deleted file mode 100644 index 8a13132376..0000000000 --- a/src/modules/partition/gui/ChoicePage.cpp +++ /dev/null @@ -1,1762 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2017 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017-2019 Adriaan de Groot - * SPDX-FileCopyrightText: 2019 Collabora Ltd - * SPDX-FileCopyrightText: 2021 Anubhav Choudhary - * SPDX-FileCopyrightText: 2023 Evan James - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "ChoicePage.h" - -#include "Config.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 "gui/BootInfoWidget.h" -#include "gui/DeviceInfoWidget.h" -#include "gui/PartitionBarsView.h" -#include "gui/PartitionLabelsView.h" -#include "gui/PartitionSplitterWidget.h" -#include "gui/ScanningDialog.h" - -#include "Branding.h" -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "partition/PartitionIterator.h" -#include "partition/PartitionQuery.h" -#include "utils/Gui.h" -#include "utils/Logger.h" -#include "utils/Retranslator.h" -#include "utils/Units.h" -#include "widgets/PrettyRadioButton.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -using Calamares::Partition::findPartitionByPath; -using Calamares::Partition::isPartitionFreeSpace; -using Calamares::Partition::PartitionIterator; -using Calamares::Widgets::PrettyRadioButton; -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 QWidget parent. - */ -ChoicePage::ChoicePage( Config* config, QWidget* parent ) - : QWidget( parent ) - , m_config( config ) - , m_nextEnabled( false ) - , m_core( nullptr ) - , m_isEfi( false ) - , m_grp( nullptr ) - , m_alongsideButton( nullptr ) - , m_eraseButton( nullptr ) - , m_replaceButton( nullptr ) - , m_somethingElseButton( nullptr ) - , m_eraseSwapChoiceComboBox( nullptr ) - , m_deviceInfoWidget( nullptr ) - , m_beforePartitionBarsView( nullptr ) - , m_beforePartitionLabelsView( nullptr ) - , m_bootloaderComboBox( nullptr ) - , m_enableEncryptionWidget( true ) -{ - setupUi( this ); - - auto gs = Calamares::JobQueue::instance()->globalStorage(); - - m_enableEncryptionWidget = gs->value( "enableLuksAutomatedPartitioning" ).toBool(); - - // Set up drives combo - m_mainLayout->setDirection( QBoxLayout::TopToBottom ); - m_drivesLayout->setDirection( QBoxLayout::LeftToRight ); - - BootInfoWidget* bootInfoWidget = new BootInfoWidget( this ); - m_drivesLayout->insertWidget( 0, bootInfoWidget ); - m_drivesLayout->insertSpacing( 1, Calamares::defaultFontHeight() / 2 ); - - m_drivesCombo = new QComboBox( this ); - m_mainLayout->setStretchFactor( m_drivesLayout, 0 ); - m_mainLayout->setStretchFactor( m_rightLayout, 1 ); - m_drivesLabel->setBuddy( m_drivesCombo ); - - m_drivesLayout->addWidget( m_drivesCombo ); - - m_deviceInfoWidget = new DeviceInfoWidget; - m_drivesLayout->addWidget( m_deviceInfoWidget ); - m_drivesLayout->addStretch(); - - m_messageLabel->setWordWrap( true ); - m_messageLabel->hide(); - - Calamares::unmarginLayout( m_itemsLayout ); - - // Drive selector + preview - CALAMARES_RETRANSLATE_SLOT( &ChoicePage::retranslate ); - - m_previewBeforeFrame->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Expanding ); - m_previewAfterFrame->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Expanding ); - m_previewAfterLabel->hide(); - m_previewAfterFrame->hide(); - m_encryptWidget->hide(); - m_reuseHomeCheckBox->hide(); - gs->insert( "reuseHome", false ); - - updateNextEnabled(); -} - -ChoicePage::~ChoicePage() {} - -void -ChoicePage::retranslate() -{ - retranslateUi( this ); - m_drivesLabel->setText( tr( "Select storage de&vice:", "@label" ) ); - m_previewBeforeLabel->setText( tr( "Current:", "@label" ) ); - m_previewAfterLabel->setText( tr( "After:", "@label" ) ); - - updateSwapChoicesTr(); - updateChoiceButtonsTr(); -} - -/** @brief Sets the @p model for the given @p box and adjusts UI sizes to match. - * - * The model provides data for drawing the items in the model; the - * drawing itself is done by the delegate, which may end up drawing a - * different width in the popup than in the collapsed combo box. - * - * Make the box wide enough to accomodate the whole expanded delegate; - * this avoids cases where the popup would truncate data being drawn - * because the overall box is sized too narrow. - */ -void -setModelToComboBox( QComboBox* box, QAbstractItemModel* model ) -{ - box->setModel( model ); - if ( model->rowCount() > 0 ) - { - QStyleOptionViewItem options; - options.initFrom( box ); - auto delegateSize = box->itemDelegate()->sizeHint( options, model->index( 0, 0 ) ); - box->setMinimumWidth( delegateSize.width() ); - } -} - -void -ChoicePage::init( PartitionCoreModule* core ) -{ - m_core = core; - m_isEfi = PartUtils::isEfiSystem(); - - setupChoices(); - - // We need to do this because a PCM revert invalidates the deviceModel. - connect( core, - &PartitionCoreModule::reverted, - this, - [ = ] - { - setModelToComboBox( m_drivesCombo, core->deviceModel() ); - m_drivesCombo->setCurrentIndex( m_lastSelectedDeviceIndex ); - } ); - setModelToComboBox( m_drivesCombo, core->deviceModel() ); - - connect( m_drivesCombo, qOverload< int >( &QComboBox::currentIndexChanged ), this, &ChoicePage::applyDeviceChoice ); - - connect( m_encryptWidget, &EncryptWidget::stateChanged, this, &ChoicePage::onEncryptWidgetStateChanged ); - connect( m_reuseHomeCheckBox, &QCheckBox::stateChanged, this, &ChoicePage::onHomeCheckBoxStateChanged ); - - ChoicePage::applyDeviceChoice(); -} - -/** @brief Creates a combobox with the given choices in it. - * - * Pre-selects the choice given by @p dflt. - * No texts are set -- that happens later by the translator functions. - */ -static inline QComboBox* -createCombo( const QSet< SwapChoice >& s, SwapChoice dflt ) -{ - QComboBox* box = new QComboBox; - for ( SwapChoice c : { SwapChoice::NoSwap, - SwapChoice::SmallSwap, - SwapChoice::FullSwap, - SwapChoice::ReuseSwap, - SwapChoice::SwapFile } ) - { - if ( s.contains( c ) ) - { - box->addItem( QString(), c ); - } - } - - int dfltIndex = box->findData( dflt ); - if ( dfltIndex >= 0 ) - { - box->setCurrentIndex( dfltIndex ); - } - - return box; -} - -/** - * @brief ChoicePage::setupChoices creates PrettyRadioButton objects for the action - * choices. - * @warning This must only run ONCE because it creates signal-slot connections for the - * actions. When an action is triggered, it runs action-specific code that may - * change the internal state of the PCM, and it updates the bottom preview (or - * split) widget. - * Synchronous loading ends here. - */ -void -ChoicePage::setupChoices() -{ - // sample os-prober output: - // /dev/sda2:Windows 7 (loader):Windows:chain - // /dev/sda6::Arch:linux - // - // There are three possibilities we have to consider: - // - There are no operating systems present - // - There is one operating system present - // - There are multiple operating systems present - // - // There are three outcomes we have to provide: - // 1) Wipe+autopartition - // 2) Resize+autopartition - // 3) Manual - // TBD: upgrade option? - - QSize iconSize( Calamares::defaultIconSize().width() * 2, Calamares::defaultIconSize().height() * 2 ); - m_grp = new QButtonGroup( this ); - - m_alongsideButton = new PrettyRadioButton; - m_alongsideButton->setIconSize( iconSize ); - m_alongsideButton->setIcon( - Calamares::defaultPixmap( Calamares::PartitionAlongside, Calamares::Original, iconSize ) ); - m_alongsideButton->addToGroup( m_grp, InstallChoice::Alongside ); - - m_eraseButton = new PrettyRadioButton; - m_eraseButton->setIconSize( iconSize ); - m_eraseButton->setIcon( Calamares::defaultPixmap( Calamares::PartitionEraseAuto, Calamares::Original, iconSize ) ); - m_eraseButton->addToGroup( m_grp, InstallChoice::Erase ); - - m_replaceButton = new PrettyRadioButton; - - m_replaceButton->setIconSize( iconSize ); - m_replaceButton->setIcon( - Calamares::defaultPixmap( Calamares::PartitionReplaceOs, Calamares::Original, iconSize ) ); - m_replaceButton->addToGroup( m_grp, InstallChoice::Replace ); - - // Fill up swap options - if ( m_config->swapChoices().count() > 1 ) - { - m_eraseSwapChoiceComboBox = createCombo( m_config->swapChoices(), m_config->swapChoice() ); - m_eraseButton->addOptionsComboBox( m_eraseSwapChoiceComboBox ); - } - - if ( m_config->eraseFsTypes().count() > 1 ) - { - m_eraseFsTypesChoiceComboBox = new QComboBox; - m_eraseFsTypesChoiceComboBox->addItems( m_config->eraseFsTypes() ); - connect( - m_eraseFsTypesChoiceComboBox, &QComboBox::currentTextChanged, m_config, &Config::setEraseFsTypeChoice ); - connect( m_config, &Config::eraseModeFilesystemChanged, this, &ChoicePage::onActionChanged ); - m_eraseButton->addOptionsComboBox( m_eraseFsTypesChoiceComboBox ); - - // Also offer it for "replace - m_replaceFsTypesChoiceComboBox = new QComboBox; - m_replaceFsTypesChoiceComboBox->addItems( m_config->eraseFsTypes() ); - connect( m_replaceFsTypesChoiceComboBox, - &QComboBox::currentTextChanged, - m_config, - &Config::setReplaceFilesystemChoice ); - connect( m_config, &Config::replaceModeFilesystemChanged, this, &ChoicePage::onActionChanged ); - m_replaceButton->addOptionsComboBox( m_replaceFsTypesChoiceComboBox ); - } - - m_itemsLayout->addWidget( m_alongsideButton ); - m_itemsLayout->addWidget( m_replaceButton ); - m_itemsLayout->addWidget( m_eraseButton ); - - m_somethingElseButton = new PrettyRadioButton; - m_somethingElseButton->setIconSize( iconSize ); - m_somethingElseButton->setIcon( - Calamares::defaultPixmap( Calamares::PartitionManual, Calamares::Original, iconSize ) ); - m_itemsLayout->addWidget( m_somethingElseButton ); - m_somethingElseButton->addToGroup( m_grp, InstallChoice::Manual ); - - m_itemsLayout->addStretch(); - - connect( m_grp, - &QButtonGroup::idToggled, - this, - [ this ]( int id, bool checked ) - { - if ( checked ) // An action was picked. - { - m_config->setInstallChoice( id ); - updateNextEnabled(); - - Q_EMIT actionChosen(); - } - else // An action was unpicked, either on its own or because of another selection. - { - if ( m_grp->checkedButton() == nullptr ) // If no other action is chosen, we must - { - // set m_choice to NoChoice and reset previews. - m_config->setInstallChoice( InstallChoice::NoChoice ); - updateNextEnabled(); - - Q_EMIT actionChosen(); - } - } - } ); - - m_rightLayout->setStretchFactor( m_itemsLayout, 1 ); - m_rightLayout->setStretchFactor( m_previewBeforeFrame, 0 ); - m_rightLayout->setStretchFactor( m_previewAfterFrame, 0 ); - - connect( this, &ChoicePage::actionChosen, this, &ChoicePage::onActionChanged ); - if ( m_eraseSwapChoiceComboBox ) - { - connect( m_eraseSwapChoiceComboBox, - QOverload< int >::of( &QComboBox::currentIndexChanged ), - this, - &ChoicePage::onEraseSwapChoiceChanged ); - } - - updateSwapChoicesTr(); - updateChoiceButtonsTr(); -} - -/** - * @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* -ChoicePage::selectedDevice() -{ - Device* currentDevice = nullptr; - currentDevice - = m_core->deviceModel()->deviceForIndex( m_core->deviceModel()->index( m_drivesCombo->currentIndex() ) ); - - return currentDevice; -} - -void -ChoicePage::hideButtons() -{ - m_eraseButton->hide(); - m_replaceButton->hide(); - m_alongsideButton->hide(); - m_somethingElseButton->hide(); -} - -void -ChoicePage::checkInstallChoiceRadioButton( InstallChoice c ) -{ - QSignalBlocker b( m_grp ); - m_grp->setExclusive( false ); - // If c == InstallChoice::NoChoice none will match and all are deselected - m_eraseButton->setChecked( InstallChoice::Erase == c ); - m_replaceButton->setChecked( InstallChoice::Replace == c ); - m_alongsideButton->setChecked( InstallChoice::Alongside == c ); - m_somethingElseButton->setChecked( InstallChoice::Manual == c ); - m_grp->setExclusive( true ); -} - -/** - * @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 -ChoicePage::applyDeviceChoice() -{ - if ( !selectedDevice() ) - { - hideButtons(); - return; - } - - if ( m_core->isDirty() ) - { - ScanningDialog::run( - QtConcurrent::run( - [ = ] - { - QMutexLocker locker( &m_coreMutex ); - m_core->revertAllDevices(); - } ), - [ this ] { continueApplyDeviceChoice(); }, - this ); - } - else - { - continueApplyDeviceChoice(); - } -} - -void -ChoicePage::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 ) - { - hideButtons(); - return; - } - - updateDeviceStatePreview(); - - // Preview setup done. Now we show/hide choices as needed. - setupActions(); - - cDebug() << "Previous device" << m_lastSelectedDeviceIndex << "new device" << m_drivesCombo->currentIndex(); - if ( m_lastSelectedDeviceIndex != m_drivesCombo->currentIndex() ) - { - m_lastSelectedDeviceIndex = m_drivesCombo->currentIndex(); - m_config->setInstallChoice( m_config->initialInstallChoice() ); - checkInstallChoiceRadioButton( m_config->installChoice() ); - } - - Q_EMIT actionChosen(); - Q_EMIT deviceChosen(); -} - -void -ChoicePage::onActionChanged() -{ - if ( m_enableEncryptionWidget ) - { - if ( m_config->installChoice() == InstallChoice::Erase && m_eraseFsTypesChoiceComboBox ) - { - m_encryptWidget->setFilesystem( FileSystem::typeForName( m_eraseFsTypesChoiceComboBox->currentText() ) ); - } - else if ( m_config->installChoice() == InstallChoice::Replace && m_replaceFsTypesChoiceComboBox ) - { - m_encryptWidget->setFilesystem( FileSystem::typeForName( m_replaceFsTypesChoiceComboBox->currentText() ) ); - } - } - - Device* currd = selectedDevice(); - if ( currd ) - { - applyActionChoice( m_config->installChoice() ); - } - - updateNextEnabled(); -} - -void -ChoicePage::onEraseSwapChoiceChanged() -{ - if ( m_eraseSwapChoiceComboBox ) - { - m_config->setSwapChoice( m_eraseSwapChoiceComboBox->currentData().toInt() ); - onActionChanged(); - } -} - -void -ChoicePage::applyActionChoice( InstallChoice choice ) -{ - cDebug() << "InstallChoice" << choice << Config::installChoiceNames().find( choice ); - m_beforePartitionBarsView->selectionModel()->disconnect( SIGNAL( currentRowChanged( QModelIndex, QModelIndex ) ) ); - auto priorSelection = m_beforePartitionBarsView->selectionModel()->currentIndex(); - m_beforePartitionBarsView->selectionModel()->clearSelection(); - m_beforePartitionBarsView->selectionModel()->clearCurrentIndex(); - - switch ( choice ) - { - case InstallChoice::Erase: - { - auto gs = Calamares::JobQueue::instance()->globalStorage(); - PartitionActions::Choices::AutoPartitionOptions options { gs->value( "defaultPartitionTableType" ).toString(), - m_config->eraseFsType(), - m_config->luksFileSystemType(), - m_encryptWidget->passphrase(), - gs->value( "efiSystemPartition" ).toString(), - Calamares::GiBtoBytes( - gs->value( "requiredStorageGiB" ).toDouble() ), - m_config->swapChoice() }; - - if ( m_core->isDirty() ) - { - ScanningDialog::run( - QtConcurrent::run( - [ = ] - { - QMutexLocker locker( &m_coreMutex ); - m_core->revertDevice( selectedDevice() ); - } ), - [ = ] - { - PartitionActions::doAutopartition( m_core, selectedDevice(), options ); - Q_EMIT deviceChosen(); - }, - this ); - } - else - { - PartitionActions::doAutopartition( m_core, selectedDevice(), options ); - Q_EMIT deviceChosen(); - } - } - break; - case InstallChoice::Replace: - if ( m_core->isDirty() ) - { - ScanningDialog::run( - QtConcurrent::run( - [ = ] - { - QMutexLocker locker( &m_coreMutex ); - m_core->revertDevice( selectedDevice() ); - } ), - [] {}, - this ); - } - connect( m_beforePartitionBarsView->selectionModel(), - &QItemSelectionModel::currentRowChanged, - this, - &ChoicePage::onPartitionToReplaceSelected, - Qt::UniqueConnection ); - - // Maintain the selection for replace - if ( priorSelection.isValid() ) - { - m_beforePartitionBarsView->selectionModel()->setCurrentIndex( priorSelection, QItemSelectionModel::Select ); - } - break; - - case InstallChoice::Alongside: - if ( m_core->isDirty() ) - { - ScanningDialog::run( - QtConcurrent::run( - [ = ] - { - QMutexLocker locker( &m_coreMutex ); - m_core->revertDevice( selectedDevice() ); - } ), - [ this ] - { - // We need to reupdate after reverting because the splitter widget is - // not a true view. - updateActionChoicePreview( m_config->installChoice() ); - updateNextEnabled(); - }, - this ); - } - - connect( m_beforePartitionBarsView->selectionModel(), - &QItemSelectionModel::currentRowChanged, - this, - &ChoicePage::doAlongsideSetupSplitter, - Qt::UniqueConnection ); - break; - case InstallChoice::NoChoice: - case InstallChoice::Manual: - break; - } - updateNextEnabled(); - updateActionChoicePreview( choice ); -} - -void -ChoicePage::doAlongsideSetupSplitter( const QModelIndex& current, const QModelIndex& previous ) -{ - Q_UNUSED( previous ) - if ( !current.isValid() ) - { - return; - } - - if ( !m_afterPartitionSplitterWidget ) - { - return; - } - - const PartitionModel* modl = qobject_cast< const PartitionModel* >( current.model() ); - if ( !modl ) - { - return; - } - - Partition* part = modl->partitionForIndex( current ); - if ( !part ) - { - cDebug() << "Partition not found for index" << current; - return; - } - - double requiredStorageGB - = Calamares::JobQueue::instance()->globalStorage()->value( "requiredStorageGiB" ).toDouble(); - - qint64 requiredStorageB = Calamares::GiBtoBytes( requiredStorageGB + 0.1 + 2.0 ); - - m_afterPartitionSplitterWidget->setSplitPartition( part->partitionPath(), - qRound64( part->used() * 1.1 ), - part->capacity() - requiredStorageB, - part->capacity() / 2 ); - - if ( m_isEfi ) - { - setupEfiSystemPartitionSelector(); - } - - cDebug() << "Partition selected for Alongside."; - - updateNextEnabled(); -} - -void -ChoicePage::onEncryptWidgetStateChanged() -{ - EncryptWidget::Encryption state = m_encryptWidget->state(); - if ( m_config->installChoice() == InstallChoice::Erase ) - { - if ( state == EncryptWidget::Encryption::Confirmed || state == EncryptWidget::Encryption::Disabled ) - { - applyActionChoice( m_config->installChoice() ); - } - } - else if ( m_config->installChoice() == InstallChoice::Replace ) - { - if ( m_beforePartitionBarsView && m_beforePartitionBarsView->selectionModel()->currentIndex().isValid() - && ( state == EncryptWidget::Encryption::Confirmed || state == EncryptWidget::Encryption::Disabled ) ) - { - doReplaceSelectedPartition( m_beforePartitionBarsView->selectionModel()->currentIndex() ); - } - } - updateNextEnabled(); -} - -void -ChoicePage::onHomeCheckBoxStateChanged() -{ - if ( m_config->installChoice() == InstallChoice::Replace - && m_beforePartitionBarsView->selectionModel()->currentIndex().isValid() ) - { - doReplaceSelectedPartition( m_beforePartitionBarsView->selectionModel()->currentIndex() ); - } -} - -void -ChoicePage::onLeave() -{ - if ( m_config->installChoice() == InstallChoice::Alongside ) - { - doAlongsideApply(); - } - - if ( m_isEfi - && ( m_config->installChoice() == InstallChoice::Alongside - || m_config->installChoice() == InstallChoice::Replace ) ) - { - QList< Partition* > efiSystemPartitions = m_core->efiSystemPartitions(); - if ( efiSystemPartitions.count() == 1 ) - { - PartitionInfo::setMountPoint( - efiSystemPartitions.first(), - Calamares::JobQueue::instance()->globalStorage()->value( "efiSystemPartition" ).toString() ); - } - else if ( efiSystemPartitions.count() > 1 && m_efiComboBox ) - { - PartitionInfo::setMountPoint( - efiSystemPartitions.at( m_efiComboBox->currentIndex() ), - Calamares::JobQueue::instance()->globalStorage()->value( "efiSystemPartition" ).toString() ); - } - else - { - cError() << "cannot set up EFI system partition.\nESP count:" << efiSystemPartitions.count() - << "\nm_efiComboBox:" << m_efiComboBox; - } - } - else // installPath is then passed to the bootloader module for MBR setup - { - if ( !m_isEfi ) - { - if ( m_bootloaderComboBox.isNull() ) - { - auto d_p = selectedDevice(); - if ( d_p ) - { - m_core->setBootLoaderInstallPath( d_p->deviceNode() ); - } - else - { - cWarning() << "No device selected for bootloader."; - } - } - else - { - QVariant var = m_bootloaderComboBox->currentData( BootLoaderModel::BootLoaderPathRole ); - if ( !var.isValid() ) - { - return; - } - m_core->setBootLoaderInstallPath( var.toString() ); - } - } - } -} - -void -ChoicePage::doAlongsideApply() -{ - Q_ASSERT( m_afterPartitionSplitterWidget->splitPartitionSize() >= 0 ); - Q_ASSERT( m_afterPartitionSplitterWidget->newPartitionSize() >= 0 ); - - QMutexLocker locker( &m_coreMutex ); - - QString path = m_beforePartitionBarsView->selectionModel() - ->currentIndex() - .data( PartitionModel::PartitionPathRole ) - .toString(); - - DeviceModel* dm = m_core->deviceModel(); - for ( int i = 0; i < dm->rowCount(); ++i ) - { - Device* dev = dm->deviceForIndex( dm->index( i ) ); - Partition* candidate = findPartitionByPath( { dev }, path ); - if ( candidate ) - { - qint64 firstSector = candidate->firstSector(); - qint64 oldLastSector = candidate->lastSector(); - qint64 newLastSector - = firstSector + m_afterPartitionSplitterWidget->splitPartitionSize() / dev->logicalSize(); - - m_core->resizePartition( dev, candidate, firstSector, newLastSector ); - m_core->layoutApply( dev, - newLastSector + 2, - oldLastSector, - m_config->luksFileSystemType(), - m_encryptWidget->passphrase(), - candidate->parent(), - candidate->roles() ); - m_core->dumpQueue(); - - break; - } - } -} - -void -ChoicePage::onPartitionToReplaceSelected( const QModelIndex& current, const QModelIndex& previous ) -{ - Q_UNUSED( previous ) - if ( !current.isValid() ) - { - return; - } - - // Reset state on selection regardless of whether this will be used. - m_reuseHomeCheckBox->setChecked( false ); - - doReplaceSelectedPartition( current ); -} - -void -ChoicePage::doReplaceSelectedPartition( const QModelIndex& current ) -{ - if ( !current.isValid() ) - { - return; - } - - // This will be deleted by the second lambda, below. - QString* homePartitionPath = new QString(); - - ScanningDialog::run( - QtConcurrent::run( - [ this, current, homePartitionPath ]( bool doReuseHomePartition ) - { - QMutexLocker locker( &m_coreMutex ); - - if ( m_core->isDirty() ) - { - m_core->revertDevice( selectedDevice() ); - } - - // if the partition is unallocated(free space), we don't replace it but create new one - // with the same first and last sector - Partition* selectedPartition - = static_cast< Partition* >( current.data( PartitionModel::PartitionPtrRole ).value< void* >() ); - if ( isPartitionFreeSpace( selectedPartition ) ) - { - //NOTE: if the selected partition is free space, we don't deal with - // a separate /home partition at all because there's no existing - // rootfs to read it from. - PartitionRole newRoles = PartitionRole( PartitionRole::Primary ); - PartitionNode* newParent = selectedDevice()->partitionTable(); - - if ( selectedPartition->parent() ) - { - Partition* parent = dynamic_cast< Partition* >( selectedPartition->parent() ); - if ( parent && parent->roles().has( PartitionRole::Extended ) ) - { - newRoles = PartitionRole( PartitionRole::Logical ); - newParent = findPartitionByPath( { selectedDevice() }, parent->partitionPath() ); - } - } - - m_core->layoutApply( selectedDevice(), - selectedPartition->firstSector(), - selectedPartition->lastSector(), - m_config->luksFileSystemType(), - m_encryptWidget->passphrase(), - newParent, - newRoles ); - } - else - { - // We can't use the PartitionPtrRole because we need to make changes to the - // main DeviceModel, not the immutable copy. - QString partPath = current.data( PartitionModel::PartitionPathRole ).toString(); - selectedPartition = findPartitionByPath( { selectedDevice() }, partPath ); - if ( selectedPartition ) - { - // Find out is the selected partition has a rootfs. If yes, then make the - // m_reuseHomeCheckBox visible and set its text to something meaningful. - homePartitionPath->clear(); - for ( const OsproberEntry& osproberEntry : m_core->osproberEntries() ) - { - if ( osproberEntry.path == partPath ) - { - *homePartitionPath = osproberEntry.homePath; - } - } - if ( homePartitionPath->isEmpty() ) - { - doReuseHomePartition = false; - } - - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - - PartitionActions::doReplacePartition( m_core, - selectedDevice(), - selectedPartition, - { gs->value( "defaultPartitionType" ).toString(), - m_config->replaceModeFilesystem(), - m_config->luksFileSystemType(), - m_encryptWidget->passphrase() } ); - Partition* homePartition = findPartitionByPath( { selectedDevice() }, *homePartitionPath ); - - if ( homePartition && doReuseHomePartition ) - { - PartitionInfo::setMountPoint( homePartition, "/home" ); - gs->insert( "reuseHome", true ); - } - else - { - gs->insert( "reuseHome", false ); - } - } - } - }, - m_reuseHomeCheckBox->isChecked() ), - [ this, homePartitionPath ] - { - m_reuseHomeCheckBox->setVisible( !homePartitionPath->isEmpty() ); - if ( !homePartitionPath->isEmpty() ) - { - m_reuseHomeCheckBox->setText( tr( "Reuse %1 as home partition for %2", "@label" ) - .arg( *homePartitionPath ) - .arg( Calamares::Branding::instance()->shortProductName() ) ); - } - delete homePartitionPath; - - if ( m_isEfi ) - { - setupEfiSystemPartitionSelector(); - } - - updateNextEnabled(); - if ( !m_bootloaderComboBox.isNull() && m_bootloaderComboBox->currentIndex() < 0 ) - { - m_bootloaderComboBox->setCurrentIndex( m_lastSelectedDeviceIndex ); - } - }, - this ); -} - -/** - * @brief clear and then rebuild the contents of the preview widget - * - * The preview widget for the current disk is completely re-constructed - * based on the on-disk state. This also triggers a rescan in the - * PCM to get a Device* copy that's unaffected by subsequent PCM changes. - */ -void -ChoicePage::updateDeviceStatePreview() -{ - //FIXME: this needs to be made async because the rescan can block the UI thread for - // a while. --Teo 10/2015 - Device* currentDevice = selectedDevice(); - Q_ASSERT( currentDevice ); - QMutexLocker locker( &m_previewsMutex ); - - cDebug() << "Updating partitioning state widgets."; - qDeleteAll( m_previewBeforeFrame->children() ); - - auto layout = m_previewBeforeFrame->layout(); - if ( layout ) - { - layout->deleteLater(); // Doesn't like nullptr - } - - layout = new QVBoxLayout; - m_previewBeforeFrame->setLayout( layout ); - Calamares::unmarginLayout( layout ); - layout->setSpacing( 6 ); - - PartitionBarsView::NestedPartitionsMode mode - = Calamares::JobQueue::instance()->globalStorage()->value( "drawNestedPartitions" ).toBool() - ? PartitionBarsView::DrawNestedPartitions - : PartitionBarsView::NoNestedPartitions; - m_beforePartitionBarsView = new PartitionBarsView( m_previewBeforeFrame ); - m_beforePartitionBarsView->setNestedPartitionsMode( mode ); - m_beforePartitionLabelsView = new PartitionLabelsView( m_previewBeforeFrame ); - m_beforePartitionLabelsView->setExtendedPartitionHidden( mode == PartitionBarsView::NoNestedPartitions ); - - Device* deviceBefore = m_core->immutableDeviceCopy( currentDevice ); - - PartitionModel* model = new PartitionModel( m_beforePartitionBarsView ); - model->init( deviceBefore, m_core->osproberEntries() ); - - m_beforePartitionBarsView->setModel( model ); - m_beforePartitionLabelsView->setModel( model ); - - // Make the bars and labels view use the same selectionModel. - auto sm = m_beforePartitionLabelsView->selectionModel(); - m_beforePartitionLabelsView->setSelectionModel( m_beforePartitionBarsView->selectionModel() ); - if ( sm ) - { - sm->deleteLater(); - } - - switch ( m_config->installChoice() ) - { - case InstallChoice::Replace: - case InstallChoice::Alongside: - m_beforePartitionBarsView->setSelectionMode( QAbstractItemView::SingleSelection ); - m_beforePartitionLabelsView->setSelectionMode( QAbstractItemView::SingleSelection ); - break; - case InstallChoice::NoChoice: - case InstallChoice::Erase: - case InstallChoice::Manual: - m_beforePartitionBarsView->setSelectionMode( QAbstractItemView::NoSelection ); - m_beforePartitionLabelsView->setSelectionMode( QAbstractItemView::NoSelection ); - } - - layout->addWidget( m_beforePartitionBarsView ); - layout->addWidget( m_beforePartitionLabelsView ); -} - -/** - * @brief rebuild the contents of the preview for the PCM-proposed state. - * - * No rescans here, this should be immediate. - * - * @param choice the chosen partitioning action. - */ -void -ChoicePage::updateActionChoicePreview( InstallChoice choice ) -{ - Device* currentDevice = selectedDevice(); - Q_ASSERT( currentDevice ); - - QMutexLocker locker( &m_previewsMutex ); - - cDebug() << "Updating partitioning preview widgets."; - qDeleteAll( m_previewAfterFrame->children() ); - - auto oldlayout = m_previewAfterFrame->layout(); - if ( oldlayout ) - { - oldlayout->deleteLater(); - } - - QVBoxLayout* layout = new QVBoxLayout; - m_previewAfterFrame->setLayout( layout ); - Calamares::unmarginLayout( layout ); - layout->setSpacing( 6 ); - - PartitionBarsView::NestedPartitionsMode mode - = Calamares::JobQueue::instance()->globalStorage()->value( "drawNestedPartitions" ).toBool() - ? PartitionBarsView::DrawNestedPartitions - : PartitionBarsView::NoNestedPartitions; - - m_reuseHomeCheckBox->hide(); - Calamares::JobQueue::instance()->globalStorage()->insert( "reuseHome", false ); - - switch ( choice ) - { - case InstallChoice::Alongside: - { - if ( m_enableEncryptionWidget ) - { - m_encryptWidget->show(); - } - m_previewBeforeLabel->setText( tr( "Current:", "@label" ) ); - m_selectLabel->setText( tr( "Select a partition to shrink, " - "then drag the bottom bar to resize" ) ); - m_selectLabel->show(); - - m_afterPartitionSplitterWidget = new PartitionSplitterWidget( m_previewAfterFrame ); - m_afterPartitionSplitterWidget->init( selectedDevice(), mode == PartitionBarsView::DrawNestedPartitions ); - layout->addWidget( m_afterPartitionSplitterWidget ); - - QLabel* sizeLabel = new QLabel( m_previewAfterFrame ); - layout->addWidget( sizeLabel ); - sizeLabel->setWordWrap( true ); - - if ( !m_isEfi ) - { - layout->addWidget( createBootloaderPanel() ); - } - - connect( m_afterPartitionSplitterWidget, - &PartitionSplitterWidget::partitionResized, - this, - [ this, sizeLabel ]( const QString& path, qint64 size, qint64 sizeNext ) - { - Q_UNUSED( path ) - sizeLabel->setText( - tr( "%1 will be shrunk to %2MiB and a new " - "%3MiB partition will be created for %4.", "@info, %1 is partition name, %4 is product name" ) - .arg( m_beforePartitionBarsView->selectionModel()->currentIndex().data().toString() ) - .arg( Calamares::BytesToMiB( size ) ) - .arg( Calamares::BytesToMiB( sizeNext ) ) - .arg( Calamares::Branding::instance()->shortProductName() ) ); - } ); - - m_previewAfterFrame->show(); - m_previewAfterLabel->show(); - - SelectionFilter filter = []( const QModelIndex& index ) - { - return PartUtils::canBeResized( - static_cast< Partition* >( index.data( PartitionModel::PartitionPtrRole ).value< void* >() ), - Logger::Once() ); - }; - m_beforePartitionBarsView->setSelectionFilter( filter ); - m_beforePartitionLabelsView->setSelectionFilter( filter ); - - break; - } - case InstallChoice::Erase: - case InstallChoice::Replace: - { - m_encryptWidget->setVisible( shouldShowEncryptWidget( choice ) ); - m_previewBeforeLabel->setText( tr( "Current:", "@label" ) ); - m_afterPartitionBarsView = new PartitionBarsView( m_previewAfterFrame ); - m_afterPartitionBarsView->setNestedPartitionsMode( mode ); - m_afterPartitionLabelsView = new PartitionLabelsView( m_previewAfterFrame ); - m_afterPartitionLabelsView->setExtendedPartitionHidden( mode == PartitionBarsView::NoNestedPartitions ); - m_afterPartitionLabelsView->setCustomNewRootLabel( - Calamares::Branding::instance()->string( Calamares::Branding::BootloaderEntryName ) ); - - PartitionModel* model = m_core->partitionModelForDevice( selectedDevice() ); - - // The QObject parents tree is meaningful for memory management here, - // see qDeleteAll above. - m_afterPartitionBarsView->setModel( model ); - m_afterPartitionLabelsView->setModel( model ); - m_afterPartitionBarsView->setSelectionMode( QAbstractItemView::NoSelection ); - m_afterPartitionLabelsView->setSelectionMode( QAbstractItemView::NoSelection ); - - layout->addWidget( m_afterPartitionBarsView ); - layout->addWidget( m_afterPartitionLabelsView ); - - if ( !m_isEfi ) - { - layout->addWidget( createBootloaderPanel() ); - } - - m_previewAfterFrame->show(); - m_previewAfterLabel->show(); - - if ( m_config->installChoice() == InstallChoice::Erase ) - { - m_selectLabel->hide(); - } - else - { - SelectionFilter filter = []( const QModelIndex& index ) - { - return PartUtils::canBeReplaced( - static_cast< Partition* >( index.data( PartitionModel::PartitionPtrRole ).value< void* >() ), - Logger::Once() ); - }; - m_beforePartitionBarsView->setSelectionFilter( filter ); - m_beforePartitionLabelsView->setSelectionFilter( filter ); - - m_selectLabel->show(); - m_selectLabel->setText( tr( "Select a partition to install on", "@label" ) ); - } - - break; - } - case InstallChoice::NoChoice: - case InstallChoice::Manual: - m_selectLabel->hide(); - m_previewAfterFrame->hide(); - m_previewBeforeLabel->setText( tr( "Current:", "@label" ) ); - m_previewAfterLabel->hide(); - m_encryptWidget->hide(); - break; - } - - if ( m_isEfi - && ( m_config->installChoice() == InstallChoice::Alongside - || m_config->installChoice() == InstallChoice::Replace ) ) - { - QHBoxLayout* efiLayout = new QHBoxLayout; - layout->addLayout( efiLayout ); - m_efiLabel = new QLabel( m_previewAfterFrame ); - efiLayout->addWidget( m_efiLabel ); - m_efiComboBox = new QComboBox( m_previewAfterFrame ); - efiLayout->addWidget( m_efiComboBox ); - m_efiLabel->setBuddy( m_efiComboBox ); - m_efiComboBox->hide(); - efiLayout->addStretch(); - } - - // Also handle selection behavior on beforeFrame. - QAbstractItemView::SelectionMode previewSelectionMode = QAbstractItemView::NoSelection; - switch ( m_config->installChoice() ) - { - case InstallChoice::Replace: - case InstallChoice::Alongside: - previewSelectionMode = QAbstractItemView::SingleSelection; - break; - case InstallChoice::NoChoice: - case InstallChoice::Erase: - case InstallChoice::Manual: - previewSelectionMode = QAbstractItemView::NoSelection; - } - - m_beforePartitionBarsView->setSelectionMode( previewSelectionMode ); - m_beforePartitionLabelsView->setSelectionMode( previewSelectionMode ); - - updateNextEnabled(); -} - -void -ChoicePage::setupEfiSystemPartitionSelector() -{ - Q_ASSERT( m_isEfi ); - - // Only the already existing ones: - QList< Partition* > efiSystemPartitions = m_core->efiSystemPartitions(); - - if ( efiSystemPartitions.count() == 0 ) //should never happen - { - m_efiLabel->setText( tr( "An EFI system partition cannot be found anywhere " - "on this system. Please go back and use manual " - "partitioning to set up %1.", "@info, %1 is product name" ) - .arg( Calamares::Branding::instance()->shortProductName() ) ); - updateNextEnabled(); - } - else if ( efiSystemPartitions.count() == 1 ) //probably most usual situation - { - m_efiLabel->setText( tr( "The EFI system partition at %1 will be used for " - "starting %2.", "@info, %1 is partition path, %2 is product name" ) - .arg( efiSystemPartitions.first()->partitionPath() ) - .arg( Calamares::Branding::instance()->shortProductName() ) ); - } - else - { - m_efiComboBox->show(); - m_efiLabel->setText( tr( "EFI system partition:", "@label" ) ); - 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 ) - { - m_efiComboBox->setCurrentIndex( i ); - } - } - } -} - -static inline void -force_uncheck( QButtonGroup* grp, PrettyRadioButton* button ) -{ - button->hide(); - grp->setExclusive( false ); - button->setChecked( false ); - grp->setExclusive( true ); -} - -static inline QDebug& -operator<<( QDebug& s, PartitionIterator& it ) -{ - s << ( ( *it ) ? ( *it )->deviceNode() : QString( "" ) ); - return s; -} - -QString -describePartitionTypes( const QStringList& types ) -{ - if ( types.empty() ) - { - return QCoreApplication::translate( - ChoicePage::staticMetaObject.className(), "any", "any partition-table type" ); - } - if ( types.size() == 1 ) - { - return types.first(); - } - if ( types.size() == 2 ) - { - return QCoreApplication::translate( - ChoicePage::staticMetaObject.className(), "%1 or %2", "partition-table types" ) - .arg( types.at( 0 ), types.at( 1 ) ); - } - // More than two, rather unlikely - return types.join( ", " ); -} - -/** - * @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 -ChoicePage::setupActions() -{ - Logger::Once o; - - Device* currentDevice = selectedDevice(); - OsproberEntryList osproberEntriesForCurrentDevice = getOsproberEntriesForDevice( currentDevice ); - - cDebug() << o << "Setting up actions for" << currentDevice->deviceNode() << "with" - << osproberEntriesForCurrentDevice.count() << "entries."; - - if ( currentDevice->partitionTable() ) - { - m_deviceInfoWidget->setPartitionTableType( currentDevice->partitionTable()->type() ); - } - else - { - m_deviceInfoWidget->setPartitionTableType( PartitionTable::unknownTableType ); - } - - if ( m_config->allowManualPartitioning() ) - { - m_somethingElseButton->show(); - } - else - { - force_uncheck( m_grp, m_somethingElseButton ); - } - - bool atLeastOneCanBeResized = false; - bool atLeastOneCanBeReplaced = false; - bool atLeastOneIsMounted = false; // Suppress 'erase' if so - bool isInactiveRAID = false; - bool matchTableType = false; - - 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; - } - - 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"; - m_messageLabel->setText( tr( "This storage device does not seem to have an operating system on it. " - "What would you like to do?
    " - "You will be able to review and confirm your choices " - "before any change is made to the storage device." ) ); - - m_eraseButton->setText( tr( "Erase disk
    " - "This will delete all data " - "currently present on the selected storage device." ) ); - - m_alongsideButton->setText( tr( "Install alongside
    " - "The installer will shrink a partition to make room for %1." ) - .arg( Calamares::Branding::instance()->shortVersionedName() ) ); - - m_replaceButton->setText( tr( "Replace a partition
    " - "Replaces a partition with %1." ) - .arg( Calamares::Branding::instance()->shortVersionedName() ) ); ); - - m_replaceButton->hide(); - m_alongsideButton->hide(); - m_grp->setExclusive( false ); - m_replaceButton->setChecked( false ); - m_alongsideButton->setChecked( false ); - m_grp->setExclusive( true ); - } - else if ( osproberEntriesForCurrentDevice.count() == 1 ) - { - QString osName = osproberEntriesForCurrentDevice.first().prettyName; - - if ( !osName.isEmpty() ) - { - CALAMARES_RETRANSLATE( - cDebug() << "Setting texts for 1 non-empty osprober entry"; - m_messageLabel->setText( tr( "This storage device has %1 on it. " - "What would you like to do?
    " - "You will be able to review and confirm your choices " - "before any change is made to the storage device." ) - .arg( osName ) ); - - m_alongsideButton->setText( tr( "Install alongside
    " - "The installer will shrink a partition to make room for %1." ) - .arg( Calamares::Branding::instance()->shortVersionedName() ) ); - - m_eraseButton->setText( tr( "Erase disk
    " - "This will delete all data " - "currently present on the selected storage device." ) ); - - m_replaceButton->setText( tr( "Replace a partition
    " - "Replaces a partition with %1." ) - .arg( Calamares::Branding::instance()->shortVersionedName() ) ); ); - } - else - { - CALAMARES_RETRANSLATE( - cDebug() << "Setting texts for 1 empty osprober entry"; - m_messageLabel->setText( tr( "This storage device already has an operating system on it. " - "What would you like to do?
    " - "You will be able to review and confirm your choices " - "before any change is made to the storage device." ) ); - - m_alongsideButton->setText( tr( "Install alongside
    " - "The installer will shrink a partition to make room for %1." ) - .arg( Calamares::Branding::instance()->shortVersionedName() ) ); - - m_eraseButton->setText( tr( "Erase disk
    " - "This will delete all data " - "currently present on the selected storage device." ) ); - - m_replaceButton->setText( tr( "Replace a partition
    " - "Replaces a partition with %1." ) - .arg( Calamares::Branding::instance()->shortVersionedName() ) ); ); - } - } - else - { - // osproberEntriesForCurrentDevice has at least 2 items. - - CALAMARES_RETRANSLATE( - cDebug() << "Setting texts for >= 2 osprober entries"; - - m_messageLabel->setText( tr( "This storage device has multiple operating systems on it. " - "What would you like to do?
    " - "You will be able to review and confirm your choices " - "before any change is made to the storage device." ) ); - - m_alongsideButton->setText( tr( "Install alongside
    " - "The installer will shrink a partition to make room for %1." ) - .arg( Calamares::Branding::instance()->shortVersionedName() ) ); - - m_eraseButton->setText( tr( "Erase disk
    " - "This will delete all data " - "currently present on the selected storage device." ) ); - - m_replaceButton->setText( tr( "Replace a partition
    " - "Replaces a partition with %1." ) - .arg( Calamares::Branding::instance()->shortVersionedName() ) ); ); - } - -#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 ) - { - m_replaceButton->show(); - } - else - { - cDebug() << "No partitions available for replace-action."; - force_uncheck( m_grp, m_replaceButton ); - } - - if ( atLeastOneCanBeResized ) - { - m_alongsideButton->show(); - } - else - { - cDebug() << "No partitions available for resize-action."; - force_uncheck( m_grp, m_alongsideButton ); - } - - if ( !atLeastOneIsMounted && !isInactiveRAID ) - { - m_eraseButton->show(); // None mounted - } - else - { - cDebug() << "No partitions (" - << "any-mounted?" << atLeastOneIsMounted << "is-raid?" << isInactiveRAID << ") for erase-action."; - force_uncheck( m_grp, m_eraseButton ); - } - - 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."; - m_alongsideButton->hide(); - m_replaceButton->hide(); - } - - if ( tableType != PartitionTable::unknownTableType && !matchTableType ) - { - m_messageLabel->setText( tr( "This storage device already has an operating system on it, " - "but the partition table %1 is different from the " - "needed %2.
    " ) - .arg( PartitionTable::tableTypeToName( tableType ) ) - .arg( describePartitionTypes( m_config->partitionTableTypes() ) ) ); - m_messageLabel->show(); - - 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."; - m_eraseButton->show(); - m_alongsideButton->hide(); - m_replaceButton->hide(); - m_somethingElseButton->hide(); - cDebug() << "Replace button suppressed because partition table type mismatch."; - force_uncheck( m_grp, m_replaceButton ); - } - - if ( m_somethingElseButton->isHidden() && m_alongsideButton->isHidden() && m_replaceButton->isHidden() - && m_eraseButton->isHidden() ) - { - if ( atLeastOneIsMounted ) - { - m_messageLabel->setText( tr( "This storage device has one of its partitions mounted.", "@info" ) ); - } - else - { - m_messageLabel->setText( - tr( "This storage device is a part of an inactive RAID device.", "@info" ) ); - } - - m_messageLabel->show(); - cWarning() << "No buttons available" - << "replaced?" << atLeastOneCanBeReplaced << "resized?" << atLeastOneCanBeResized - << "erased? (not-mounted and not-raid)" << !atLeastOneIsMounted << "and" << !isInactiveRAID; - } -} - -OsproberEntryList -ChoicePage::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 -ChoicePage::isNextEnabled() const -{ - return m_nextEnabled; -} - -bool -ChoicePage::calculateNextEnabled() const -{ - auto sm_p = m_beforePartitionBarsView ? m_beforePartitionBarsView->selectionModel() : nullptr; - - switch ( m_config->installChoice() ) - { - case InstallChoice::NoChoice: - 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 for alongside or replace"; - return false; - } - break; - case InstallChoice::Erase: - case InstallChoice::Manual: - // Nothing to check for these - break; - } - - 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 && m_encryptWidget->isVisible() ) - { - switch ( m_encryptWidget->state() ) - { - case EncryptWidget::Encryption::Unconfirmed: - cDebug() << "No passphrase provided or passphrase mismatch."; - return false; - case EncryptWidget::Encryption::Disabled: - case EncryptWidget::Encryption::Confirmed: - // Checkbox not checked, **or** passphrases match - break; - } - } - - return true; -} - -void -ChoicePage::updateNextEnabled() -{ - bool enabled = calculateNextEnabled(); - - if ( enabled != m_nextEnabled ) - { - m_nextEnabled = enabled; - Q_EMIT nextStatusChanged( enabled ); - } -} - -void -ChoicePage::updateSwapChoicesTr() -{ - if ( !m_eraseSwapChoiceComboBox ) - { - return; - } - - static_assert( SwapChoice::NoSwap == 0, "Enum values out-of-sync" ); - for ( int index = 0; index < m_eraseSwapChoiceComboBox->count(); ++index ) - { - bool ok = false; - int value = 0; - - switch ( value = m_eraseSwapChoiceComboBox->itemData( index ).toInt( &ok ) ) - { - // case 0: - case SwapChoice::NoSwap: - // toInt() returns 0 on failure, so check for ok - if ( ok ) // It was explicitly set to 0 - { - m_eraseSwapChoiceComboBox->setItemText( index, tr( "No swap", "@label" ) ); - } - else - { - cWarning() << "Box item" << index << m_eraseSwapChoiceComboBox->itemText( index ) - << "has non-integer role."; - } - break; - case SwapChoice::ReuseSwap: - m_eraseSwapChoiceComboBox->setItemText( index, tr( "Reuse swap", "@label" ) ); - break; - case SwapChoice::SmallSwap: - m_eraseSwapChoiceComboBox->setItemText( index, tr( "Swap (no Hibernate)", "@label" ) ); - break; - case SwapChoice::FullSwap: - m_eraseSwapChoiceComboBox->setItemText( index, tr( "Swap (with Hibernate)", "@label" ) ); - break; - case SwapChoice::SwapFile: - m_eraseSwapChoiceComboBox->setItemText( index, tr( "Swap to file", "@label" ) ); - break; - default: - cWarning() << "Box item" << index << m_eraseSwapChoiceComboBox->itemText( index ) << "has role" << value; - } - } -} - -void -ChoicePage::updateChoiceButtonsTr() -{ - if ( m_somethingElseButton ) - { - m_somethingElseButton->setText( tr( "Manual partitioning
    " - "You can create or resize partitions yourself." ) ); - } -} - -int -ChoicePage::lastSelectedDeviceIndex() -{ - return m_lastSelectedDeviceIndex; -} - -void -ChoicePage::setLastSelectedDeviceIndex( int index ) -{ - m_lastSelectedDeviceIndex = index; - m_drivesCombo->setCurrentIndex( m_lastSelectedDeviceIndex ); -} - -QWidget* -ChoicePage::createBootloaderPanel() -{ - QWidget* panelWidget = new QWidget; - - QHBoxLayout* mainLayout = new QHBoxLayout; - panelWidget->setLayout( mainLayout ); - mainLayout->setContentsMargins( 0, 0, 0, 0 ); - QLabel* widgetLabel = new QLabel( panelWidget ); - mainLayout->addWidget( widgetLabel ); - widgetLabel->setText( tr( "Bootloader location:", "@label" ) ); - - QComboBox* comboForBootloader = new QComboBox( panelWidget ); - comboForBootloader->setModel( m_core->bootLoaderModel() ); - - // When the chosen bootloader device changes, we update the choice in the PCM - connect( comboForBootloader, - QOverload< int >::of( &QComboBox::currentIndexChanged ), - this, - [ this ]( int newIndex ) - { - QComboBox* bootloaderCombo = qobject_cast< QComboBox* >( sender() ); - if ( bootloaderCombo ) - { - QVariant var = bootloaderCombo->itemData( newIndex, BootLoaderModel::BootLoaderPathRole ); - if ( !var.isValid() ) - { - return; - } - m_core->setBootLoaderInstallPath( var.toString() ); - } - } ); - m_bootloaderComboBox = comboForBootloader; - - connect( m_core->bootLoaderModel(), - &QAbstractItemModel::modelReset, - [ this ]() - { - if ( !m_bootloaderComboBox.isNull() ) - { - Calamares::restoreSelectedBootLoader( *m_bootloaderComboBox, m_core->bootLoaderInstallPath() ); - } - } ); - connect( - m_core, - &PartitionCoreModule::deviceReverted, - this, - [ this ]( Device* ) - { - if ( !m_bootloaderComboBox.isNull() ) - { - if ( m_bootloaderComboBox->model() != m_core->bootLoaderModel() ) - { - m_bootloaderComboBox->setModel( m_core->bootLoaderModel() ); - } - - m_bootloaderComboBox->setCurrentIndex( m_lastSelectedDeviceIndex ); - } - }, - Qt::QueuedConnection ); - // ^ Must be Queued so it's sure to run when the widget is already visible. - - mainLayout->addWidget( m_bootloaderComboBox ); - widgetLabel->setBuddy( m_bootloaderComboBox ); - mainLayout->addStretch(); - - return panelWidget; -} - -bool -ChoicePage::shouldShowEncryptWidget( Config::InstallChoice choice ) const -{ - bool suitableFS = true; - if ( !m_config->allowZfsEncryption() - && ( ( m_eraseFsTypesChoiceComboBox && m_eraseFsTypesChoiceComboBox->isVisible() - && m_eraseFsTypesChoiceComboBox->currentText() == "zfs" ) - || ( m_replaceFsTypesChoiceComboBox && m_replaceFsTypesChoiceComboBox->isVisible() - && m_replaceFsTypesChoiceComboBox->currentText() == "zfs" ) ) ) - { - suitableFS = false; - } - - const bool suitableChoice - = choice == InstallChoice::Erase || choice == InstallChoice::Alongside || choice == InstallChoice::Replace; - return suitableChoice && m_enableEncryptionWidget && suitableFS; -} diff --git a/src/modules/partition/gui/ChoicePage.h b/src/modules/partition/gui/ChoicePage.h deleted file mode 100644 index 7deb4dec65..0000000000 --- a/src/modules/partition/gui/ChoicePage.h +++ /dev/null @@ -1,177 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2018-2019 Adriaan de Groot - * SPDX-FileCopyrightText: 2019 Collabora Ltd - * SPDX-FileCopyrightText: 2023 Evan James - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef CHOICEPAGE_H -#define CHOICEPAGE_H - -#include "ui_ChoicePage.h" - - -#include "Config.h" -#include "core/OsproberEntry.h" - -#include -#include -#include -#include - -class QBoxLayout; -class QComboBox; -class QLabel; -class QListView; - -namespace Calamares -{ -namespace Widgets -{ -class PrettyRadioButton; -} // namespace Widgets -} // namespace Calamares - -class Config; -class DeviceInfoWidget; -class PartitionBarsView; -class PartitionSplitterWidget; -class PartitionLabelsView; -class PartitionCoreModule; - -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 ChoicePage : public QWidget, private Ui::ChoicePage -{ - Q_OBJECT -public: - explicit ChoicePage( Config* config, QWidget* parent = nullptr ); - ~ChoicePage() override; - - /** - * @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 ); - -signals: - void nextStatusChanged( bool ); - void actionChosen(); - void deviceChosen(); - -private slots: - void onPartitionToReplaceSelected( const QModelIndex& current, const QModelIndex& previous ); - void doReplaceSelectedPartition( const QModelIndex& current ); - void doAlongsideSetupSplitter( const QModelIndex& current, const QModelIndex& previous ); - void onEncryptWidgetStateChanged(); - void onHomeCheckBoxStateChanged(); - - /// @brief Calls applyActionChoice() as needed. - void onActionChanged(); - /// @brief Calls onActionChanged() as needed. - void onEraseSwapChoiceChanged(); - - void retranslate(); - -private: - bool calculateNextEnabled() const; - void updateNextEnabled(); - void setupChoices(); - void checkInstallChoiceRadioButton( Config::InstallChoice choice ); ///< Sets the chosen button to "on" - /** @brief Create a panel with "boot loader location:" - * - * Panel + dropdown and handling for model updates. Returns a pointer - * to the panel's widget. - */ - QWidget* createBootloaderPanel(); - Device* selectedDevice(); - - /* Change the UI depending on the device selected. */ - void hideButtons(); // Hide everything when no device - void applyDeviceChoice(); // Start scanning new device - void continueApplyDeviceChoice(); // .. called after scan - - void updateDeviceStatePreview(); - void updateActionChoicePreview( Config::InstallChoice choice ); - bool shouldShowEncryptWidget( Config::InstallChoice choice ) const; - void setupActions(); - OsproberEntryList getOsproberEntriesForDevice( Device* device ) const; - void doAlongsideApply(); - void setupEfiSystemPartitionSelector(); - - // Translations support - void updateSwapChoicesTr(); - void updateChoiceButtonsTr(); - - Config* m_config; - bool m_nextEnabled; - PartitionCoreModule* m_core; - - QMutex m_previewsMutex; - - bool m_isEfi; - QComboBox* m_drivesCombo; - - QButtonGroup* m_grp; - Calamares::Widgets::PrettyRadioButton* m_alongsideButton; - Calamares::Widgets::PrettyRadioButton* m_eraseButton; - Calamares::Widgets::PrettyRadioButton* m_replaceButton; - Calamares::Widgets::PrettyRadioButton* m_somethingElseButton; - QComboBox* m_eraseSwapChoiceComboBox = nullptr; // UI, see also Config's swap choice - QComboBox* m_eraseFsTypesChoiceComboBox = nullptr; // UI, see also Config's erase-mode FS - QComboBox* m_replaceFsTypesChoiceComboBox = nullptr; // UI, see also Config's erase-mode FS - - - DeviceInfoWidget* m_deviceInfoWidget; - - QPointer< PartitionBarsView > m_beforePartitionBarsView; - QPointer< PartitionLabelsView > m_beforePartitionLabelsView; - QPointer< PartitionBarsView > m_afterPartitionBarsView; - QPointer< PartitionLabelsView > m_afterPartitionLabelsView; - QPointer< PartitionSplitterWidget > m_afterPartitionSplitterWidget; - QPointer< QComboBox > m_bootloaderComboBox; - QPointer< QLabel > m_efiLabel; - QPointer< QComboBox > m_efiComboBox; - - int m_lastSelectedDeviceIndex = -1; - - bool m_enableEncryptionWidget = false; - - QMutex m_coreMutex; -}; - -#endif // CHOICEPAGE_H diff --git a/src/modules/partition/gui/ChoicePage.ui b/src/modules/partition/gui/ChoicePage.ui deleted file mode 100644 index baceba0273..0000000000 --- a/src/modules/partition/gui/ChoicePage.ui +++ /dev/null @@ -1,224 +0,0 @@ - - - -SPDX-FileCopyrightText: 2015 Teo Mrnjavac <teo@kde.org> -SPDX-License-Identifier: GPL-3.0-or-later - - ChoicePage - - - - 0 - 0 - 743 - 512 - - - - Form - - - - 0 - - - - - - - - - - <m_drivesLabel> - - - - - - - - - - - - - - <m_messageLabel> - - - - - - - QFrame::NoFrame - - - QFrame::Plain - - - 0 - - - true - - - - - 0 - 0 - 729 - 233 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - QFrame::HLine - - - QFrame::Raised - - - - - - - - - - <m_reuseHomeCheckBox> - - - - - - - - - - - - - - 0 - - - - - 0 - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 8 - - - - - - - - After: - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - - - 0 - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 8 - - - - - - - - Before: - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - - - - - - - - - - EncryptWidget - QWidget -
    gui/EncryptWidget.h
    - 1 -
    -
    - - -
    diff --git a/src/modules/partition/gui/CreatePartitionDialog.cpp b/src/modules/partition/gui/CreatePartitionDialog.cpp deleted file mode 100644 index d186761381..0000000000 --- a/src/modules/partition/gui/CreatePartitionDialog.cpp +++ /dev/null @@ -1,362 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2018 2020, Adriaan de Groot - * SPDX-FileCopyrightText: 2018 Andrius Štikonas - * SPDX-FileCopyrightText: 2018 Caio Carvalho - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "CreatePartitionDialog.h" -#include "ui_CreatePartitionDialog.h" - -#include "core/ColorUtils.h" -#include "core/KPMHelpers.h" -#include "core/PartUtils.h" -#include "core/PartitionInfo.h" -#include "gui/PartitionDialogHelpers.h" -#include "gui/PartitionSizeController.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "Settings.h" -#include "partition/FileSystem.h" -#include "partition/PartitionQuery.h" -#include "utils/Logger.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -using Calamares::Partition::untranslatedFS; -using Calamares::Partition::userVisibleFS; - -static QSet< FileSystem::Type > s_unmountableFS( { FileSystem::Unformatted, - FileSystem::LinuxSwap, - FileSystem::Extended, - FileSystem::Unknown, - FileSystem::Lvm2_PV } ); - -CreatePartitionDialog::CreatePartitionDialog( Device* device, - PartitionNode* parentPartition, - const QStringList& usedMountPoints, - QWidget* parentWidget ) - : QDialog( parentWidget ) - , m_ui( new Ui_CreatePartitionDialog ) - , m_partitionSizeController( new PartitionSizeController( this ) ) - , m_device( device ) - , m_parent( parentPartition ) - , m_usedMountPoints( usedMountPoints ) -{ - m_ui->setupUi( this ); - m_ui->encryptWidget->setText( tr( "En&crypt", "@action" ) ); - m_ui->encryptWidget->hide(); - - if ( m_device->type() != Device::Type::LVM_Device ) - { - m_ui->lvNameLabel->hide(); - m_ui->lvNameLineEdit->hide(); - } - if ( m_device->type() == Device::Type::LVM_Device ) - { - /* LVM logical volume name can consist of: letters numbers _ . - + - * It cannot start with underscore _ and must not be equal to . or .. or any entry in /dev/ - * QLineEdit accepts QValidator::Intermediate, so we just disable . at the beginning */ - QRegularExpression re( QStringLiteral( R"(^(?!_|\.)[\w\-.+]+)" ) ); - QRegularExpressionValidator* validator = new QRegularExpressionValidator( re, this ); - m_ui->lvNameLineEdit->setValidator( validator ); - } - - if ( device->partitionTable()->type() == PartitionTable::msdos - || device->partitionTable()->type() == PartitionTable::msdos_sectorbased ) - { - initMbrPartitionTypeUi(); - } - else - { - initGptPartitionTypeUi(); - } - - // File system; the config value is translated (best-effort) to a type - FileSystem::Type defaultFSType; - QString untranslatedFSName = PartUtils::canonicalFilesystemName( - Calamares::JobQueue::instance()->globalStorage()->value( "defaultFileSystemType" ).toString(), &defaultFSType ); - if ( defaultFSType == FileSystem::Type::Unknown ) - { - defaultFSType = FileSystem::Type::Ext4; - } - - int defaultFsIndex = -1; - int fsCounter = 0; - QStringList fsNames; - for ( auto fs : FileSystemFactory::map() ) - { - // We need to ensure zfs is added to the list if the zfs module is enabled - if ( ( fs->type() == FileSystem::Type::Zfs && Calamares::Settings::instance()->isModuleEnabled( "zfs" ) ) - || ( fs->supportCreate() != FileSystem::cmdSupportNone && fs->type() != FileSystem::Extended ) ) - { - fsNames << userVisibleFS( fs ); // This is put into the combobox - if ( fs->type() == defaultFSType ) - { - defaultFsIndex = fsCounter; - } - fsCounter++; - } - } - m_ui->fsComboBox->addItems( fsNames ); - - // Connections - connect( m_ui->fsComboBox, SIGNAL( activated( int ) ), SLOT( updateMountPointUi() ) ); - connect( m_ui->extendedRadioButton, SIGNAL( toggled( bool ) ), SLOT( updateMountPointUi() ) ); - - connect( m_ui->mountPointComboBox, - &QComboBox::currentTextChanged, - this, - &CreatePartitionDialog::checkMountPointSelection ); - - // Select a default - m_ui->fsComboBox->setCurrentIndex( defaultFsIndex ); - updateMountPointUi(); - checkMountPointSelection(); -} - -CreatePartitionDialog::CreatePartitionDialog( Device* device, - const FreeSpace& freeSpacePartition, - const QStringList& usedMountPoints, - QWidget* parentWidget ) - : CreatePartitionDialog( device, freeSpacePartition.p->parent(), usedMountPoints, parentWidget ) -{ - standardMountPoints( *( m_ui->mountPointComboBox ), QString() ); - setFlagList( *( m_ui->m_listFlags ), - static_cast< PartitionTable::Flags >( ~PartitionTable::Flags::Int( 0 ) ), - PartitionTable::Flags() ); - initPartResizerWidget( freeSpacePartition.p ); -} - -CreatePartitionDialog::CreatePartitionDialog( Device* device, - const FreshPartition& existingNewPartition, - const QStringList& usedMountPoints, - QWidget* parentWidget ) - : CreatePartitionDialog( device, existingNewPartition.p->parent(), usedMountPoints, parentWidget ) -{ - standardMountPoints( *( m_ui->mountPointComboBox ), PartitionInfo::mountPoint( existingNewPartition.p ) ); - setFlagList( *( m_ui->m_listFlags ), - static_cast< PartitionTable::Flags >( ~PartitionTable::Flags::Int( 0 ) ), - PartitionInfo::flags( existingNewPartition.p ) ); - - const bool isExtended = existingNewPartition.p->roles().has( PartitionRole::Extended ); - if ( isExtended ) - { - cDebug() << "Editing extended partitions is not supported."; - return; - } - - initPartResizerWidget( existingNewPartition.p ); - - FileSystem::Type fsType = existingNewPartition.p->fileSystem().type(); - m_ui->fsComboBox->setCurrentText( FileSystem::nameForType( fsType ) ); - - setSelectedMountPoint( m_ui->mountPointComboBox, PartitionInfo::mountPoint( existingNewPartition.p ) ); - updateMountPointUi(); -} - -CreatePartitionDialog::~CreatePartitionDialog() {} - - -PartitionTable::Flags -CreatePartitionDialog::newFlags() const -{ - return flagsFromList( *( m_ui->m_listFlags ) ); -} - -void -CreatePartitionDialog::initMbrPartitionTypeUi() -{ - QString fixedPartitionString; - bool parentIsPartitionTable = m_parent->isRoot(); - if ( !parentIsPartitionTable ) - { - m_role = PartitionRole( PartitionRole::Logical ); - fixedPartitionString = tr( "Logical", "@label" ); - } - else if ( m_device->partitionTable()->hasExtended() ) - { - m_role = PartitionRole( PartitionRole::Primary ); - fixedPartitionString = tr( "Primary", "@label" ); - } - - if ( fixedPartitionString.isEmpty() ) - { - m_ui->fixedPartitionLabel->hide(); - } - else - { - m_ui->fixedPartitionLabel->setText( fixedPartitionString ); - m_ui->primaryRadioButton->hide(); - m_ui->extendedRadioButton->hide(); - } -} - -void -CreatePartitionDialog::initGptPartitionTypeUi() -{ - m_role = PartitionRole( PartitionRole::Primary ); - m_ui->fixedPartitionLabel->setText( tr( "GPT", "@label" ) ); - m_ui->primaryRadioButton->hide(); - m_ui->extendedRadioButton->hide(); -} - -Partition* -CreatePartitionDialog::getNewlyCreatedPartition() -{ - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - - if ( m_role.roles() == PartitionRole::None ) - { - m_role = PartitionRole( m_ui->extendedRadioButton->isChecked() ? PartitionRole::Extended - : PartitionRole::Primary ); - } - - qint64 first = m_partitionSizeController->firstSector(); - qint64 last = m_partitionSizeController->lastSector(); - - FileSystem::Type fsType = m_role.has( PartitionRole::Extended ) - ? FileSystem::Extended - : FileSystem::typeForName( m_ui->fsComboBox->currentText() ); - const QString fsLabel = m_ui->filesystemLabelEdit->text(); - - // The newly-created partitions have no flags set (no **active** flags), - // because they're new. The desired flags can be retrieved from - // newFlags() and the consumer (see PartitionPage::onCreateClicked) - // does so, to set up the partition for create-and-then-set-flags. - Partition* partition = nullptr; - QString luksFsType = gs->value( "luksFileSystemType" ).toString(); - QString luksPassphrase = m_ui->encryptWidget->passphrase(); - if ( m_ui->encryptWidget->state() == EncryptWidget::Encryption::Confirmed && !luksPassphrase.isEmpty() - && fsType != FileSystem::Zfs ) - { - partition = KPMHelpers::createNewEncryptedPartition( - m_parent, - *m_device, - m_role, - fsType, - fsLabel, - first, - last, - Config::luksGenerationNames().find( luksFsType, Config::LuksGeneration::Luks1 ), - luksPassphrase, - PartitionTable::Flags() ); - } - else - { - partition = KPMHelpers::createNewPartition( - m_parent, *m_device, m_role, fsType, fsLabel, first, last, PartitionTable::Flags() ); - } - - // For zfs, we let the zfs module handle the encryption but we need to make the passphrase available to later modules - if ( fsType == FileSystem::Zfs ) - { - Calamares::GlobalStorage* storage = Calamares::JobQueue::instance()->globalStorage(); - QList< QVariant > zfsInfoList; - QVariantMap zfsInfo; - - // If this is not the first encrypted zfs partition, get the old list first - if ( storage->contains( "zfsInfo" ) ) - { - zfsInfoList = storage->value( "zfsInfo" ).toList(); - storage->remove( "zfsInfo" ); - } - - // Save the information subsequent modules will need - zfsInfo[ "encrypted" ] - = m_ui->encryptWidget->state() == EncryptWidget::Encryption::Confirmed && !luksPassphrase.isEmpty(); - zfsInfo[ "passphrase" ] = luksPassphrase; - zfsInfo[ "mountpoint" ] = selectedMountPoint( m_ui->mountPointComboBox ); - - // Add it to the list and insert it into global storage - zfsInfoList.append( zfsInfo ); - storage->insert( "zfsInfo", zfsInfoList ); - } - - if ( m_device->type() == Device::Type::LVM_Device ) - { - partition->setPartitionPath( m_device->deviceNode() + QStringLiteral( "/" ) - + m_ui->lvNameLineEdit->text().trimmed() ); - } - - PartitionInfo::setMountPoint( partition, selectedMountPoint( m_ui->mountPointComboBox ) ); - PartitionInfo::setFormat( partition, true ); - - return partition; -} - -void -CreatePartitionDialog::updateMountPointUi() -{ - bool enabled = m_ui->primaryRadioButton->isChecked(); - if ( enabled ) - { - // This maps translated (user-visible) FS names to a type - FileSystem::Type type = FileSystem::typeForName( m_ui->fsComboBox->currentText() ); - enabled = !s_unmountableFS.contains( type ); - - if ( FileSystemFactory::map()[ FileSystem::Type::Luks ]->supportCreate() && FS::luks::canEncryptType( type ) - && !m_role.has( PartitionRole::Extended ) ) - { - m_ui->encryptWidget->show(); - m_ui->encryptWidget->reset(); - } - else if ( FileSystemFactory::map()[ FileSystem::Type::Luks2 ]->supportCreate() - && FS::luks2::canEncryptType( type ) && !m_role.has( PartitionRole::Extended ) ) - { - m_ui->encryptWidget->show(); - m_ui->encryptWidget->reset(); - } - else - { - m_ui->encryptWidget->reset(); - m_ui->encryptWidget->hide(); - } - } - m_ui->mountPointLabel->setEnabled( enabled ); - m_ui->mountPointComboBox->setEnabled( enabled ); - if ( !enabled ) - { - m_ui->mountPointComboBox->setCurrentText( QString() ); - } -} - -void -CreatePartitionDialog::checkMountPointSelection() -{ - validateMountPoint( selectedMountPoint( m_ui->mountPointComboBox ), - m_usedMountPoints, - m_ui->mountPointExplanation, - m_ui->buttonBox->button( QDialogButtonBox::Ok ) ); -} - -void -CreatePartitionDialog::initPartResizerWidget( Partition* partition ) -{ - QColor color = Calamares::Partition::isPartitionFreeSpace( partition ) - ? ColorUtils::colorForPartitionInFreeSpace( partition ) - : ColorUtils::colorForPartition( partition ); - m_partitionSizeController->init( m_device, partition, color ); - m_partitionSizeController->setPartResizerWidget( m_ui->partResizerWidget ); - m_partitionSizeController->setSpinBox( m_ui->sizeSpinBox ); -} diff --git a/src/modules/partition/gui/CreatePartitionDialog.h b/src/modules/partition/gui/CreatePartitionDialog.h deleted file mode 100644 index 38c65aaf6e..0000000000 --- a/src/modules/partition/gui/CreatePartitionDialog.h +++ /dev/null @@ -1,98 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef CREATEPARTITIONDIALOG_H -#define CREATEPARTITIONDIALOG_H - -// KPMcore -#include -#include - -#include -#include - - -class Device; -class Partition; -class PartitionNode; -class PartitionSizeController; -class Ui_CreatePartitionDialog; - -/** - * The dialog which is shown to create a new partition or to edit a - * to-be-created partition. - */ -class CreatePartitionDialog : public QDialog -{ - Q_OBJECT - -private: - /** @brief Delegated constructor - * - * This does all the shared UI setup. - */ - CreatePartitionDialog( Device* device, - PartitionNode* parentPartition, - const QStringList& usedMountPoints, - QWidget* parentWidget ); - -public: - struct FreeSpace - { - Partition* p; - }; - struct FreshPartition - { - Partition* p; - }; - - /** @brief Dialog for editing a new partition based on free space. - * - * Creating from free space makes a wholly new partition with - * no flags set at all. - */ - CreatePartitionDialog( Device* device, - const FreeSpace& freeSpacePartition, - const QStringList& usedMountPoints, - QWidget* parentWidget = nullptr ); - /** @brief Dialog for editing a newly-created partition. - * - * A partition previously newly created (e.g. via this dialog - * and the constructor above) can be re-edited. - */ - CreatePartitionDialog( Device* device, - const FreshPartition& existingNewPartition, - const QStringList& usedMountPoints, - QWidget* parentWidget = nullptr ); - ~CreatePartitionDialog() override; - - Partition* getNewlyCreatedPartition(); - - PartitionTable::Flags newFlags() const; - -private Q_SLOTS: - void updateMountPointUi(); - void checkMountPointSelection(); - -private: - QScopedPointer< Ui_CreatePartitionDialog > m_ui; - PartitionSizeController* m_partitionSizeController; - Device* m_device; - PartitionNode* m_parent; - PartitionRole m_role = PartitionRole( PartitionRole::None ); - QStringList m_usedMountPoints; - - void initGptPartitionTypeUi(); - void initMbrPartitionTypeUi(); - void initPartResizerWidget( Partition* ); -}; - -#endif /* CREATEPARTITIONDIALOG_H */ diff --git a/src/modules/partition/gui/CreatePartitionDialog.ui b/src/modules/partition/gui/CreatePartitionDialog.ui deleted file mode 100644 index 0ee715fe05..0000000000 --- a/src/modules/partition/gui/CreatePartitionDialog.ui +++ /dev/null @@ -1,344 +0,0 @@ - - - -SPDX-FileCopyrightText: 2014 Aurélien Gâteau <agateau@kde.org> -SPDX-License-Identifier: GPL-3.0-or-later - - CreatePartitionDialog - - - - 0 - 0 - 763 - 689 - - - - Create a Partition - - - - - - - 0 - 0 - - - - - 0 - 59 - - - - - - - - - - Si&ze: - - - sizeSpinBox - - - - - - - MiB - - - - - - - Partition &Type: - - - primaryRadioButton - - - - - - - - - Primar&y - - - true - - - - - - - E&xtended - - - - - - - [fixed-partition-label] - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Vertical - - - - 20 - 13 - - - - - - - - Fi&le System: - - - fsComboBox - - - - - - - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 13 - - - - - - - - LVM LV name - - - - - - - - - - &Mount Point: - - - mountPointComboBox - - - - - - - - 0 - 0 - - - - true - - - -1 - - - - - - - Flags: - - - - - - - true - - - QAbstractItemView::NoSelection - - - true - - - - - - - Qt::Vertical - - - - 17 - 13 - - - - - - - - Label for the filesystem - - - 16 - - - - - - - FS Label: - - - - - - - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - PartResizerWidget - QWidget -
    kpmcore/gui/partresizerwidget.h
    - 1 -
    - - EncryptWidget - QWidget -
    gui/EncryptWidget.h
    - 1 -
    -
    - - primaryRadioButton - fsComboBox - - - - - buttonBox - accepted() - CreatePartitionDialog - accept() - - - 185 - 203 - - - 157 - 178 - - - - - buttonBox - rejected() - CreatePartitionDialog - reject() - - - 185 - 203 - - - 243 - 178 - - - - - extendedRadioButton - toggled(bool) - fsComboBox - setDisabled(bool) - - - 131 - 36 - - - 134 - 66 - - - - - extendedRadioButton - toggled(bool) - label_2 - setDisabled(bool) - - - 109 - 43 - - - 79 - 64 - - - - -
    diff --git a/src/modules/partition/gui/CreatePartitionTableDialog.ui b/src/modules/partition/gui/CreatePartitionTableDialog.ui deleted file mode 100644 index 4f9fe59177..0000000000 --- a/src/modules/partition/gui/CreatePartitionTableDialog.ui +++ /dev/null @@ -1,142 +0,0 @@ - - - -SPDX-FileCopyrightText: 2014 Aurélien Gâteau <agateau@kde.org> -SPDX-License-Identifier: GPL-3.0-or-later - - CreatePartitionTableDialog - - - - 0 - 0 - 297 - 182 - - - - - 0 - 0 - - - - Create Partition Table - - - - - - - 75 - true - - - - [are-you-sure-message] - - - - - - - Creating a new partition table will delete all existing data on the disk. - - - true - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 24 - - - - - - - - What kind of partition table do you want to create? - - - - - - - Master Boot Record (MBR) - - - true - - - - - - - GUID Partition Table (GPT) - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - mbrRadioButton - gptRadioButton - buttonBox - - - - - buttonBox - accepted() - CreatePartitionTableDialog - accept() - - - 222 - 141 - - - 157 - 155 - - - - - buttonBox - rejected() - CreatePartitionTableDialog - reject() - - - 290 - 147 - - - 286 - 155 - - - - - diff --git a/src/modules/partition/gui/CreateVolumeGroupDialog.cpp b/src/modules/partition/gui/CreateVolumeGroupDialog.cpp deleted file mode 100644 index 3d13687bb3..0000000000 --- a/src/modules/partition/gui/CreateVolumeGroupDialog.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "CreateVolumeGroupDialog.h" - -#include -#include - -#include -#include -#include - -CreateVolumeGroupDialog::CreateVolumeGroupDialog( QString& vgName, - QVector< const Partition* >& selectedPVs, - QVector< const Partition* > pvList, - qint64& pSize, - QWidget* parent ) - : VolumeGroupBaseDialog( vgName, pvList, parent ) - , m_selectedPVs( selectedPVs ) - , m_peSize( pSize ) -{ - setWindowTitle( tr( "Create Volume Group", "@title" ) ); - - peSize()->setValue( pSize ); - - vgType()->setEnabled( false ); -} - -void -CreateVolumeGroupDialog::accept() -{ - QString& name = vgNameValue(); - name = vgName()->text(); - - m_selectedPVs << checkedItems(); - - qint64& pe = m_peSize; - pe = peSize()->value(); - - QDialog::accept(); -} diff --git a/src/modules/partition/gui/CreateVolumeGroupDialog.h b/src/modules/partition/gui/CreateVolumeGroupDialog.h deleted file mode 100644 index 4712a9106a..0000000000 --- a/src/modules/partition/gui/CreateVolumeGroupDialog.h +++ /dev/null @@ -1,33 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef CREATEVOLUMEGROUPDIALOG_H -#define CREATEVOLUMEGROUPDIALOG_H - -#include "gui/VolumeGroupBaseDialog.h" - -class CreateVolumeGroupDialog : public VolumeGroupBaseDialog -{ - Q_OBJECT -public: - CreateVolumeGroupDialog( QString& vgName, - QVector< const Partition* >& selectedPVs, - QVector< const Partition* > pvList, - qint64& pSize, - QWidget* parent ); - - void accept() override; - -private: - QVector< const Partition* >& m_selectedPVs; - - qint64& m_peSize; -}; - -#endif // CREATEVOLUMEGROUPDIALOG_H diff --git a/src/modules/partition/gui/DeviceInfoWidget.cpp b/src/modules/partition/gui/DeviceInfoWidget.cpp deleted file mode 100644 index f57ed91d3e..0000000000 --- a/src/modules/partition/gui/DeviceInfoWidget.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "DeviceInfoWidget.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "utils/Gui.h" -#include "utils/Logger.h" -#include "utils/QtCompat.h" -#include "utils/Retranslator.h" - -#include -#include -#include - -DeviceInfoWidget::DeviceInfoWidget( QWidget* parent ) - : QWidget( parent ) - , m_ptIcon( new QLabel ) - , m_ptLabel( new QLabel ) - , m_tableType( PartitionTable::unknownTableType ) -{ - QHBoxLayout* mainLayout = new QHBoxLayout; - setLayout( mainLayout ); - - Calamares::unmarginLayout( mainLayout ); - m_ptLabel->setObjectName( "deviceInfoLabel" ); - m_ptIcon->setObjectName( "deviceInfoIcon" ); - mainLayout->addWidget( m_ptIcon ); - mainLayout->addWidget( m_ptLabel ); - - QSize iconSize = Calamares::defaultIconSize(); - - m_ptIcon->setMargin( 0 ); - m_ptIcon->setFixedSize( iconSize ); - m_ptIcon->setPixmap( Calamares::defaultPixmap( Calamares::PartitionTable, Calamares::Original, iconSize ) ); - - QFontMetrics fm = QFontMetrics( QFont() ); - m_ptLabel->setMinimumWidth( fm.boundingRect( "Amiga" ).width() + Calamares::defaultFontHeight() / 2 ); - m_ptLabel->setAlignment( Qt::AlignCenter ); - - QPalette palette; - palette.setBrush( WindowText, QColor( "#4D4D4D" ) ); //dark grey - - m_ptIcon->setAutoFillBackground( true ); - m_ptLabel->setAutoFillBackground( true ); - m_ptIcon->setPalette( palette ); - m_ptLabel->setPalette( palette ); - - CALAMARES_RETRANSLATE_SLOT( &DeviceInfoWidget::retranslateUi ); -} - -void -DeviceInfoWidget::setPartitionTableType( PartitionTable::TableType type ) -{ - m_tableType = type; - retranslateUi(); -} - -void -DeviceInfoWidget::retranslateUi() -{ - QString typeString; - QString toolTipString; - - // fix up if the name shouldn't be uppercase: - switch ( m_tableType ) - { - case PartitionTable::msdos: - case PartitionTable::msdos_sectorbased: - typeString = "MBR"; - toolTipString += tr( "

    This partition table type is only advisable on older " - "systems which start from a BIOS boot " - "environment. GPT is recommended in most other cases.

    " - "Warning: the MBR partition table " - "is an obsolete MS-DOS era standard.
    " - "Only 4 primary partitions may be created, and of " - "those 4, one can be an extended partition, which " - "may in turn contain many logical partitions." ); - break; - case PartitionTable::gpt: - // TypeString is ok - toolTipString += tr( "

    This is the recommended partition table type for modern " - "systems which start from an EFI boot " - "environment." ); - break; - case PartitionTable::loop: - typeString = "loop"; - toolTipString = tr( "This is a loop " - "device.

    " - "It is a pseudo-device with no partition table " - "that makes a file accessible as a block device. " - "This kind of setup usually only contains a single filesystem." ); - break; - case PartitionTable::none: - case PartitionTable::unknownTableType: - typeString = " ? "; - toolTipString = tr( "This installer cannot detect a partition table on the " - "selected storage device.

    " - "The device either has no partition " - "table, or the partition table is corrupted or of an unknown " - "type.
    " - "This installer can create a new partition table for you, " - "either automatically, or through the manual partitioning " - "page." ); - break; - // The next ones need to have the name adjusted, but the default tooltip is OK - case PartitionTable::mac: - typeString = "Mac"; - break; - case PartitionTable::amiga: - typeString = "Amiga"; - break; - case PartitionTable::sun: - typeString = "Sun"; - break; - // Peculiar tables, do nothing and use default type and tooltip strings - case PartitionTable::aix: - case PartitionTable::bsd: - case PartitionTable::dasd: - case PartitionTable::dvh: - case PartitionTable::pc98: - case PartitionTable::vmd: - break; - } - - if ( typeString.isEmpty() ) - { - typeString = PartitionTable::tableTypeToName( m_tableType ).toUpper(); - } - if ( toolTipString.isEmpty() ) - { - toolTipString = tr( "This device has a %1 partition " - "table." ) - .arg( typeString ); - } - - m_ptLabel->setText( typeString ); - m_ptLabel->setToolTip( toolTipString ); - - m_ptIcon->setToolTip( tr( "The type of partition table on the " - "selected storage device.

    " - "The only way to change the partition table type is to " - "erase and recreate the partition table from scratch, " - "which destroys all data on the storage device.
    " - "This installer will keep the current partition table " - "unless you explicitly choose otherwise.
    " - "If unsure, on modern systems GPT is preferred." ) ); -} diff --git a/src/modules/partition/gui/DeviceInfoWidget.h b/src/modules/partition/gui/DeviceInfoWidget.h deleted file mode 100644 index a69251be1a..0000000000 --- a/src/modules/partition/gui/DeviceInfoWidget.h +++ /dev/null @@ -1,37 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - - -#ifndef DEVICEINFOWIDGET_H -#define DEVICEINFOWIDGET_H - -#include - -#include - -class QLabel; - -class DeviceInfoWidget : public QWidget -{ - Q_OBJECT -public: - explicit DeviceInfoWidget( QWidget* parent = nullptr ); - - void setPartitionTableType( PartitionTable::TableType type ); - -public slots: - void retranslateUi(); - -private: - QLabel* m_ptIcon; - QLabel* m_ptLabel; - PartitionTable::TableType m_tableType; -}; - -#endif // DEVICEINFOWIDGET_H diff --git a/src/modules/partition/gui/EditExistingPartitionDialog.cpp b/src/modules/partition/gui/EditExistingPartitionDialog.cpp deleted file mode 100644 index 7a3f4951a2..0000000000 --- a/src/modules/partition/gui/EditExistingPartitionDialog.cpp +++ /dev/null @@ -1,384 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2008-2009 Volker Lanz - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2016 Andrius Štikonas - * SPDX-FileCopyrightText: 2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2018 2020, Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Flags handling originally from KDE Partition Manager. - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "EditExistingPartitionDialog.h" -#include "ui_EditExistingPartitionDialog.h" - -#include "core/ColorUtils.h" -#include "core/KPMHelpers.h" -#include "core/PartUtils.h" -#include "core/PartitionCoreModule.h" -#include "core/PartitionInfo.h" -#include "gui/PartitionDialogHelpers.h" -#include "gui/PartitionSizeController.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "Settings.h" -#include "partition/FileSystem.h" -#include "utils/Logger.h" -#include "widgets/TranslationFix.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -using Calamares::Partition::untranslatedFS; -using Calamares::Partition::userVisibleFS; - -static void -updateLabel( PartitionCoreModule* core, Device* device, Partition* partition, const QString& fsLabel ) -{ - // In this case, we are not formatting the partition, but we are setting the - // label on the current filesystem, if any. We only create the job if the - // label actually changed. - if ( partition->fileSystem().type() != FileSystem::Type::Unformatted && fsLabel != partition->fileSystem().label() ) - { - core->setFilesystemLabel( device, partition, fsLabel ); - } -} - -EditExistingPartitionDialog::EditExistingPartitionDialog( Device* device, - Partition* partition, - const QStringList& usedMountPoints, - QWidget* parentWidget ) - : QDialog( parentWidget ) - , m_ui( new Ui_EditExistingPartitionDialog ) - , m_device( device ) - , m_partition( partition ) - , m_partitionSizeController( new PartitionSizeController( this ) ) - , m_usedMountPoints( usedMountPoints ) -{ - m_ui->setupUi( this ); - m_ui->encryptWidget->hide(); - standardMountPoints( *( m_ui->mountPointComboBox ), PartitionInfo::mountPoint( partition ) ); - - QColor color = ColorUtils::colorForPartition( m_partition ); - m_partitionSizeController->init( m_device, m_partition, color ); - m_partitionSizeController->setSpinBox( m_ui->sizeSpinBox ); - - connect( m_ui->mountPointComboBox, - &QComboBox::currentTextChanged, - this, - &EditExistingPartitionDialog::checkMountPointSelection ); - - // The filesystem label field is always enabled, because we may want to change - // the label on the current filesystem without formatting. - m_ui->fileSystemLabelEdit->setText( PartitionInfo::label( m_partition ) ); - m_ui->fileSystemLabel->setEnabled( true ); - - replacePartResizerWidget(); - - connect( m_ui->formatRadioButton, - &QAbstractButton::toggled, - [ this ]( bool doFormat ) - { - replacePartResizerWidget(); - - m_ui->fileSystemComboBox->setEnabled( doFormat ); - - if ( !doFormat ) - { - m_ui->fileSystemComboBox->setCurrentText( userVisibleFS( m_partition->fileSystem() ) ); - } - - updateMountPointPicker(); - } ); - - connect( - m_ui->fileSystemComboBox, &QComboBox::currentTextChanged, [ this ]( QString ) { updateMountPointPicker(); } ); - - // File system - QStringList fsNames; - for ( auto fs : FileSystemFactory::map() ) - { - // We need to ensure zfs is added to the list if the zfs module is enabled - if ( ( fs->type() == FileSystem::Type::Zfs && Calamares::Settings::instance()->isModuleEnabled( "zfs" ) ) - || ( fs->supportCreate() != FileSystem::cmdSupportNone && fs->type() != FileSystem::Extended ) ) - { - fsNames << userVisibleFS( fs ); // For the combo box - } - } - m_ui->fileSystemComboBox->addItems( fsNames ); - - FileSystem::Type defaultFSType; - QString untranslatedFSName = PartUtils::canonicalFilesystemName( - Calamares::JobQueue::instance()->globalStorage()->value( "defaultFileSystemType" ).toString(), &defaultFSType ); - if ( defaultFSType == FileSystem::Type::Unknown ) - { - defaultFSType = FileSystem::Type::Ext4; - } - - QString thisFSNameForUser = userVisibleFS( m_partition->fileSystem() ); - if ( fsNames.contains( thisFSNameForUser ) ) - { - m_ui->fileSystemComboBox->setCurrentText( thisFSNameForUser ); - } - else - { - m_ui->fileSystemComboBox->setCurrentText( FileSystem::nameForType( defaultFSType ) ); - } - - // Force a format if the existing device is a zfs device since reusing a - // zpool isn't currently supported; disable the radio buttons then. - const bool partitionIsZFS = m_partition->fileSystem().type() == FileSystem::Type::Zfs; - m_ui->formatRadioButton->setEnabled( !partitionIsZFS ); - m_ui->keepRadioButton->setEnabled( !partitionIsZFS ); - - const bool formatChecked = partitionIsZFS || PartitionInfo::format( m_partition ); - m_ui->formatRadioButton->setChecked( formatChecked ); - m_ui->keepRadioButton->setChecked( !formatChecked ); - - m_ui->fileSystemComboBox->setEnabled( m_ui->formatRadioButton->isChecked() ); - - setFlagList( *( m_ui->m_listFlags ), m_partition->availableFlags(), PartitionInfo::flags( m_partition ) ); -} - -EditExistingPartitionDialog::~EditExistingPartitionDialog() {} - -PartitionTable::Flags -EditExistingPartitionDialog::newFlags() const -{ - return flagsFromList( *( m_ui->m_listFlags ) ); -} - -void -EditExistingPartitionDialog::applyChanges( PartitionCoreModule* core ) -{ - // Remove jobs that we might have created for this partition already, - // and also clear intentions so that we set the current ones unconditionally. - core->clearJobs( m_device, m_partition ); - PartitionInfo::reset( m_partition ); - - const QString mountPoint = selectedMountPoint( m_ui->mountPointComboBox ); - PartitionInfo::setMountPoint( m_partition, mountPoint ); - - qint64 newFirstSector = m_partitionSizeController->firstSector(); - qint64 newLastSector = m_partitionSizeController->lastSector(); - bool partResizedMoved = newFirstSector != m_partition->firstSector() || newLastSector != m_partition->lastSector(); - - FileSystem::Type fsType = FileSystem::Unknown; - if ( m_ui->formatRadioButton->isChecked() ) - { - fsType = m_partition->roles().has( PartitionRole::Extended ) - ? FileSystem::Extended - : FileSystem::typeForName( m_ui->fileSystemComboBox->currentText() ); - } - const QString fsLabel = m_ui->fileSystemLabelEdit->text(); - - const auto resultFlags = newFlags(); - const auto currentFlags = PartitionInfo::flags( m_partition ); - - cDebug() << m_partition->partitionPath() << "format?" << m_ui->formatRadioButton->isChecked() << "label=" << fsLabel - << "mount=" << mountPoint; - - if ( partResizedMoved ) - { - cDebug() << "old boundaries:" << m_partition->firstSector() << m_partition->lastSector() - << m_partition->length(); - cDebug() << Logger::SubEntry << "new boundaries:" << newFirstSector << newLastSector; - - if ( m_ui->formatRadioButton->isChecked() ) - { - Partition* newPartition = KPMHelpers::createNewPartition( m_partition->parent(), - *m_device, - m_partition->roles(), - fsType, - fsLabel, - newFirstSector, - newLastSector, - resultFlags ); - PartitionInfo::setMountPoint( newPartition, PartitionInfo::mountPoint( m_partition ) ); - PartitionInfo::setFormat( newPartition, true ); - - core->deletePartition( m_device, m_partition ); - core->createPartition( m_device, newPartition ); - core->setPartitionFlags( m_device, newPartition, resultFlags ); - } - else - { - core->resizePartition( m_device, m_partition, newFirstSector, newLastSector ); - if ( currentFlags != resultFlags ) - { - core->setPartitionFlags( m_device, m_partition, resultFlags ); - } - updateLabel( core, m_device, m_partition, fsLabel ); - PartitionInfo::setFormat( m_partition, false ); - } - } - else - { - // No size changes - if ( m_ui->formatRadioButton->isChecked() ) - { - // if the FS type is unchanged, we just format - if ( m_partition->fileSystem().type() == fsType ) - { - core->formatPartition( m_device, m_partition ); - if ( currentFlags != resultFlags ) - { - core->setPartitionFlags( m_device, m_partition, resultFlags ); - } - core->setFilesystemLabel( m_device, m_partition, fsLabel ); - PartitionInfo::setFormat( m_partition, true ); - } - else // otherwise, we delete and recreate the partition with new fs type - { - Partition* newPartition = KPMHelpers::createNewPartition( m_partition->parent(), - *m_device, - m_partition->roles(), - fsType, - fsLabel, - m_partition->firstSector(), - m_partition->lastSector(), - resultFlags ); - PartitionInfo::setMountPoint( newPartition, PartitionInfo::mountPoint( m_partition ) ); - PartitionInfo::setFormat( newPartition, true ); - - core->deletePartition( m_device, m_partition ); - core->createPartition( m_device, newPartition ); - core->setPartitionFlags( m_device, newPartition, resultFlags ); - } - } - else - { - if ( currentFlags != resultFlags ) - { - core->setPartitionFlags( m_device, m_partition, resultFlags ); - } - updateLabel( core, m_device, m_partition, fsLabel ); - PartitionInfo::setFormat( m_partition, false ); - - core->refreshPartition( m_device, m_partition ); - } - - // Update the existing luks partition - const QString passphrase = m_ui->encryptWidget->passphrase(); - if ( !passphrase.isEmpty() ) - { - if ( KPMHelpers::savePassphrase( m_partition, passphrase ) != KPMHelpers::SavePassphraseValue::NoError ) - { - QString message = tr( "Passphrase for existing partition" ); - QString description = tr( "Partition %1 could not be decrypted " - "with the given passphrase." - "

    " - "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(); - } - } - } -} - - -void -EditExistingPartitionDialog::replacePartResizerWidget() -{ - /* - * There is no way to reliably update the partition used by - * PartResizerWidget, which is necessary when we switch between "format" and - * "keep". This is a hack which replaces the existing PartResizerWidget - * with a new one. - */ - PartResizerWidget* widget = new PartResizerWidget( this ); - - layout()->replaceWidget( m_ui->partResizerWidget, widget ); - delete m_ui->partResizerWidget; - m_ui->partResizerWidget = widget; - - m_partitionSizeController->setPartResizerWidget( widget, m_ui->formatRadioButton->isChecked() ); -} - -void -EditExistingPartitionDialog::updateMountPointPicker() -{ - bool doFormat = m_ui->formatRadioButton->isChecked(); - FileSystem::Type fsType = FileSystem::Unknown; - if ( doFormat ) - { - fsType = FileSystem::typeForName( m_ui->fileSystemComboBox->currentText() ); - } - else - { - fsType = m_partition->fileSystem().type(); - } - bool canMount = true; - if ( fsType == FileSystem::Extended || fsType == FileSystem::LinuxSwap || fsType == FileSystem::Unformatted - || fsType == FileSystem::Unknown || fsType == FileSystem::Lvm2_PV ) - { - canMount = false; - } - - m_ui->mountPointLabel->setEnabled( canMount ); - m_ui->mountPointComboBox->setEnabled( canMount ); - if ( !canMount ) - { - setSelectedMountPoint( m_ui->mountPointComboBox, QString() ); - } - - toggleEncryptWidget(); -} - -void -EditExistingPartitionDialog::checkMountPointSelection() -{ - 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(); - } -} diff --git a/src/modules/partition/gui/EditExistingPartitionDialog.h b/src/modules/partition/gui/EditExistingPartitionDialog.h deleted file mode 100644 index 5d1e7fd650..0000000000 --- a/src/modules/partition/gui/EditExistingPartitionDialog.h +++ /dev/null @@ -1,64 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef EDITEXISTINGPARTITIONDIALOG_H -#define EDITEXISTINGPARTITIONDIALOG_H - -#include - -#include -#include - -class PartitionCoreModule; -class Device; -class Partition; -class PartitionSizeController; -class Ui_EditExistingPartitionDialog; - -/** - * The dialog which is shown to edit a partition which already existed when the installer started. - * - * It lets you decide how to reuse the partition: whether to keep its content - * or reformat it, whether to resize or move it. - */ -class EditExistingPartitionDialog : public QDialog -{ - Q_OBJECT -public: - struct FreeSpace - { - Partition* p; - }; - - EditExistingPartitionDialog( Device* device, - Partition* partition, - const QStringList& usedMountPoints, - QWidget* parentWidget = nullptr ); - ~EditExistingPartitionDialog() override; - - void applyChanges( PartitionCoreModule* module ); - -private slots: - void checkMountPointSelection(); - -private: - QScopedPointer< Ui_EditExistingPartitionDialog > m_ui; - Device* m_device; - Partition* m_partition; - PartitionSizeController* m_partitionSizeController; - QStringList m_usedMountPoints; - - PartitionTable::Flags newFlags() const; - void replacePartResizerWidget(); - void updateMountPointPicker(); - void toggleEncryptWidget(); -}; - -#endif /* EDITEXISTINGPARTITIONDIALOG_H */ diff --git a/src/modules/partition/gui/EditExistingPartitionDialog.ui b/src/modules/partition/gui/EditExistingPartitionDialog.ui deleted file mode 100644 index ff9cc33c54..0000000000 --- a/src/modules/partition/gui/EditExistingPartitionDialog.ui +++ /dev/null @@ -1,289 +0,0 @@ - - - -SPDX-FileCopyrightText: 2014 Aurélien Gâteau <agateau@kde.org> -SPDX-License-Identifier: GPL-3.0-or-later - - EditExistingPartitionDialog - - - - 0 - 0 - 570 - 689 - - - - - 0 - 0 - - - - Edit Existing Partition - - - - QLayout::SetMinimumSize - - - - - - 0 - 0 - - - - - 0 - 59 - - - - - - - - QFormLayout::ExpandingFieldsGrow - - - - - Con&tent: - - - keepRadioButton - - - - - - - &Keep - - - true - - - - - - - Format - - - - - - - - 0 - 0 - - - - - 300 - 0 - - - - Warning: Formatting the partition will erase all existing data. - - - true - - - - - - - &Mount Point: - - - mountPointComboBox - - - - - - - - 0 - 0 - - - - true - - - -1 - - - - - - - Si&ze: - - - sizeSpinBox - - - - - - - MiB - - - - - - - Fi&le System: - - - fileSystemComboBox - - - - - - - - - - Flags: - - - - - - - true - - - QAbstractItemView::NoSelection - - - true - - - - - - - Label for the filesystem - - - 16 - - - - - - - FS Label: - - - - - - - - - - - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 13 - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - PartResizerWidget - QWidget -
    kpmcore/gui/partresizerwidget.h
    - 1 -
    - - EncryptWidget - QWidget -
    gui/EncryptWidget.h
    - 1 -
    -
    - - sizeSpinBox - keepRadioButton - formatRadioButton - mountPointComboBox - buttonBox - - - - - buttonBox - accepted() - EditExistingPartitionDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - EditExistingPartitionDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - -
    diff --git a/src/modules/partition/gui/EncryptWidget.cpp b/src/modules/partition/gui/EncryptWidget.cpp deleted file mode 100644 index 176a7c610a..0000000000 --- a/src/modules/partition/gui/EncryptWidget.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-FileCopyrightText: 2023 Evan James - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "EncryptWidget.h" - -#include "ui_EncryptWidget.h" - -#include "Branding.h" -#include "utils/Gui.h" -#include "utils/Retranslator.h" - -constexpr int ZFS_MIN_LENGTH = 8; - -/** @brief Does this system support whole-disk encryption? - * - * Returns @c true if the system is likely to support encryption - * with sufficient performance to be usable. A machine that can't - * doe hardware-assisted AES is **probably** too slow, so we could - * warn the user that ticking the "encrypt system" box is a bad - * idea. - * - * Since we don't have an oracle that can answer that question, - * just pretend every system can do it. - */ -static inline bool -systemSupportsEncryptionAcceptably() -{ - return true; -} - -EncryptWidget::EncryptWidget( QWidget* parent ) - : QWidget( parent ) - , m_ui( new Ui::EncryptWidget ) - , m_state( Encryption::Disabled ) -{ - m_ui->setupUi( this ); - - m_ui->m_iconLabel->setFixedWidth( m_ui->m_iconLabel->height() ); - m_ui->m_passphraseLineEdit->hide(); - m_ui->m_confirmLineEdit->hide(); - m_ui->m_iconLabel->hide(); - // TODO: this deserves better rendering, an icon or something, but that will - // depend on having a non-bogus implementation of systemSupportsEncryptionAcceptably - if ( systemSupportsEncryptionAcceptably() ) - { - m_ui->m_encryptionUnsupportedLabel->hide(); - } - else - { - // This is really ugly, but the character is unicode "unlocked" - m_ui->m_encryptionUnsupportedLabel->setText( QStringLiteral( "🔓" ) ); - m_ui->m_encryptionUnsupportedLabel->show(); - } - - connect( m_ui->m_encryptCheckBox, &QCheckBox::stateChanged, this, &EncryptWidget::onCheckBoxStateChanged ); - connect( m_ui->m_passphraseLineEdit, &QLineEdit::textEdited, this, &EncryptWidget::onPassphraseEdited ); - connect( m_ui->m_confirmLineEdit, &QLineEdit::textEdited, this, &EncryptWidget::onPassphraseEdited ); - - setFixedHeight( m_ui->m_passphraseLineEdit->height() ); // Avoid jumping up and down - updateState(); - - CALAMARES_RETRANSLATE_SLOT( &EncryptWidget::retranslate ); -} - -void -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 -{ - 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; -} - -void -EncryptWidget::setText( const QString& text ) -{ - m_ui->m_encryptCheckBox->setText( text ); -} - -QString -EncryptWidget::passphrase() const -{ - if ( m_state == Encryption::Confirmed ) - { - return m_ui->m_passphraseLineEdit->text(); - } - return QString(); -} - -void -EncryptWidget::retranslate() -{ - m_ui->retranslateUi( this ); - onPassphraseEdited(); // For the tooltip -} - -///@brief Give @p label the @p pixmap from the standard-pixmaps -static void -applyPixmap( QLabel* label, Calamares::ImageType pixmap ) -{ - label->setFixedWidth( label->height() ); - label->setPixmap( Calamares::defaultPixmap( pixmap, Calamares::Original, label->size() ) ); -} - -void -EncryptWidget::updateState( const bool notify ) -{ - if ( m_ui->m_passphraseLineEdit->isVisible() ) - { - QString p1 = m_ui->m_passphraseLineEdit->text(); - QString p2 = m_ui->m_confirmLineEdit->text(); - - if ( p1.isEmpty() && p2.isEmpty() ) - { - applyPixmap( m_ui->m_iconLabel, Calamares::StatusWarning ); - m_ui->m_iconLabel->setToolTip( tr( "Please enter the same passphrase in both boxes.", "@tooltip" ) ); - } - else if ( m_filesystem == FileSystem::Zfs && p1.length() < ZFS_MIN_LENGTH ) - { - applyPixmap( m_ui->m_iconLabel, Calamares::StatusError ); - m_ui->m_iconLabel->setToolTip( tr( "Password must be a minimum of %1 characters.", "@tooltip" ).arg( ZFS_MIN_LENGTH ) ); - } - else if ( p1 == p2 ) - { - applyPixmap( m_ui->m_iconLabel, Calamares::StatusOk ); - m_ui->m_iconLabel->setToolTip( QString() ); - } - else - { - applyPixmap( m_ui->m_iconLabel, Calamares::StatusError ); - m_ui->m_iconLabel->setToolTip( tr( "Please enter the same passphrase in both boxes.", "@tooltip" ) ); - } - } - - Encryption newState = state(); - - if ( newState != m_state ) - { - m_state = newState; - if ( notify ) - { - Q_EMIT stateChanged( m_state ); - } - } -} - -void -EncryptWidget::onPassphraseEdited() -{ - if ( !m_ui->m_iconLabel->isVisible() ) - { - m_ui->m_iconLabel->show(); - } - - updateState(); -} - -void -EncryptWidget::onCheckBoxStateChanged( int checked ) -{ - // @p checked is a Qt::CheckState, 0 is "unchecked" and 2 is "checked" - m_ui->m_passphraseLineEdit->setVisible( checked ); - m_ui->m_confirmLineEdit->setVisible( checked ); - m_ui->m_iconLabel->setVisible( checked ); - m_ui->m_passphraseLineEdit->clear(); - m_ui->m_confirmLineEdit->clear(); - m_ui->m_iconLabel->clear(); - - updateState(); -} - -void -EncryptWidget::setFilesystem( const FileSystem::Type fs ) -{ - m_filesystem = fs; - if ( m_state != Encryption::Disabled ) - { - updateState( false ); - } -} diff --git a/src/modules/partition/gui/EncryptWidget.h b/src/modules/partition/gui/EncryptWidget.h deleted file mode 100644 index 9669b4d213..0000000000 --- a/src/modules/partition/gui/EncryptWidget.h +++ /dev/null @@ -1,68 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-FileCopyrightText: 2023 Evan James - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - - -#ifndef ENCRYPTWIDGET_H -#define ENCRYPTWIDGET_H - -#include - -#include - -namespace Ui -{ -class EncryptWidget; -} // namespace Ui - -class EncryptWidget : public QWidget -{ - Q_OBJECT - -public: - enum class Encryption : unsigned short - { - Disabled = 0, - Unconfirmed, - Confirmed - }; - - explicit EncryptWidget( QWidget* parent = nullptr ); - - void reset( bool checkVisible = true ); - - Encryption state() const; - void setText( const QString& text ); - - /** - * @brief setFilesystem sets the filesystem name used for password validation - * @param fs A QString containing the name of the filesystem - */ - void setFilesystem( const FileSystem::Type fs ); - - QString passphrase() const; - - void retranslate(); - -signals: - void stateChanged( Encryption ); - -private: - void updateState( const bool notify = true ); - void onPassphraseEdited(); - void onCheckBoxStateChanged( int checked ); - - Ui::EncryptWidget* m_ui; - Encryption m_state; - - FileSystem::Type m_filesystem; -}; - -#endif // ENCRYPTWIDGET_H diff --git a/src/modules/partition/gui/EncryptWidget.ui b/src/modules/partition/gui/EncryptWidget.ui deleted file mode 100644 index 24d63b5a3e..0000000000 --- a/src/modules/partition/gui/EncryptWidget.ui +++ /dev/null @@ -1,100 +0,0 @@ - - - -SPDX-FileCopyrightText: 2016 Teo Mrnjavac <teo@kde.org> -SPDX-License-Identifier: GPL-3.0-or-later - - EncryptWidget - - - - 0 - 0 - 822 - 59 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - En&crypt system - - - - - - - Your system does not seem to support encryption well enough to encrypt the entire system. You may enable encryption, but performance may suffer. - - - 🔓 - - - Qt::AlignCenter - - - - - - - QLineEdit::Password - - - Passphrase - - - - - - - QLineEdit::Password - - - Confirm passphrase - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - Qt::AlignCenter - - - - - - - - diff --git a/src/modules/partition/gui/ListPhysicalVolumeWidgetItem.cpp b/src/modules/partition/gui/ListPhysicalVolumeWidgetItem.cpp deleted file mode 100644 index 8eeafcbf4b..0000000000 --- a/src/modules/partition/gui/ListPhysicalVolumeWidgetItem.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "ListPhysicalVolumeWidgetItem.h" - -#include "core/SizeUtils.h" - -ListPhysicalVolumeWidgetItem::ListPhysicalVolumeWidgetItem( const Partition* partition, bool checked ) - : QListWidgetItem( QString( "%1 | %2" ).arg( partition->deviceNode(), formatByteSize( partition->capacity() ) ) ) - , m_partition( partition ) -{ - setToolTip( partition->deviceNode() ); - setSizeHint( QSize( 0, 32 ) ); - setCheckState( checked ? Qt::Checked : Qt::Unchecked ); -} - -const Partition* -ListPhysicalVolumeWidgetItem::partition() const -{ - return m_partition; -} - -ListPhysicalVolumeWidgetItem::~ListPhysicalVolumeWidgetItem() {} diff --git a/src/modules/partition/gui/ListPhysicalVolumeWidgetItem.h b/src/modules/partition/gui/ListPhysicalVolumeWidgetItem.h deleted file mode 100644 index 5d7fdcb764..0000000000 --- a/src/modules/partition/gui/ListPhysicalVolumeWidgetItem.h +++ /dev/null @@ -1,29 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef LISTPHYSICALVOLUMEWIDGETITEM_H -#define LISTPHYSICALVOLUMEWIDGETITEM_H - -#include - -#include - -class ListPhysicalVolumeWidgetItem : public QListWidgetItem -{ -public: - ListPhysicalVolumeWidgetItem( const Partition* partition, bool checked ); - ~ListPhysicalVolumeWidgetItem() override; - - const Partition* partition() const; - -private: - const Partition* m_partition; -}; - -#endif // LISTPHYSICALVOLUMEWIDGETITEM_H diff --git a/src/modules/partition/gui/PartitionBarsView.cpp b/src/modules/partition/gui/PartitionBarsView.cpp deleted file mode 100644 index ef748d2621..0000000000 --- a/src/modules/partition/gui/PartitionBarsView.cpp +++ /dev/null @@ -1,535 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ -#include "gui/PartitionBarsView.h" - -#include "core/ColorUtils.h" -#include "core/PartitionModel.h" - -#include "utils/Gui.h" -#include "utils/Logger.h" - -#include - -#include -#include -#include -#include - -static const int VIEW_HEIGHT = qMax( Calamares::defaultFontHeight() + 8, // wins out with big fonts - int( Calamares::defaultFontHeight() * 0.6 ) + 22 ); // wins out with small fonts -static constexpr int CORNER_RADIUS = 3; -static const int EXTENDED_PARTITION_MARGIN = qMax( 4, VIEW_HEIGHT / 6 ); - -// The SELECTION_MARGIN is applied within a hardcoded 2px padding anyway, so -// we start from EXTENDED_PARTITION_MARGIN - 2 in all cases. -// Then we try to ensure the selection rectangle fits exactly between the extended -// rectangle and the outer frame (the "/ 2" part), unless that's not possible, and in -// that case we at least make sure we have a 1px gap between the selection rectangle -// and the extended partition box (the "- 2" part). -// At worst, on low DPI systems, this will mean in order: -// 1px outer rect, 1 px gap, 1px selection rect, 1px gap, 1px extended partition rect. -static const int SELECTION_MARGIN - = qMin( ( EXTENDED_PARTITION_MARGIN - 2 ) / 2, ( EXTENDED_PARTITION_MARGIN - 2 ) - 2 ); - -PartitionBarsView::PartitionBarsView( QWidget* parent ) - : QAbstractItemView( parent ) - , m_nestedPartitionsMode( NoNestedPartitions ) - , canBeSelected( []( const QModelIndex& ) { return true; } ) - , m_hoveredIndex( QModelIndex() ) -{ - this->setObjectName( "partitionBarView" ); - setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ); - setFrameStyle( QFrame::NoFrame ); - setSelectionBehavior( QAbstractItemView::SelectRows ); - setSelectionMode( QAbstractItemView::SingleSelection ); - - // Debug - connect( this, - &PartitionBarsView::clicked, - this, - [ = ]( const QModelIndex& index ) { cDebug() << "Clicked row" << index.row(); } ); - setMouseTracking( true ); -} - -PartitionBarsView::~PartitionBarsView() {} - -void -PartitionBarsView::setNestedPartitionsMode( PartitionBarsView::NestedPartitionsMode mode ) -{ - m_nestedPartitionsMode = mode; - viewport()->repaint(); -} - -QSize -PartitionBarsView::minimumSizeHint() const -{ - return sizeHint(); -} - -QSize -PartitionBarsView::sizeHint() const -{ - return QSize( -1, VIEW_HEIGHT ); -} - -void -PartitionBarsView::paintEvent( QPaintEvent* event ) -{ - QPainter painter( viewport() ); - painter.fillRect( rect(), palette().window() ); - painter.setRenderHint( QPainter::Antialiasing ); - - QRect partitionsRect = rect(); - partitionsRect.setHeight( VIEW_HEIGHT ); - - painter.save(); - drawPartitions( &painter, partitionsRect, QModelIndex() ); - painter.restore(); -} - -void -PartitionBarsView::drawSection( QPainter* painter, const QRect& rect_, int x, int width, const QModelIndex& index ) -{ - QColor color - = index.isValid() ? index.data( Qt::DecorationRole ).value< QColor >() : ColorUtils::unknownDisklabelColor(); - bool isFreeSpace = index.isValid() ? index.data( PartitionModel::IsFreeSpaceRole ).toBool() : true; - - QRect rect = rect_; - const int y = rect.y(); - const int height = rect.height(); - const int radius = qMax( 1, CORNER_RADIUS - ( VIEW_HEIGHT - height ) / 2 ); - painter->setClipRect( x, y, width, height ); - painter->translate( 0.5, 0.5 ); - - rect.adjust( 0, 0, -1, -1 ); - - if ( selectionMode() != QAbstractItemView::NoSelection && // no hover without selection - m_hoveredIndex.isValid() && index == m_hoveredIndex ) - { - if ( canBeSelected( index ) ) - { - painter->setBrush( color.lighter( 115 ) ); - } - else - { - painter->setBrush( color ); - } - } - else - { - painter->setBrush( color ); - } - - QColor borderColor = color.darker(); - - painter->setPen( borderColor ); - - painter->drawRoundedRect( rect, radius, radius ); - - // Draw shade - if ( !isFreeSpace ) - { - rect.adjust( 2, 2, -2, -2 ); - } - - QLinearGradient gradient( 0, 0, 0, height / 2 ); - - qreal c = isFreeSpace ? 0 : 1; - gradient.setColorAt( 0, QColor::fromRgbF( c, c, c, 0.3 ) ); - gradient.setColorAt( 1, QColor::fromRgbF( c, c, c, 0 ) ); - - painter->setPen( Qt::NoPen ); - - painter->setBrush( gradient ); - painter->drawRoundedRect( rect, radius, radius ); - - if ( selectionMode() != QAbstractItemView::NoSelection && index.isValid() && selectionModel() - && !selectionModel()->selectedIndexes().isEmpty() && selectionModel()->selectedIndexes().first() == index ) - { - painter->setPen( QPen( borderColor, 1 ) ); - QColor highlightColor = QPalette().highlight().color(); - highlightColor = highlightColor.lighter( 500 ); - highlightColor.setAlpha( 120 ); - painter->setBrush( highlightColor ); - - QRect selectionRect = rect; - selectionRect.setX( x + 1 ); - selectionRect.setWidth( width - 3 ); //account for the previous rect.adjust - - if ( rect.x() > selectionRect.x() ) //hack for first item - { - selectionRect.adjust( rect.x() - selectionRect.x(), 0, 0, 0 ); - } - - if ( rect.right() < selectionRect.right() ) //hack for last item - { - selectionRect.adjust( 0, 0, -( selectionRect.right() - rect.right() ), 0 ); - } - - selectionRect.adjust( SELECTION_MARGIN, SELECTION_MARGIN, -SELECTION_MARGIN, -SELECTION_MARGIN ); - - painter->drawRoundedRect( selectionRect, radius - 1, radius - 1 ); - } - - painter->translate( -0.5, -0.5 ); -} - -void -PartitionBarsView::drawPartitions( QPainter* painter, const QRect& rect, const QModelIndex& parent ) -{ - PartitionModel* modl = qobject_cast< PartitionModel* >( model() ); - if ( !modl ) - { - return; - } - const int totalWidth = rect.width(); - - auto pair = computeItemsVector( parent ); - QVector< PartitionBarsView::Item >& items = pair.first; - qreal& total = pair.second; - int x = rect.x(); - for ( int row = 0; row < items.count(); ++row ) - { - const auto& item = items[ row ]; - int width; - if ( row < items.count() - 1 ) - { - width = totalWidth * ( item.size / total ); - } - else - // Make sure we fill the last pixel column - { - width = rect.right() - x + 1; - } - - drawSection( painter, rect, x, width, item.index ); - - if ( m_nestedPartitionsMode == DrawNestedPartitions && modl->hasChildren( item.index ) ) - { - QRect subRect( x + EXTENDED_PARTITION_MARGIN, - rect.y() + EXTENDED_PARTITION_MARGIN, - width - 2 * EXTENDED_PARTITION_MARGIN, - rect.height() - 2 * EXTENDED_PARTITION_MARGIN ); - drawPartitions( painter, subRect, item.index ); - } - x += width; - } - - if ( !items.count() && !modl->device()->partitionTable() ) // No disklabel or unknown - { - int width = rect.right() - rect.x() + 1; - drawSection( painter, rect, rect.x(), width, QModelIndex() ); - } -} - -QModelIndex -PartitionBarsView::indexAt( const QPoint& point ) const -{ - return indexAt( point, rect(), QModelIndex() ); -} - -QModelIndex -PartitionBarsView::indexAt( const QPoint& point, const QRect& rect, const QModelIndex& parent ) const -{ - PartitionModel* modl = qobject_cast< PartitionModel* >( model() ); - if ( !modl ) - { - return QModelIndex(); - } - const int totalWidth = rect.width(); - - auto pair = computeItemsVector( parent ); - QVector< PartitionBarsView::Item >& items = pair.first; - qreal& total = pair.second; - int x = rect.x(); - for ( int row = 0; row < items.count(); ++row ) - { - const auto& item = items[ row ]; - int width; - if ( row < items.count() - 1 ) - { - width = totalWidth * ( item.size / total ); - } - else - // Make sure we fill the last pixel column - { - width = rect.right() - x + 1; - } - - QRect thisItemRect( x, rect.y(), width, rect.height() ); - if ( thisItemRect.contains( point ) ) - { - if ( m_nestedPartitionsMode == DrawNestedPartitions && modl->hasChildren( item.index ) ) - { - QRect subRect( x + EXTENDED_PARTITION_MARGIN, - rect.y() + EXTENDED_PARTITION_MARGIN, - width - 2 * EXTENDED_PARTITION_MARGIN, - rect.height() - 2 * EXTENDED_PARTITION_MARGIN ); - - if ( subRect.contains( point ) ) - { - return indexAt( point, subRect, item.index ); - } - return item.index; - } - else // contains but no children, we win - { - return item.index; - } - } - x += width; - } - - return QModelIndex(); -} - -QRect -PartitionBarsView::visualRect( const QModelIndex& index ) const -{ - return visualRect( index, rect(), QModelIndex() ); -} - -QRect -PartitionBarsView::visualRect( const QModelIndex& index, const QRect& rect, const QModelIndex& parent ) const -{ - PartitionModel* modl = qobject_cast< PartitionModel* >( model() ); - if ( !modl ) - { - return QRect(); - } - const int totalWidth = rect.width(); - - auto pair = computeItemsVector( parent ); - QVector< PartitionBarsView::Item >& items = pair.first; - qreal& total = pair.second; - int x = rect.x(); - for ( int row = 0; row < items.count(); ++row ) - { - const auto& item = items[ row ]; - int width; - if ( row < items.count() - 1 ) - { - width = totalWidth * ( item.size / total ); - } - else - // Make sure we fill the last pixel column - { - width = rect.right() - x + 1; - } - - QRect thisItemRect( x, rect.y(), width, rect.height() ); - if ( item.index == index ) - { - return thisItemRect; - } - - if ( m_nestedPartitionsMode == DrawNestedPartitions && modl->hasChildren( item.index ) - && index.parent() == item.index ) - { - QRect subRect( x + EXTENDED_PARTITION_MARGIN, - rect.y() + EXTENDED_PARTITION_MARGIN, - width - 2 * EXTENDED_PARTITION_MARGIN, - rect.height() - 2 * EXTENDED_PARTITION_MARGIN ); - - QRect candidateVisualRect = visualRect( index, subRect, item.index ); - if ( !candidateVisualRect.isNull() ) - { - return candidateVisualRect; - } - } - - x += width; - } - - return QRect(); -} - -QRegion -PartitionBarsView::visualRegionForSelection( const QItemSelection& selection ) const -{ - return QRegion(); -} - -int -PartitionBarsView::horizontalOffset() const -{ - return 0; -} - -int -PartitionBarsView::verticalOffset() const -{ - return 0; -} - -void -PartitionBarsView::scrollTo( const QModelIndex& index, ScrollHint hint ) -{ - Q_UNUSED( index ) - Q_UNUSED( hint ) -} - -void -PartitionBarsView::setSelectionModel( QItemSelectionModel* selectionModel ) -{ - QAbstractItemView::setSelectionModel( selectionModel ); - connect( selectionModel, &QItemSelectionModel::selectionChanged, this, [ = ] { viewport()->repaint(); } ); -} - -void -PartitionBarsView::setSelectionFilter( std::function< bool( const QModelIndex& ) > canBeSelected ) -{ - this->canBeSelected = canBeSelected; -} - -QModelIndex -PartitionBarsView::moveCursor( CursorAction, Qt::KeyboardModifiers ) -{ - return QModelIndex(); -} - -bool -PartitionBarsView::isIndexHidden( const QModelIndex& ) const -{ - return false; -} - -void -PartitionBarsView::setSelection( const QRect& rect, QItemSelectionModel::SelectionFlags flags ) -{ - //HACK: this is an utterly awful workaround, which is unfortunately necessary. - // QAbstractItemView::mousePressedEvent calls setSelection, but before that, - // for some mental reason, it works under the assumption that every item is a - // rectangle. This rectangle is provided by visualRect, and the idea mostly - // works, except when the item is an extended partition item, which is of course - // a rectangle with a rectangular hole in the middle. - // QAbstractItemView::mousePressEvent builds a QRect with x1, y1 in the center - // of said visualRect, and x2, y2 in the real QMouseEvent position. - // This may very well yield a QRect with negative size, which is meaningless. - // Therefore the QRect we get here is totally bogus, and its topLeft is outside - // the actual area of the item we need. - // What we need are the real coordinates of the QMouseEvent, and the only way to - // get them is by fetching the private x2, y2 from the rect. - // TL;DR: this sucks, look away. -- Teo 12/2015 - int x1, y1, x2, y2; - rect.getCoords( &x1, &y1, &x2, &y2 ); - - QModelIndex eventIndex = indexAt( QPoint( x2, y2 ) ); - if ( canBeSelected( eventIndex ) ) - { - selectionModel()->select( eventIndex, flags ); - } - - viewport()->repaint(); -} - -void -PartitionBarsView::mouseMoveEvent( QMouseEvent* event ) -{ - QModelIndex candidateIndex = indexAt( event->pos() ); - QPersistentModelIndex oldHoveredIndex = m_hoveredIndex; - if ( candidateIndex.isValid() ) - { - m_hoveredIndex = candidateIndex; - } - else - { - m_hoveredIndex = QModelIndex(); - QGuiApplication::restoreOverrideCursor(); - } - - if ( oldHoveredIndex != m_hoveredIndex ) - { - if ( m_hoveredIndex.isValid() && !canBeSelected( m_hoveredIndex ) ) - { - QGuiApplication::setOverrideCursor( Qt::ForbiddenCursor ); - } - else - { - QGuiApplication::restoreOverrideCursor(); - } - - viewport()->repaint(); - } -} - -void -PartitionBarsView::leaveEvent( QEvent* ) -{ - QGuiApplication::restoreOverrideCursor(); - if ( m_hoveredIndex.isValid() ) - { - m_hoveredIndex = QModelIndex(); - viewport()->repaint(); - } -} - -void -PartitionBarsView::mousePressEvent( QMouseEvent* event ) -{ - QModelIndex candidateIndex = indexAt( event->pos() ); - if ( canBeSelected( candidateIndex ) ) - { - QAbstractItemView::mousePressEvent( event ); - } - else - { - event->accept(); - } -} - -void -PartitionBarsView::updateGeometries() -{ - updateGeometry(); //get a new rect() for redrawing all the labels -} - -QPair< QVector< PartitionBarsView::Item >, qreal > -PartitionBarsView::computeItemsVector( const QModelIndex& parent ) const -{ - int count = model()->rowCount( parent ); - QVector< PartitionBarsView::Item > items; - - qreal total = 0; - for ( int row = 0; row < count; ++row ) - { - QModelIndex index = model()->index( row, 0, parent ); - if ( m_nestedPartitionsMode == NoNestedPartitions && model()->hasChildren( index ) ) - { - QPair< QVector< PartitionBarsView::Item >, qreal > childVect = computeItemsVector( index ); - items += childVect.first; - total += childVect.second; - } - else - { - qreal size = index.data( PartitionModel::SizeRole ).toLongLong(); - total += size; - items.append( { size, index } ); - } - } - - count = items.count(); - - // The sizes we have are perfect, but now we have to hardcode a minimum size for small - // partitions and compensate for it in the total. - qreal adjustedTotal = total; - for ( int row = 0; row < count; ++row ) - { - if ( items[ row ].size < 0.01 * total ) // If this item is smaller than 1% of everything, - { - // force its width to 1%. - adjustedTotal -= items[ row ].size; - items[ row ].size = 0.01 * total; - adjustedTotal += items[ row ].size; - } - } - - return qMakePair( items, adjustedTotal ); -} diff --git a/src/modules/partition/gui/PartitionBarsView.h b/src/modules/partition/gui/PartitionBarsView.h deleted file mode 100644 index 39c3bafe1d..0000000000 --- a/src/modules/partition/gui/PartitionBarsView.h +++ /dev/null @@ -1,91 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ -#ifndef PARTITIONPREVIEW_H -#define PARTITIONPREVIEW_H - -#include "PartitionViewSelectionFilter.h" - -#include - - -/** - * A Qt model view which displays the partitions inside a device as a colored bar. - * - * It has been created to be used with a PartitionModel instance, but does not - * call any PartitionModel-specific methods: it should be usable with other - * models as long as they provide the same roles PartitionModel provides. - */ -class PartitionBarsView : public QAbstractItemView -{ - Q_OBJECT -public: - enum NestedPartitionsMode - { - NoNestedPartitions = 0, - DrawNestedPartitions - }; - - explicit PartitionBarsView( QWidget* parent = nullptr ); - ~PartitionBarsView() override; - - void setNestedPartitionsMode( NestedPartitionsMode mode ); - - QSize minimumSizeHint() const override; - - QSize sizeHint() const override; - - void paintEvent( QPaintEvent* event ) override; - - // QAbstractItemView API - QModelIndex indexAt( const QPoint& point ) const override; - QRect visualRect( const QModelIndex& index ) const override; - void scrollTo( const QModelIndex& index, ScrollHint hint = EnsureVisible ) override; - - void setSelectionModel( QItemSelectionModel* selectionModel ) override; - - void setSelectionFilter( SelectionFilter canBeSelected ); - -protected: - // QAbstractItemView API - QRegion visualRegionForSelection( const QItemSelection& selection ) const override; - int horizontalOffset() const override; - int verticalOffset() const override; - bool isIndexHidden( const QModelIndex& index ) const override; - QModelIndex moveCursor( CursorAction cursorAction, Qt::KeyboardModifiers modifiers ) override; - void setSelection( const QRect& rect, QItemSelectionModel::SelectionFlags flags ) override; - - void mouseMoveEvent( QMouseEvent* event ) override; - void leaveEvent( QEvent* event ) override; - void mousePressEvent( QMouseEvent* event ) override; - -protected slots: - void updateGeometries() override; - -private: - void drawPartitions( QPainter* painter, const QRect& rect, const QModelIndex& parent ); - void drawSection( QPainter* painter, const QRect& rect_, int x, int width, const QModelIndex& index ); - QModelIndex indexAt( const QPoint& point, const QRect& rect, const QModelIndex& parent ) const; - QRect visualRect( const QModelIndex& index, const QRect& rect, const QModelIndex& parent ) const; - - NestedPartitionsMode m_nestedPartitionsMode; - - SelectionFilter canBeSelected; - - struct Item - { - qreal size; - QModelIndex index; - }; - inline QPair< QVector< Item >, qreal > computeItemsVector( const QModelIndex& parent ) const; - QPersistentModelIndex m_hoveredIndex; -}; - -#endif /* PARTITIONPREVIEW_H */ diff --git a/src/modules/partition/gui/PartitionDialogHelpers.cpp b/src/modules/partition/gui/PartitionDialogHelpers.cpp deleted file mode 100644 index b41c12cc97..0000000000 --- a/src/modules/partition/gui/PartitionDialogHelpers.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2018-2021 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "PartitionDialogHelpers.h" - -#include "core/PartUtils.h" -#include "gui/CreatePartitionDialog.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "utils/Logger.h" - -#include -#include -#include -#include -#include - -QStringList -standardMountPoints() -{ - QStringList mountPoints { "/", "/boot", "/home", "/opt", "/srv", "/usr", "/var" }; - if ( PartUtils::isEfiSystem() ) - { - mountPoints << Calamares::JobQueue::instance()->globalStorage()->value( "efiSystemPartition" ).toString(); - } - mountPoints.removeDuplicates(); - mountPoints.sort(); - return mountPoints; -} - -void -standardMountPoints( QComboBox& combo ) -{ - combo.clear(); - combo.lineEdit()->setPlaceholderText( QObject::tr( "(no mount point)" ) ); - combo.addItems( standardMountPoints() ); -} - -void -standardMountPoints( QComboBox& combo, const QString& selected ) -{ - standardMountPoints( combo ); - setSelectedMountPoint( combo, selected ); -} - -QString -selectedMountPoint( QComboBox& combo ) -{ - return combo.currentText(); -} - -void -setSelectedMountPoint( QComboBox& combo, const QString& selected ) -{ - if ( selected.isEmpty() ) - { - combo.setCurrentIndex( -1 ); // (no mount point) - } - else - { - for ( int i = 0; i < combo.count(); ++i ) - { - if ( selected == combo.itemText( i ) ) - { - combo.setCurrentIndex( i ); - return; - } - } - combo.addItem( selected ); - combo.setCurrentIndex( combo.count() - 1 ); - } -} - -bool -validateMountPoint( const QString& mountPoint, const QStringList& inUse, QLabel* label, QPushButton* button ) -{ - QString msg; - bool ok = true; - - if ( inUse.contains( mountPoint ) ) - { - msg = CreatePartitionDialog::tr( "Mountpoint already in use. Please select another one.", "@info" ); - ok = false; - } - else if ( !mountPoint.isEmpty() && !mountPoint.startsWith( '/' ) ) - { - msg = CreatePartitionDialog::tr( "Mountpoint must start with a /.", "@info" ); - ok = false; - } - - if ( label ) - { - label->setText( msg ); - } - if ( button ) - { - button->setEnabled( ok ); - } - return ok; -} - - -PartitionTable::Flags -flagsFromList( const QListWidget& list ) -{ - PartitionTable::Flags flags; - - for ( int i = 0; i < list.count(); i++ ) - { - if ( list.item( i )->checkState() == Qt::Checked ) - { - flags |= static_cast< PartitionTable::Flag >( list.item( i )->data( Qt::UserRole ).toInt() ); - } - } - - return flags; -} - -void -setFlagList( QListWidget& list, PartitionTable::Flags available, PartitionTable::Flags checked ) -{ - int f = 1; - QString s; - while ( !( s = PartitionTable::flagName( static_cast< PartitionTable::Flag >( f ) ) ).isEmpty() ) - { - if ( available & f ) - { - QListWidgetItem* item = new QListWidgetItem( s ); - list.addItem( item ); - item->setFlags( Qt::ItemIsUserCheckable | Qt::ItemIsEnabled ); - item->setData( Qt::UserRole, f ); - item->setCheckState( ( checked & f ) ? Qt::Checked : Qt::Unchecked ); - } - - f <<= 1; - } -} diff --git a/src/modules/partition/gui/PartitionDialogHelpers.h b/src/modules/partition/gui/PartitionDialogHelpers.h deleted file mode 100644 index eea0998c4b..0000000000 --- a/src/modules/partition/gui/PartitionDialogHelpers.h +++ /dev/null @@ -1,79 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef PARTITION_GUI_PARTITIONDIALOGHELPERS -#define PARTITION_GUI_PARTITIONDIALOGHELPERS - -#include - -#include - -class QPushButton; -class QComboBox; -class QLabel; -class QListWidget; - -/** - * Returns a list of standard mount points (e.g. /, /usr, ...). - * This also includes the EFI mount point if that is necessary - * on the target system. - */ -QStringList standardMountPoints(); - -/** - * Clears the combobox and fills it with "(no mount point)" - * and the elements of standardMountPoints(), above. - */ -void standardMountPoints( QComboBox& ); - -/** - * As above, but also sets the displayed mount point to @p selected, - * unless it is empty, in which case "(no mount point)" is chosen. - */ -void standardMountPoints( QComboBox&, const QString& selected ); - -/** - * Get the mount point selected in the combo box (which should - * have been set up with standardMountPoints(), above); this - * will map the topmost item (i.e. "(no mount point)") back - * to blank, to allow easy detection of no-mount-selected. - */ -QString selectedMountPoint( QComboBox& combo ); -static inline QString -selectedMountPoint( QComboBox* combo ) -{ - return selectedMountPoint( *combo ); -} - -void setSelectedMountPoint( QComboBox& combo, const QString& selected ); -static inline void -setSelectedMountPoint( QComboBox* combo, const QString& selected ) -{ - setSelectedMountPoint( *combo, selected ); -} - -/** @brief Validate a @p mountPoint and adjust the UI - * - * If @p mountPoint is valid -- unused and starts with a /, for instance -- - * then the button is enabled, label is cleared, and returns @c true. - * - * If it is not valid, returns @c false and sets the UI - * to explain why. - */ -bool validateMountPoint( const QString& mountPoint, const QStringList& inUse, QLabel* label, QPushButton* button ); - -/** - * Get the flags that have been checked in the list widget. - */ -PartitionTable::Flags flagsFromList( const QListWidget& list ); -void setFlagList( QListWidget& list, PartitionTable::Flags available, PartitionTable::Flags checked ); - -#endif diff --git a/src/modules/partition/gui/PartitionLabelsView.cpp b/src/modules/partition/gui/PartitionLabelsView.cpp deleted file mode 100644 index e338da252a..0000000000 --- a/src/modules/partition/gui/PartitionLabelsView.cpp +++ /dev/null @@ -1,604 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "PartitionLabelsView.h" - -#include "core/ColorUtils.h" -#include "core/PartitionModel.h" -#include "core/SizeUtils.h" - -#include "utils/Gui.h" -#include "utils/Logger.h" -#include "utils/Units.h" - -#include -#include - -// Qt -#include -#include -#include - -using namespace Calamares::Units; - -static const int LAYOUT_MARGIN = 4; -static const int LABEL_PARTITION_SQUARE_MARGIN = qMax( Calamares::defaultFontHeight() - 2, 18 ); -static const int LABELS_MARGIN = LABEL_PARTITION_SQUARE_MARGIN; -static const int CORNER_RADIUS = 2; - -static QStringList -buildUnknownDisklabelTexts( Device* dev ) -{ - QStringList texts = { QObject::tr( "Unpartitioned space or unknown partition table", "@info" ), - formatByteSize( dev->totalLogical() * dev->logicalSize() ) }; - return texts; -} - -PartitionLabelsView::PartitionLabelsView( QWidget* parent ) - : QAbstractItemView( parent ) - , m_canBeSelected( []( const QModelIndex& ) { return true; } ) - , m_extendedPartitionHidden( false ) -{ - setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ); - setFrameStyle( QFrame::NoFrame ); - setSelectionBehavior( QAbstractItemView::SelectRows ); - setSelectionMode( QAbstractItemView::SingleSelection ); - this->setObjectName( "partitionLabel" ); - setMouseTracking( true ); -} - -PartitionLabelsView::~PartitionLabelsView() {} - -QSize -PartitionLabelsView::minimumSizeHint() const -{ - return sizeHint(); -} - -QSize -PartitionLabelsView::sizeHint() const -{ - QAbstractItemModel* modl = model(); - if ( modl ) - { - return QSize( -1, LAYOUT_MARGIN + sizeForAllLabels( rect().width() ).height() ); - } - return QSize(); -} - -void -PartitionLabelsView::paintEvent( QPaintEvent* event ) -{ - Q_UNUSED( event ) - - QPainter painter( viewport() ); - painter.fillRect( rect(), palette().window() ); - painter.setRenderHint( QPainter::Antialiasing ); - - QRect lRect = labelsRect(); - - drawLabels( &painter, lRect, QModelIndex() ); -} - -QRect -PartitionLabelsView::labelsRect() const -{ - return rect().adjusted( 0, LAYOUT_MARGIN, 0, 0 ); -} - -static void -drawPartitionSquare( QPainter* painter, const QRect& rect, const QBrush& brush ) -{ - painter->fillRect( rect.adjusted( 1, 1, -1, -1 ), brush ); - painter->setRenderHint( QPainter::Antialiasing, true ); - painter->setPen( QPalette().shadow().color() ); - painter->translate( .5, .5 ); - painter->drawRoundedRect( rect.adjusted( 0, 0, -1, -1 ), CORNER_RADIUS, CORNER_RADIUS ); - painter->translate( -.5, -.5 ); -} - -static void -drawSelectionSquare( QPainter* painter, const QRect& rect, const QBrush& brush ) -{ - painter->save(); - painter->setPen( QPen( brush.color().darker(), 1 ) ); - QColor highlightColor = QPalette().highlight().color(); - highlightColor = highlightColor.lighter( 500 ); - highlightColor.setAlpha( 120 ); - painter->setBrush( highlightColor ); - painter->translate( .5, .5 ); - painter->drawRoundedRect( rect.adjusted( 0, 0, -1, -1 ), CORNER_RADIUS, CORNER_RADIUS ); - painter->translate( -.5, -.5 ); - painter->restore(); -} - -QModelIndexList -PartitionLabelsView::getIndexesToDraw( const QModelIndex& parent ) const -{ - QModelIndexList list; - - QAbstractItemModel* modl = model(); - if ( !modl ) - { - return list; - } - - for ( int row = 0; row < modl->rowCount( parent ); ++row ) - { - QModelIndex index = modl->index( row, 0, parent ); - - //HACK: horrible special casing follows. - // To save vertical space, we choose to hide short instances of free space. - // Arbitrary limit: 10MiB. - const qint64 maxHiddenB = 10_MiB; - if ( index.data( PartitionModel::IsFreeSpaceRole ).toBool() - && index.data( PartitionModel::SizeRole ).toLongLong() < maxHiddenB ) - { - continue; - } - - if ( !modl->hasChildren( index ) || !m_extendedPartitionHidden ) - { - list.append( index ); - } - - if ( modl->hasChildren( index ) ) - { - list.append( getIndexesToDraw( index ) ); - } - } - return list; -} - -QStringList -PartitionLabelsView::buildTexts( const QModelIndex& index ) const -{ - QString firstLine, secondLine; - - if ( index.data( PartitionModel::IsPartitionNewRole ).toBool() ) - { - QString label = index.data( PartitionModel::FileSystemLabelRole ).toString(); - - if ( !label.isEmpty() ) - { - firstLine = label; - } - else - { - QString mountPoint = index.sibling( index.row(), PartitionModel::MountPointColumn ).data().toString(); - if ( mountPoint == "/" ) - { - firstLine = m_customNewRootLabel.isEmpty() ? tr( "Root" ) : m_customNewRootLabel; - } - else if ( mountPoint == "/home" ) - { - firstLine = tr( "Home", "@label" ); - } - else if ( mountPoint == "/boot" ) - { - firstLine = tr( "Boot", "@label" ); - } - else if ( mountPoint.contains( "/efi" ) - && index.data( PartitionModel::FileSystemTypeRole ).toInt() == FileSystem::Fat32 ) - { - firstLine = tr( "EFI system", "@label" ); - } - else if ( index.data( PartitionModel::FileSystemTypeRole ).toInt() == FileSystem::LinuxSwap ) - { - firstLine = tr( "Swap", "@label" ); - } - else if ( !mountPoint.isEmpty() ) - { - firstLine = tr( "New partition for %1", "@label" ).arg( mountPoint ); - } - else - { - firstLine = tr( "New partition", "@label" ); - } - } - } - else if ( index.data( PartitionModel::OsproberNameRole ).toString().isEmpty() ) - { - firstLine = index.data().toString(); - if ( firstLine.startsWith( "/dev/" ) ) - { - firstLine.remove( 0, 5 ); // "/dev/" - } - } - else - { - firstLine = index.data( PartitionModel::OsproberNameRole ).toString(); - } - - if ( index.data( PartitionModel::IsFreeSpaceRole ).toBool() - || index.data( PartitionModel::FileSystemTypeRole ).toInt() == FileSystem::Extended ) - { - secondLine = index.sibling( index.row(), PartitionModel::SizeColumn ).data().toString(); - } - else - { - //: size[number] filesystem[name] - secondLine = tr( "%1 %2" ) - .arg( index.sibling( index.row(), PartitionModel::SizeColumn ).data().toString() ) - .arg( index.sibling( index.row(), PartitionModel::FileSystemColumn ).data().toString() ); - } - - return { firstLine, secondLine }; -} - -void -PartitionLabelsView::drawLabels( QPainter* painter, const QRect& rect, const QModelIndex& parent ) -{ - PartitionModel* modl = qobject_cast< PartitionModel* >( model() ); - if ( !modl ) - { - return; - } - - const QModelIndexList indexesToDraw = getIndexesToDraw( parent ); - - int label_x = rect.x(); - int label_y = rect.y(); - for ( const QModelIndex& index : indexesToDraw ) - { - QStringList texts = buildTexts( index ); - - QSize labelSize = sizeForLabel( texts ); - - QColor labelColor = index.data( Qt::DecorationRole ).value< QColor >(); - - if ( label_x + labelSize.width() > rect.width() ) //wrap to new line if overflow - { - label_x = rect.x(); - label_y += labelSize.height() + labelSize.height() / 4; - } - - // Draw hover - if ( selectionMode() != QAbstractItemView::NoSelection && // no hover without selection - m_hoveredIndex.isValid() && index == m_hoveredIndex ) - { - painter->save(); - QRect labelRect( QPoint( label_x, label_y ), labelSize ); - labelRect.adjust( 0, -LAYOUT_MARGIN, 0, -2 * LAYOUT_MARGIN ); - painter->translate( 0.5, 0.5 ); - QRect hoverRect = labelRect.adjusted( 0, 0, -1, -1 ); - painter->setBrush( QPalette().window().color().lighter( 102 ) ); - painter->setPen( Qt::NoPen ); - painter->drawRoundedRect( hoverRect, CORNER_RADIUS, CORNER_RADIUS ); - - painter->translate( -0.5, -0.5 ); - painter->restore(); - } - - // Is this element the selected one? - bool sel = selectionMode() != QAbstractItemView::NoSelection && index.isValid() && selectionModel() - && !selectionModel()->selectedIndexes().isEmpty() && selectionModel()->selectedIndexes().first() == index; - - drawLabel( painter, texts, labelColor, QPoint( label_x, label_y ), sel ); - - label_x += labelSize.width() + LABELS_MARGIN; - } - - if ( !modl->rowCount() && !modl->device()->partitionTable() ) // No disklabel or unknown - { - QStringList texts = buildUnknownDisklabelTexts( modl->device() ); - QColor labelColor = ColorUtils::unknownDisklabelColor(); - drawLabel( painter, texts, labelColor, QPoint( rect.x(), rect.y() ), false /*can't be selected*/ ); - } -} - -QSize -PartitionLabelsView::sizeForAllLabels( int maxLineWidth ) const -{ - PartitionModel* modl = qobject_cast< PartitionModel* >( model() ); - if ( !modl ) - { - return QSize(); - } - - const QModelIndexList indexesToDraw = getIndexesToDraw( QModelIndex() ); - - int lineLength = 0; - int numLines = 1; - int singleLabelHeight = 0; - for ( const QModelIndex& index : indexesToDraw ) - { - QStringList texts = buildTexts( index ); - - QSize labelSize = sizeForLabel( texts ); - - if ( lineLength + labelSize.width() > maxLineWidth ) - { - numLines++; - lineLength = labelSize.width(); - } - else - { - lineLength += LABELS_MARGIN + labelSize.width(); - } - - singleLabelHeight = qMax( singleLabelHeight, labelSize.height() ); - } - - if ( !modl->rowCount() && !modl->device()->partitionTable() ) // Unknown or no disklabel - { - singleLabelHeight = sizeForLabel( buildUnknownDisklabelTexts( modl->device() ) ).height(); - } - - int totalHeight = numLines * singleLabelHeight + ( numLines - 1 ) * singleLabelHeight / 4; //spacings - - return QSize( maxLineWidth, totalHeight ); -} - -QSize -PartitionLabelsView::sizeForLabel( const QStringList& text ) const -{ - int vertOffset = 0; - int width = 0; - for ( const QString& textLine : text ) - { - QSize textSize = fontMetrics().size( Qt::TextSingleLine, textLine ); - - vertOffset += textSize.height(); - width = qMax( width, textSize.width() ); - } - width += LABEL_PARTITION_SQUARE_MARGIN; //for the color square - return QSize( width, vertOffset ); -} - -void -PartitionLabelsView::drawLabel( QPainter* painter, - const QStringList& text, - const QColor& color, - const QPoint& pos, - bool selected ) -{ - painter->setPen( Qt::black ); - int vertOffset = 0; - int width = 0; - for ( const QString& textLine : text ) - { - QSize textSize = painter->fontMetrics().size( Qt::TextSingleLine, textLine ); - painter->drawText( - pos.x() + LABEL_PARTITION_SQUARE_MARGIN, pos.y() + vertOffset + textSize.height() / 2, textLine ); - vertOffset += textSize.height(); - painter->setPen( Qt::gray ); - width = qMax( width, textSize.width() ); - } - - QRect partitionSquareRect( - pos.x(), pos.y() - 3, LABEL_PARTITION_SQUARE_MARGIN - 5, LABEL_PARTITION_SQUARE_MARGIN - 5 ); - drawPartitionSquare( painter, partitionSquareRect, color ); - - if ( selected ) - { - drawSelectionSquare( painter, partitionSquareRect.adjusted( 2, 2, -2, -2 ), color ); - } - - painter->setPen( Qt::black ); -} - -QModelIndex -PartitionLabelsView::indexAt( const QPoint& point ) const -{ - PartitionModel* modl = qobject_cast< PartitionModel* >( model() ); - if ( !modl ) - { - return QModelIndex(); - } - - const QModelIndexList indexesToDraw = getIndexesToDraw( QModelIndex() ); - - QRect rect = this->rect(); - int label_x = rect.x(); - int label_y = rect.y(); - for ( const QModelIndex& index : indexesToDraw ) - { - QStringList texts = buildTexts( index ); - - QSize labelSize = sizeForLabel( texts ); - - if ( label_x + labelSize.width() > rect.width() ) //wrap to new line if overflow - { - label_x = rect.x(); - label_y += labelSize.height() + labelSize.height() / 4; - } - - QRect labelRect( QPoint( label_x, label_y ), labelSize ); - if ( labelRect.contains( point ) ) - { - return index; - } - - label_x += labelSize.width() + LABELS_MARGIN; - } - - return QModelIndex(); -} - -QRect -PartitionLabelsView::visualRect( const QModelIndex& idx ) const -{ - PartitionModel* modl = qobject_cast< PartitionModel* >( model() ); - if ( !modl ) - { - return QRect(); - } - - const QModelIndexList indexesToDraw = getIndexesToDraw( QModelIndex() ); - - QRect rect = this->rect(); - int label_x = rect.x(); - int label_y = rect.y(); - for ( const QModelIndex& index : indexesToDraw ) - { - QStringList texts = buildTexts( index ); - - QSize labelSize = sizeForLabel( texts ); - - if ( label_x + labelSize.width() > rect.width() ) //wrap to new line if overflow - { - label_x = rect.x(); - label_y += labelSize.height() + labelSize.height() / 4; - } - - if ( idx.isValid() && idx == index ) - { - return QRect( QPoint( label_x, label_y ), labelSize ); - } - - label_x += labelSize.width() + LABELS_MARGIN; - } - - return QRect(); -} - -QRegion -PartitionLabelsView::visualRegionForSelection( const QItemSelection& selection ) const -{ - Q_UNUSED( selection ) - - return QRegion(); -} - -int -PartitionLabelsView::horizontalOffset() const -{ - return 0; -} - -int -PartitionLabelsView::verticalOffset() const -{ - return 0; -} - -void -PartitionLabelsView::scrollTo( const QModelIndex& index, ScrollHint hint ) -{ - Q_UNUSED( index ) - Q_UNUSED( hint ) -} - -void -PartitionLabelsView::setCustomNewRootLabel( const QString& text ) -{ - m_customNewRootLabel = text; - viewport()->repaint(); -} - -void -PartitionLabelsView::setSelectionModel( QItemSelectionModel* selectionModel ) -{ - QAbstractItemView::setSelectionModel( selectionModel ); - connect( selectionModel, &QItemSelectionModel::selectionChanged, this, [ = ] { viewport()->repaint(); } ); -} - -void -PartitionLabelsView::setSelectionFilter( SelectionFilter canBeSelected ) -{ - m_canBeSelected = canBeSelected; -} - -void -PartitionLabelsView::setExtendedPartitionHidden( bool hidden ) -{ - m_extendedPartitionHidden = hidden; -} - -QModelIndex -PartitionLabelsView::moveCursor( CursorAction cursorAction, Qt::KeyboardModifiers modifiers ) -{ - Q_UNUSED( cursorAction ) - Q_UNUSED( modifiers ) - - return QModelIndex(); -} - -bool -PartitionLabelsView::isIndexHidden( const QModelIndex& index ) const -{ - Q_UNUSED( index ) - - return false; -} - -void -PartitionLabelsView::setSelection( const QRect& rect, QItemSelectionModel::SelectionFlags flags ) -{ - QModelIndex eventIndex = indexAt( rect.topLeft() ); - if ( m_canBeSelected( eventIndex ) ) - { - selectionModel()->select( eventIndex, flags ); - } -} - -void -PartitionLabelsView::mouseMoveEvent( QMouseEvent* event ) -{ - QModelIndex candidateIndex = indexAt( event->pos() ); - QPersistentModelIndex oldHoveredIndex = m_hoveredIndex; - if ( candidateIndex.isValid() ) - { - m_hoveredIndex = candidateIndex; - } - else - { - m_hoveredIndex = QModelIndex(); - QGuiApplication::restoreOverrideCursor(); - } - - if ( oldHoveredIndex != m_hoveredIndex ) - { - if ( m_hoveredIndex.isValid() && !m_canBeSelected( m_hoveredIndex ) ) - { - QGuiApplication::setOverrideCursor( Qt::ForbiddenCursor ); - } - else - { - QGuiApplication::restoreOverrideCursor(); - } - - viewport()->repaint(); - } -} - -void -PartitionLabelsView::leaveEvent( QEvent* event ) -{ - Q_UNUSED( event ) - - QGuiApplication::restoreOverrideCursor(); - if ( m_hoveredIndex.isValid() ) - { - m_hoveredIndex = QModelIndex(); - viewport()->repaint(); - } -} - -void -PartitionLabelsView::mousePressEvent( QMouseEvent* event ) -{ - QModelIndex candidateIndex = indexAt( event->pos() ); - if ( m_canBeSelected( candidateIndex ) ) - { - QAbstractItemView::mousePressEvent( event ); - } - else - { - event->accept(); - } -} - -void -PartitionLabelsView::updateGeometries() -{ - updateGeometry(); //get a new rect() for redrawing all the labels -} diff --git a/src/modules/partition/gui/PartitionLabelsView.h b/src/modules/partition/gui/PartitionLabelsView.h deleted file mode 100644 index 9b5a277ab2..0000000000 --- a/src/modules/partition/gui/PartitionLabelsView.h +++ /dev/null @@ -1,84 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef PARTITIONLABELSVIEW_H -#define PARTITIONLABELSVIEW_H - -#include "PartitionViewSelectionFilter.h" - -#include - -/** - * A Qt model view which displays colored labels for partitions. - * - * It has been created to be used with a PartitionModel instance, but does not - * call any PartitionModel-specific methods: it should be usable with other - * models as long as they provide the same roles PartitionModel provides. - */ -class PartitionLabelsView : public QAbstractItemView -{ - Q_OBJECT -public: - explicit PartitionLabelsView( QWidget* parent = nullptr ); - ~PartitionLabelsView() override; - - QSize minimumSizeHint() const override; - - QSize sizeHint() const override; - - void paintEvent( QPaintEvent* event ) override; - - // QAbstractItemView API - QModelIndex indexAt( const QPoint& point ) const override; - QRect visualRect( const QModelIndex& idx ) const override; - void scrollTo( const QModelIndex& index, ScrollHint hint = EnsureVisible ) override; - - void setCustomNewRootLabel( const QString& text ); - - void setSelectionModel( QItemSelectionModel* selectionModel ) override; - - void setSelectionFilter( SelectionFilter canBeSelected ); - - void setExtendedPartitionHidden( bool hidden ); - -protected: - // QAbstractItemView API - QRegion visualRegionForSelection( const QItemSelection& selection ) const override; - int horizontalOffset() const override; - int verticalOffset() const override; - bool isIndexHidden( const QModelIndex& index ) const override; - QModelIndex moveCursor( CursorAction cursorAction, Qt::KeyboardModifiers modifiers ) override; - void setSelection( const QRect& rect, QItemSelectionModel::SelectionFlags flags ) override; - - void mouseMoveEvent( QMouseEvent* event ) override; - void leaveEvent( QEvent* event ) override; - void mousePressEvent( QMouseEvent* event ) override; - -protected slots: - void updateGeometries() override; - -private: - QRect labelsRect() const; - void drawLabels( QPainter* painter, const QRect& rect, const QModelIndex& parent ); - QSize sizeForAllLabels( int maxLineWidth ) const; - QSize sizeForLabel( const QStringList& text ) const; - void drawLabel( QPainter* painter, const QStringList& text, const QColor& color, const QPoint& pos, bool selected ); - QModelIndexList getIndexesToDraw( const QModelIndex& parent ) const; - QStringList buildTexts( const QModelIndex& index ) const; - - SelectionFilter m_canBeSelected; - bool m_extendedPartitionHidden; - - QString m_customNewRootLabel; - QPersistentModelIndex m_hoveredIndex; -}; - -#endif // PARTITIONLABELSVIEW_H diff --git a/src/modules/partition/gui/PartitionPage.cpp b/src/modules/partition/gui/PartitionPage.cpp deleted file mode 100644 index 28b4d85837..0000000000 --- a/src/modules/partition/gui/PartitionPage.cpp +++ /dev/null @@ -1,689 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2018-2019 Adriaan de Groot - * SPDX-FileCopyrightText: 2018 Andrius Štikonas - * SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho - * SPDX-FileCopyrightText: 2019 Collabora Ltd - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "PartitionPage.h" - -// Local -#include "core/BootLoaderModel.h" -#include "core/DeviceModel.h" -#include "core/KPMHelpers.h" -#include "core/PartUtils.h" -#include "core/PartitionCoreModule.h" -#include "core/PartitionInfo.h" -#include "core/PartitionModel.h" -#include "gui/CreatePartitionDialog.h" -#include "gui/CreateVolumeGroupDialog.h" -#include "gui/EditExistingPartitionDialog.h" -#include "gui/ResizeVolumeGroupDialog.h" -#include "gui/ScanningDialog.h" - -#include "ui_CreatePartitionTableDialog.h" -#include "ui_PartitionPage.h" - -#include "Branding.h" -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "partition/PartitionQuery.h" -#include "utils/Logger.h" -#include "utils/Retranslator.h" -#include "widgets/TranslationFix.h" - -// KPMcore -#include -#include -#include -#include -#include - -// Qt -#include -#include -#include -#include -#include -#include -#include - -PartitionPage::PartitionPage( PartitionCoreModule* core, QWidget* parent ) - : QWidget( parent ) - , m_ui( new Ui_PartitionPage ) - , m_core( core ) - , m_lastSelectedBootLoaderIndex( -1 ) - , m_isEfi( false ) -{ - m_isEfi = PartUtils::isEfiSystem(); - - m_ui->setupUi( this ); - m_ui->partitionLabelsView->setVisible( - Calamares::JobQueue::instance()->globalStorage()->value( "alwaysShowPartitionLabels" ).toBool() ); - m_ui->deviceComboBox->setModel( m_core->deviceModel() ); - m_ui->bootLoaderComboBox->setModel( m_core->bootLoaderModel() ); - connect( - m_core->bootLoaderModel(), &QAbstractItemModel::modelReset, this, &PartitionPage::restoreSelectedBootLoader ); - PartitionBarsView::NestedPartitionsMode mode - = Calamares::JobQueue::instance()->globalStorage()->value( "drawNestedPartitions" ).toBool() - ? PartitionBarsView::DrawNestedPartitions - : PartitionBarsView::NoNestedPartitions; - m_ui->partitionBarsView->setNestedPartitionsMode( mode ); - updateButtons(); - updateBootLoaderInstallPath(); - - updateFromCurrentDevice(); - - connect( m_ui->deviceComboBox, &QComboBox::currentTextChanged, this, &PartitionPage::updateFromCurrentDevice ); - connect( m_ui->bootLoaderComboBox, - QOverload< int >::of( &QComboBox::activated ), - this, - &PartitionPage::updateSelectedBootLoaderIndex ); - connect( - m_ui->bootLoaderComboBox, &QComboBox::currentTextChanged, this, &PartitionPage::updateBootLoaderInstallPath ); - - connect( m_core, &PartitionCoreModule::isDirtyChanged, m_ui->revertButton, &QWidget::setEnabled ); - - connect( - m_ui->partitionTreeView, &QAbstractItemView::doubleClicked, this, &PartitionPage::onPartitionViewActivated ); - connect( m_ui->revertButton, &QAbstractButton::clicked, this, &PartitionPage::onRevertClicked ); - connect( m_ui->newVolumeGroupButton, &QAbstractButton::clicked, this, &PartitionPage::onNewVolumeGroupClicked ); - connect( - m_ui->resizeVolumeGroupButton, &QAbstractButton::clicked, this, &PartitionPage::onResizeVolumeGroupClicked ); - connect( m_ui->deactivateVolumeGroupButton, - &QAbstractButton::clicked, - this, - &PartitionPage::onDeactivateVolumeGroupClicked ); - connect( - m_ui->removeVolumeGroupButton, &QAbstractButton::clicked, this, &PartitionPage::onRemoveVolumeGroupClicked ); - connect( - m_ui->newPartitionTableButton, &QAbstractButton::clicked, this, &PartitionPage::onNewPartitionTableClicked ); - connect( m_ui->createButton, &QAbstractButton::clicked, this, &PartitionPage::onCreateClicked ); - connect( m_ui->editButton, &QAbstractButton::clicked, this, &PartitionPage::onEditClicked ); - connect( m_ui->deleteButton, &QAbstractButton::clicked, this, &PartitionPage::onDeleteClicked ); - - if ( m_isEfi ) - { - m_ui->bootLoaderComboBox->hide(); - m_ui->label_3->hide(); - } - - CALAMARES_RETRANSLATE( m_ui->retranslateUi( this ); ); -} - -PartitionPage::~PartitionPage() {} - -void -PartitionPage::updateButtons() -{ - bool allow_create = false, allow_create_table = false, allow_edit = false, allow_delete = false; - bool currentDeviceIsVG = false, isDeactivable = false; - bool isRemovable = false, isVGdeactivated = false; - - QModelIndex index = m_ui->partitionTreeView->currentIndex(); - if ( index.isValid() ) - { - const PartitionModel* model = static_cast< const PartitionModel* >( index.model() ); - Q_ASSERT( model ); - Partition* partition = model->partitionForIndex( index ); - Q_ASSERT( partition ); - const bool isFree = Calamares::Partition::isPartitionFreeSpace( partition ); - const bool isExtended = partition->roles().has( PartitionRole::Extended ); - - // An extended partition can have a "free space" child; that one does - // not count as a real child. If there are more children, at least one - // is a real one and we should not allow the extended partition to be - // deleted. - const bool hasChildren = isExtended - && ( partition->children().length() > 1 - || ( partition->children().length() == 1 - && !Calamares::Partition::isPartitionFreeSpace( partition->children().at( 0 ) ) ) ); - - const bool isInVG = m_core->isInVG( partition ); - - allow_create = isFree; - - // Keep it simple for now: do not support editing extended partitions as - // it does not work with our current edit implementation which is - // actually remove + add. This would not work with extended partitions - // because they need to be created *before* creating logical partitions - // inside them, so an edit must be applied without altering the job - // order. - // TODO: See if LVM PVs can be edited in Calamares - allow_edit = !isFree && !isExtended; - allow_delete = !isFree && !isInVG && !hasChildren; - } - - if ( m_ui->deviceComboBox->currentIndex() >= 0 ) - { - Device* device = nullptr; - QModelIndex deviceIndex = m_core->deviceModel()->index( m_ui->deviceComboBox->currentIndex(), 0 ); - if ( deviceIndex.isValid() ) - { - device = m_core->deviceModel()->deviceForIndex( deviceIndex ); - } - if ( !device ) - { - cWarning() << "Device for updateButtons is nullptr"; - } - else if ( device->type() != Device::Type::LVM_Device ) - { - allow_create_table = true; - - if ( device->type() == Device::Type::SoftwareRAID_Device - && static_cast< SoftwareRAID* >( device )->status() == SoftwareRAID::Status::Inactive ) - { - allow_create_table = false; - allow_create = false; - } - } - else - { - currentDeviceIsVG = true; - - LvmDevice* lvmDevice = dynamic_cast< LvmDevice* >( m_core->deviceModel()->deviceForIndex( deviceIndex ) ); - - isDeactivable = DeactivateVolumeGroupOperation::isDeactivatable( lvmDevice ); - isRemovable = RemoveVolumeGroupOperation::isRemovable( lvmDevice ); - - isVGdeactivated = m_core->isVGdeactivated( lvmDevice ); - - if ( isVGdeactivated ) - { - m_ui->revertButton->setEnabled( true ); - } - } - } - - m_ui->createButton->setEnabled( allow_create ); - m_ui->editButton->setEnabled( allow_edit ); - m_ui->deleteButton->setEnabled( allow_delete ); - m_ui->newPartitionTableButton->setEnabled( allow_create_table ); - m_ui->resizeVolumeGroupButton->setEnabled( currentDeviceIsVG && !isVGdeactivated ); - m_ui->deactivateVolumeGroupButton->setEnabled( currentDeviceIsVG && isDeactivable && !isVGdeactivated ); - m_ui->removeVolumeGroupButton->setEnabled( currentDeviceIsVG && isRemovable ); -} - -void -PartitionPage::onNewPartitionTableClicked() -{ - QModelIndex index = m_core->deviceModel()->index( m_ui->deviceComboBox->currentIndex(), 0 ); - Q_ASSERT( index.isValid() ); - Device* device = m_core->deviceModel()->deviceForIndex( index ); - - QPointer< QDialog > dlg = new QDialog( this ); - Ui_CreatePartitionTableDialog ui; - ui.setupUi( dlg.data() ); - QString areYouSure = tr( "Are you sure you want to create a new partition table on %1?" ).arg( device->name() ); - if ( PartUtils::isEfiSystem() ) - { - ui.gptRadioButton->setChecked( true ); - } - else - { - ui.mbrRadioButton->setChecked( true ); - } - - ui.areYouSureLabel->setText( areYouSure ); - if ( dlg->exec() == QDialog::Accepted ) - { - PartitionTable::TableType type = ui.mbrRadioButton->isChecked() ? PartitionTable::msdos : PartitionTable::gpt; - m_core->createPartitionTable( device, type ); - } - delete dlg; - // PartionModelReset isn't emitted after createPartitionTable, so we have to manually update - // the bootLoader index after the reset. - updateBootLoaderIndex(); -} - -bool -PartitionPage::checkCanCreate( Device* device ) -{ - auto table = device->partitionTable(); - - if ( table->type() == PartitionTable::msdos || table->type() == PartitionTable::msdos_sectorbased ) - { - cDebug() << "Checking MSDOS partition" << table->numPrimaries() << "primaries, max" << table->maxPrimaries(); - - if ( ( table->numPrimaries() >= table->maxPrimaries() ) && !table->hasExtended() ) - { - QMessageBox mb( - QMessageBox::Warning, - tr( "Can not create new partition" ), - tr( "The partition table on %1 already has %2 primary partitions, and no more can be added. " - "Please remove one primary partition and add an extended partition, instead." ) - .arg( device->name() ) - .arg( table->numPrimaries() ), - QMessageBox::Ok ); - Calamares::fixButtonLabels( &mb ); - mb.exec(); - return false; - } - return true; - } - else - { - return true; // GPT is fine - } -} - -void -PartitionPage::onNewVolumeGroupClicked() -{ - QString vgName; - QVector< const Partition* > selectedPVs; - qint64 peSize = 4; - - QVector< const Partition* > availablePVs; - - for ( const Partition* p : m_core->lvmPVs() ) - { - if ( !m_core->isInVG( p ) ) - { - availablePVs << p; - } - } - - QPointer< CreateVolumeGroupDialog > dlg - = new CreateVolumeGroupDialog( vgName, selectedPVs, availablePVs, peSize, this ); - - if ( dlg->exec() == QDialog::Accepted ) - { - QModelIndex partitionIndex = m_ui->partitionTreeView->currentIndex(); - - if ( partitionIndex.isValid() ) - { - const PartitionModel* model = static_cast< const PartitionModel* >( partitionIndex.model() ); - Q_ASSERT( model ); - Partition* partition = model->partitionForIndex( partitionIndex ); - Q_ASSERT( partition ); - - // Disable delete button if current partition was selected to be in VG - // TODO: Should Calamares edit LVM PVs which are in VGs? - if ( selectedPVs.contains( partition ) ) - { - m_ui->deleteButton->setEnabled( false ); - } - } - - QModelIndex deviceIndex = m_core->deviceModel()->index( m_ui->deviceComboBox->currentIndex(), 0 ); - Q_ASSERT( deviceIndex.isValid() ); - - QVariant previousIndexDeviceData = m_core->deviceModel()->data( deviceIndex, Qt::ToolTipRole ); - - // Creating new VG - m_core->createVolumeGroup( vgName, selectedPVs, peSize ); - - // As createVolumeGroup method call resets deviceModel, - // is needed to set the current index in deviceComboBox as the previous one - int previousIndex = m_ui->deviceComboBox->findData( previousIndexDeviceData, Qt::ToolTipRole ); - - m_ui->deviceComboBox->setCurrentIndex( ( previousIndex < 0 ) ? 0 : previousIndex ); - updateFromCurrentDevice(); - } - - delete dlg; -} - -void -PartitionPage::onResizeVolumeGroupClicked() -{ - QModelIndex deviceIndex = m_core->deviceModel()->index( m_ui->deviceComboBox->currentIndex(), 0 ); - LvmDevice* device = dynamic_cast< LvmDevice* >( m_core->deviceModel()->deviceForIndex( deviceIndex ) ); - - Q_ASSERT( device && device->type() == Device::Type::LVM_Device ); - - QVector< const Partition* > availablePVs; - QVector< const Partition* > selectedPVs; - - for ( const Partition* p : m_core->lvmPVs() ) - { - if ( !m_core->isInVG( p ) ) - { - availablePVs << p; - } - } - - QPointer< ResizeVolumeGroupDialog > dlg = new ResizeVolumeGroupDialog( device, availablePVs, selectedPVs, this ); - - if ( dlg->exec() == QDialog::Accepted ) - { - m_core->resizeVolumeGroup( device, selectedPVs ); - } - - delete dlg; -} - -void -PartitionPage::onDeactivateVolumeGroupClicked() -{ - QModelIndex deviceIndex = m_core->deviceModel()->index( m_ui->deviceComboBox->currentIndex(), 0 ); - LvmDevice* device = dynamic_cast< LvmDevice* >( m_core->deviceModel()->deviceForIndex( deviceIndex ) ); - - Q_ASSERT( device && device->type() == Device::Type::LVM_Device ); - - m_core->deactivateVolumeGroup( device ); - - updateFromCurrentDevice(); - - PartitionModel* model = m_core->partitionModelForDevice( device ); - model->update(); -} - -void -PartitionPage::onRemoveVolumeGroupClicked() -{ - QModelIndex deviceIndex = m_core->deviceModel()->index( m_ui->deviceComboBox->currentIndex(), 0 ); - LvmDevice* device = dynamic_cast< LvmDevice* >( m_core->deviceModel()->deviceForIndex( deviceIndex ) ); - - Q_ASSERT( device && device->type() == Device::Type::LVM_Device ); - - m_core->removeVolumeGroup( device ); -} - -void -PartitionPage::onCreateClicked() -{ - QModelIndex index = m_ui->partitionTreeView->currentIndex(); - Q_ASSERT( index.isValid() ); - - const PartitionModel* model = static_cast< const PartitionModel* >( index.model() ); - Partition* partition = model->partitionForIndex( index ); - Q_ASSERT( partition ); - - if ( !checkCanCreate( model->device() ) ) - { - return; - } - - QPointer< CreatePartitionDialog > dlg = new CreatePartitionDialog( - model->device(), CreatePartitionDialog::FreeSpace { partition }, getCurrentUsedMountpoints(), this ); - if ( dlg->exec() == QDialog::Accepted ) - { - Partition* newPart = dlg->getNewlyCreatedPartition(); - m_core->createPartition( model->device(), newPart, dlg->newFlags() ); - } - delete dlg; -} - -void -PartitionPage::onEditClicked() -{ - QModelIndex index = m_ui->partitionTreeView->currentIndex(); - Q_ASSERT( index.isValid() ); - - const PartitionModel* model = static_cast< const PartitionModel* >( index.model() ); - Partition* partition = model->partitionForIndex( index ); - Q_ASSERT( partition ); - - if ( Calamares::Partition::isPartitionNew( partition ) ) - { - updatePartitionToCreate( model->device(), partition ); - } - else - { - editExistingPartition( model->device(), partition ); - } -} - -void -PartitionPage::onDeleteClicked() -{ - QModelIndex index = m_ui->partitionTreeView->currentIndex(); - Q_ASSERT( index.isValid() ); - - const PartitionModel* model = static_cast< const PartitionModel* >( index.model() ); - Partition* partition = model->partitionForIndex( index ); - Q_ASSERT( partition ); - - m_core->deletePartition( model->device(), partition ); -} - - -void -PartitionPage::onRevertClicked() -{ - ScanningDialog::run( - QtConcurrent::run( - [ this ] - { - QMutexLocker locker( &m_revertMutex ); - - int oldIndex = m_ui->deviceComboBox->currentIndex(); - m_core->revertAllDevices(); - m_ui->deviceComboBox->setCurrentIndex( ( oldIndex < 0 ) ? 0 : oldIndex ); - updateFromCurrentDevice(); - } ), - [ this ] - { - m_lastSelectedBootLoaderIndex = -1; - if ( m_ui->bootLoaderComboBox->currentIndex() < 0 ) - { - m_ui->bootLoaderComboBox->setCurrentIndex( 0 ); - } - }, - this ); -} - -void -PartitionPage::onPartitionViewActivated() -{ - QModelIndex index = m_ui->partitionTreeView->currentIndex(); - if ( !index.isValid() ) - { - return; - } - - const PartitionModel* model = static_cast< const PartitionModel* >( index.model() ); - Q_ASSERT( model ); - Partition* partition = model->partitionForIndex( index ); - Q_ASSERT( partition ); - - // Use the buttons to trigger the actions so that they do nothing if they - // are disabled. Alternatively, the code could use QAction to centralize, - // but I don't expect there will be other occurences of triggering the same - // action from multiple UI elements in this page, so it does not feel worth - // the price. - if ( Calamares::Partition::isPartitionFreeSpace( partition ) ) - { - m_ui->createButton->click(); - } - else - { - m_ui->editButton->click(); - } -} - -void -PartitionPage::updatePartitionToCreate( Device* device, Partition* partition ) -{ - QStringList mountPoints = getCurrentUsedMountpoints(); - mountPoints.removeOne( PartitionInfo::mountPoint( partition ) ); - - QPointer< CreatePartitionDialog > dlg - = new CreatePartitionDialog( device, CreatePartitionDialog::FreshPartition { partition }, mountPoints, this ); - if ( dlg->exec() == QDialog::Accepted ) - { - Partition* newPartition = dlg->getNewlyCreatedPartition(); - m_core->deletePartition( device, partition ); - m_core->createPartition( device, newPartition, dlg->newFlags() ); - } - delete dlg; -} - -void -PartitionPage::editExistingPartition( Device* device, Partition* partition ) -{ - QStringList mountPoints = getCurrentUsedMountpoints(); - mountPoints.removeOne( PartitionInfo::mountPoint( partition ) ); - - QPointer< EditExistingPartitionDialog > dlg - = new EditExistingPartitionDialog( device, partition, mountPoints, this ); - if ( dlg->exec() == QDialog::Accepted ) - { - dlg->applyChanges( m_core ); - } - delete dlg; -} - -void -PartitionPage::updateBootLoaderInstallPath() -{ - if ( m_isEfi || !m_ui->bootLoaderComboBox->isVisible() ) - { - return; - } - - QVariant var = m_ui->bootLoaderComboBox->currentData( BootLoaderModel::BootLoaderPathRole ); - if ( !var.isValid() ) - { - return; - } - cDebug() << "PartitionPage::updateBootLoaderInstallPath" << var.toString(); - m_core->setBootLoaderInstallPath( var.toString() ); -} - -void -PartitionPage::updateSelectedBootLoaderIndex() -{ - m_lastSelectedBootLoaderIndex = m_ui->bootLoaderComboBox->currentIndex(); - cDebug() << "Selected bootloader index" << m_lastSelectedBootLoaderIndex; -} - -void -PartitionPage::restoreSelectedBootLoader() -{ - Calamares::restoreSelectedBootLoader( *( m_ui->bootLoaderComboBox ), m_core->bootLoaderInstallPath() ); -} - -void -PartitionPage::reconcileSelections() -{ - QModelIndex selectedIndex = m_ui->partitionBarsView->selectionModel()->currentIndex(); - selectedIndex = selectedIndex.sibling( selectedIndex.row(), 0 ); - m_ui->partitionBarsView->setCurrentIndex( selectedIndex ); - m_ui->partitionLabelsView->setCurrentIndex( selectedIndex ); -} - -void -PartitionPage::updateFromCurrentDevice() -{ - QModelIndex index = m_core->deviceModel()->index( m_ui->deviceComboBox->currentIndex(), 0 ); - if ( !index.isValid() ) - { - return; - } - - Device* device = m_core->deviceModel()->deviceForIndex( index ); - - QAbstractItemModel* oldModel = m_ui->partitionTreeView->model(); - if ( oldModel ) - { - disconnect( oldModel, nullptr, this, nullptr ); - } - - PartitionModel* model = m_core->partitionModelForDevice( device ); - m_ui->partitionBarsView->setModel( model ); - m_ui->partitionLabelsView->setModel( model ); - m_ui->partitionTreeView->setModel( model ); - m_ui->partitionTreeView->expandAll(); - - // Make all views use the same selection model. - if ( m_ui->partitionBarsView->selectionModel() != m_ui->partitionTreeView->selectionModel() - || m_ui->partitionBarsView->selectionModel() != m_ui->partitionLabelsView->selectionModel() ) - { - // Tree view - QItemSelectionModel* selectionModel = m_ui->partitionTreeView->selectionModel(); - m_ui->partitionTreeView->setSelectionModel( m_ui->partitionBarsView->selectionModel() ); - selectionModel->deleteLater(); - - // Labels view - selectionModel = m_ui->partitionLabelsView->selectionModel(); - m_ui->partitionLabelsView->setSelectionModel( m_ui->partitionBarsView->selectionModel() ); - selectionModel->deleteLater(); - } - - // This is necessary because even with the same selection model it might happen that - // a !=0 column is selected in the tree view, which for some reason doesn't trigger a - // timely repaint in the bars view. - connect( m_ui->partitionBarsView->selectionModel(), - &QItemSelectionModel::currentChanged, - this, - &PartitionPage::reconcileSelections, - Qt::UniqueConnection ); - - // Must be done here because we need to have a model set to define - // individual column resize mode - QHeaderView* header = m_ui->partitionTreeView->header(); - header->setSectionResizeMode( QHeaderView::ResizeToContents ); - header->setSectionResizeMode( 0, QHeaderView::Stretch ); - - updateButtons(); - // Establish connection here because selection model is destroyed when - // model changes - connect( m_ui->partitionTreeView->selectionModel(), - &QItemSelectionModel::currentChanged, - [ this ]( const QModelIndex&, const QModelIndex& ) { updateButtons(); } ); - connect( model, &QAbstractItemModel::modelReset, this, &PartitionPage::onPartitionModelReset ); -} - -void -PartitionPage::onPartitionModelReset() -{ - m_ui->partitionTreeView->expandAll(); - updateButtons(); - updateBootLoaderIndex(); -} - -void -PartitionPage::updateBootLoaderIndex() -{ - // set bootloader back to user selected index - if ( m_lastSelectedBootLoaderIndex >= 0 && m_ui->bootLoaderComboBox->count() ) - { - m_ui->bootLoaderComboBox->setCurrentIndex( m_lastSelectedBootLoaderIndex ); - } -} - -QStringList -PartitionPage::getCurrentUsedMountpoints() -{ - QModelIndex index = m_core->deviceModel()->index( m_ui->deviceComboBox->currentIndex(), 0 ); - if ( !index.isValid() ) - { - return QStringList(); - } - - Device* device = m_core->deviceModel()->deviceForIndex( index ); - QStringList mountPoints; - - for ( Partition* partition : device->partitionTable()->children() ) - { - const QString& mountPoint = PartitionInfo::mountPoint( partition ); - if ( !mountPoint.isEmpty() ) - { - mountPoints << mountPoint; - } - } - - return mountPoints; -} - -int -PartitionPage::selectedDeviceIndex() -{ - return m_ui->deviceComboBox->currentIndex(); -} - -void -PartitionPage::selectDeviceByIndex( int index ) -{ - m_ui->deviceComboBox->setCurrentIndex( index ); -} diff --git a/src/modules/partition/gui/PartitionPage.h b/src/modules/partition/gui/PartitionPage.h deleted file mode 100644 index d3ae60eb83..0000000000 --- a/src/modules/partition/gui/PartitionPage.h +++ /dev/null @@ -1,89 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2018-2019 Adriaan de Groot - * SPDX-FileCopyrightText: 2019 Collabora Ltd - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef PARTITIONPAGE_H -#define PARTITIONPAGE_H - -#include -#include -#include - -class PartitionCoreModule; -class Ui_PartitionPage; - -class Device; -class Partition; - -/** - * The user interface for the module. - * - * Shows the information exposed by PartitionCoreModule and asks it to schedule - * jobs according to user actions. - */ -class PartitionPage : public QWidget -{ - Q_OBJECT -public: - explicit PartitionPage( PartitionCoreModule* core, QWidget* parent = nullptr ); - ~PartitionPage() override; - - void onRevertClicked(); - - int selectedDeviceIndex(); - void selectDeviceByIndex( int index ); - -private Q_SLOTS: - /// @brief Update everything when the base device changes - void updateFromCurrentDevice(); - /// @brief Update when the selected device for boot loader changes - void updateBootLoaderInstallPath(); - /// @brief Explicitly selected boot loader path - void updateSelectedBootLoaderIndex(); - /// @brief After boot loader model changes, try to preserve previously set value - void restoreSelectedBootLoader(); - /// @brief Make the selections in each widget match - void reconcileSelections(); - -private: - QScopedPointer< Ui_PartitionPage > m_ui; - PartitionCoreModule* m_core; - void updateButtons(); - void onNewPartitionTableClicked(); - void onNewVolumeGroupClicked(); - void onResizeVolumeGroupClicked(); - void onDeactivateVolumeGroupClicked(); - void onRemoveVolumeGroupClicked(); - void onCreateClicked(); - void onEditClicked(); - void onDeleteClicked(); - void onPartitionViewActivated(); - void onPartitionModelReset(); - - void updatePartitionToCreate( Device*, Partition* ); - void editExistingPartition( Device*, Partition* ); - void updateBootLoaderIndex(); - - /** - * @brief Check if a new partition can be created (as primary) on the device. - * - * Returns true if a new partition can be created on the device. Provides - * a warning popup and returns false if it cannot. - */ - bool checkCanCreate( Device* ); - - QStringList getCurrentUsedMountpoints(); - - QMutex m_revertMutex; - int m_lastSelectedBootLoaderIndex; - bool m_isEfi; -}; - -#endif // PARTITIONPAGE_H diff --git a/src/modules/partition/gui/PartitionPage.ui b/src/modules/partition/gui/PartitionPage.ui deleted file mode 100644 index ddbd21bf69..0000000000 --- a/src/modules/partition/gui/PartitionPage.ui +++ /dev/null @@ -1,241 +0,0 @@ - - - -SPDX-FileCopyrightText: 2014 Aurélien Gâteau <agateau@kde.org> -SPDX-License-Identifier: GPL-3.0-or-later - - PartitionPage - - - - 0 - 0 - 684 - 304 - - - - Form - - - - - - - - Storage de&vice: - - - deviceComboBox - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - false - - - &Revert All Changes - - - - - - - - - - - - - - - QAbstractItemView::NoEditTriggers - - - false - - - true - - - false - - - false - - - - - - - - - New Partition &Table - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Cre&ate - - - - - - - &Edit - - - - - - - &Delete - - - - - - - - - - - New Volume Group - - - - - - - Resize Volume Group - - - - - - - Deactivate Volume Group - - - - - - - Remove Volume Group - - - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 24 - - - - - - - - - - I&nstall boot loader on: - - - bootLoaderComboBox - - - - - - - QComboBox::AdjustToContents - - - - - - - Qt::Horizontal - - - - 40 - 1 - - - - - - - - - - - PartitionBarsView - QFrame -
    gui/PartitionBarsView.h
    - 1 -
    - - PartitionLabelsView - QFrame -
    gui/PartitionLabelsView.h
    - 1 -
    -
    - - deviceComboBox - revertButton - partitionTreeView - newPartitionTableButton - createButton - editButton - deleteButton - bootLoaderComboBox - - - -
    diff --git a/src/modules/partition/gui/PartitionSizeController.cpp b/src/modules/partition/gui/PartitionSizeController.cpp deleted file mode 100644 index c21ebd1c4e..0000000000 --- a/src/modules/partition/gui/PartitionSizeController.cpp +++ /dev/null @@ -1,221 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2016 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "gui/PartitionSizeController.h" - -#include "core/ColorUtils.h" -#include "core/KPMHelpers.h" - -#include "utils/Units.h" - -// Qt -#include - -// KPMcore -#include -#include - -// stdc++ -#include - -PartitionSizeController::PartitionSizeController( QObject* parent ) - : QObject( parent ) -{ -} - -void -PartitionSizeController::init( Device* device, Partition* partition, const QColor& color ) -{ - m_device = device; - m_originalPartition = partition; - // PartResizerWidget stores its changes directly in the partition it is - // initialized with. We don't want the changes to be committed that way, - // because it means we would have to revert them if the user cancel the - // dialog the widget is in. Therefore we init PartResizerWidget with a clone - // of the original partition. - m_partition.reset( KPMHelpers::clonePartition( m_device, partition ) ); - m_partitionColor = color; -} - -void -PartitionSizeController::setPartResizerWidget( PartResizerWidget* widget, bool format ) -{ - Q_ASSERT( m_device ); - - if ( m_partResizerWidget ) - { - disconnect( m_partResizerWidget, nullptr, this, nullptr ); - } - - m_dirty = false; - m_currentSpinBoxValue = -1; - - // Update partition filesystem. This must be done *before* the call to - // PartResizerWidget::init() otherwise it will be ignored by the widget. - // This is why this method accept a `format` boolean. - qint64 used = format ? 0 : m_originalPartition->fileSystem().sectorsUsed(); - m_partition->fileSystem().setSectorsUsed( used ); - - // Init PartResizerWidget - m_partResizerWidget = widget; - PartitionTable* table = m_device->partitionTable(); - qint64 minFirstSector = m_originalPartition->firstSector() - table->freeSectorsBefore( *m_originalPartition ); - qint64 maxLastSector = m_originalPartition->lastSector() + table->freeSectorsAfter( *m_originalPartition ); - m_partResizerWidget->init( *m_device, *m_partition.data(), minFirstSector, maxLastSector ); - - // FIXME: Should be set by PartResizerWidget itself - m_partResizerWidget->setFixedHeight( PartResizerWidget::handleHeight() ); - - QPalette pal = widget->palette(); - pal.setColor( QPalette::Base, ColorUtils::freeSpaceColor() ); - pal.setColor( QPalette::Button, m_partitionColor ); - m_partResizerWidget->setPalette( pal ); - connectWidgets(); - - if ( !format ) - { - // If we are not formatting, update the widget to make sure the space - // between the first and last sectors is big enough to fit the existing - // content. - m_updating = true; - - qint64 firstSector = m_partition->firstSector(); - qint64 lastSector = m_partition->lastSector(); - - // This first time we call doAAUPRW with real first/last sector, - // all further calls will come from updatePartResizerWidget, and - // will therefore use values calculated from the SpinBox. - doAlignAndUpdatePartResizerWidget( firstSector, lastSector ); - - m_updating = false; - } -} - -void -PartitionSizeController::setSpinBox( QSpinBox* spinBox ) -{ - if ( m_spinBox ) - { - disconnect( m_spinBox, nullptr, this, nullptr ); - } - m_spinBox = spinBox; - m_spinBox->setMaximum( std::numeric_limits< int >::max() ); - connectWidgets(); -} - -void -PartitionSizeController::connectWidgets() -{ - if ( !m_spinBox || !m_partResizerWidget ) - { - return; - } - - connect( m_spinBox, SIGNAL( editingFinished() ), SLOT( updatePartResizerWidget() ) ); - connect( m_partResizerWidget, SIGNAL( firstSectorChanged( qint64 ) ), SLOT( updateSpinBox() ) ); - connect( m_partResizerWidget, SIGNAL( lastSectorChanged( qint64 ) ), SLOT( updateSpinBox() ) ); - - // Init m_spinBox from m_partResizerWidget - updateSpinBox(); -} - -void -PartitionSizeController::updatePartResizerWidget() -{ - if ( m_updating ) - { - return; - } - if ( m_spinBox->value() == m_currentSpinBoxValue ) - { - return; - } - - m_updating = true; - qint64 sectorSize = qint64( m_spinBox->value() ) * 1024 * 1024 / m_device->logicalSize(); - - qint64 firstSector = m_partition->firstSector(); - qint64 lastSector = firstSector + sectorSize - 1; - - doAlignAndUpdatePartResizerWidget( firstSector, lastSector ); - - m_updating = false; -} - -void -PartitionSizeController::doAlignAndUpdatePartResizerWidget( qint64 firstSector, qint64 lastSector ) -{ - if ( lastSector > m_partResizerWidget->maximumLastSector() ) - { - qint64 delta = lastSector - m_partResizerWidget->maximumLastSector(); - firstSector -= delta; - lastSector -= delta; - } - if ( lastSector != m_partition->lastSector() ) - { - m_partResizerWidget->updateLastSector( lastSector ); - m_dirty = true; - } - if ( firstSector != m_partition->firstSector() ) - { - m_partResizerWidget->updateFirstSector( firstSector ); - m_dirty = true; - } - - // Update spinbox value in case it was an impossible value - doUpdateSpinBox(); -} - -void -PartitionSizeController::updateSpinBox() -{ - if ( m_updating ) - { - return; - } - m_updating = true; - doUpdateSpinBox(); - m_updating = false; -} - -void -PartitionSizeController::doUpdateSpinBox() -{ - if ( !m_spinBox ) - { - return; - } - int mbSize = Calamares::BytesToMiB( m_partition->length() * m_device->logicalSize() ); - m_spinBox->setValue( mbSize ); - if ( m_currentSpinBoxValue != -1 && //if it's not the first time we're setting it - m_currentSpinBoxValue != mbSize ) //and the operation changes the SB value - { - m_dirty = true; - } - m_currentSpinBoxValue = mbSize; -} - -qint64 -PartitionSizeController::firstSector() const -{ - return m_partition->firstSector(); -} - -qint64 -PartitionSizeController::lastSector() const -{ - return m_partition->lastSector(); -} - -bool -PartitionSizeController::isDirty() const -{ - return m_dirty; -} diff --git a/src/modules/partition/gui/PartitionSizeController.h b/src/modules/partition/gui/PartitionSizeController.h deleted file mode 100644 index 69cf2ef216..0000000000 --- a/src/modules/partition/gui/PartitionSizeController.h +++ /dev/null @@ -1,72 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2016 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef PARTITIONSIZECONTROLLER_H -#define PARTITIONSIZECONTROLLER_H - -// KPMcore -#include - -// Qt -#include -#include -#include -#include - -class QSpinBox; - -class Device; -class Partition; -class PartResizerWidget; - -/** - * Synchronizes a PartResizerWidget and a QSpinBox, making sure any change made - * to one is reflected in the other. - * - * It does not touch the partition it works on: changes are exposed through the - * firstSector() and lastSector() getters. - */ -class PartitionSizeController : public QObject -{ - Q_OBJECT -public: - explicit PartitionSizeController( QObject* parent = nullptr ); - void init( Device* device, Partition* partition, const QColor& color ); - void setPartResizerWidget( PartResizerWidget* widget, bool format = true ); - void setSpinBox( QSpinBox* spinBox ); - - qint64 firstSector() const; - qint64 lastSector() const; - - bool isDirty() const; - -private: - QPointer< PartResizerWidget > m_partResizerWidget; - QPointer< QSpinBox > m_spinBox; - Device* m_device = nullptr; - const Partition* m_originalPartition = nullptr; - QScopedPointer< Partition > m_partition; - QColor m_partitionColor; - - bool m_updating = false; - - void connectWidgets(); - void doUpdateSpinBox(); - void doAlignAndUpdatePartResizerWidget( qint64 fistSector, qint64 lastSector ); - - bool m_dirty = false; - qint64 m_currentSpinBoxValue = -1; - -private Q_SLOTS: - void updatePartResizerWidget(); - void updateSpinBox(); -}; - -#endif /* PARTITIONSIZECONTROLLER_H */ diff --git a/src/modules/partition/gui/PartitionSplitterWidget.cpp b/src/modules/partition/gui/PartitionSplitterWidget.cpp deleted file mode 100644 index 9fef8e348b..0000000000 --- a/src/modules/partition/gui/PartitionSplitterWidget.cpp +++ /dev/null @@ -1,636 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2016 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "PartitionSplitterWidget.h" - -#include "core/ColorUtils.h" -#include "core/KPMHelpers.h" - -#include "partition/PartitionIterator.h" -#include "partition/PartitionQuery.h" -#include "utils/Logger.h" - -#include "utils/Gui.h" - -#include -#include - -#include -#include -#include -#include -#include - -using Calamares::Partition::PartitionIterator; - -static const int VIEW_HEIGHT = qMax( Calamares::defaultFontHeight() + 8, // wins out with big fonts - int( Calamares::defaultFontHeight() * 0.6 ) + 22 ); // wins out with small fonts -static const int CORNER_RADIUS = 3; -static const int EXTENDED_PARTITION_MARGIN = qMax( 4, VIEW_HEIGHT / 6 ); - -/** @brief Applies @p operation to each item - * - * A PartitionSplitterItem can contain a tree of items (each item has its - * own list of children) so recurse over all the children. Returns a count - * of how many items were affected. - */ -static int -countTransform( QVector< PartitionSplitterItem >& items, - const std::function< bool( PartitionSplitterItem& ) >& operation ) -{ - int opCount = 0; - for ( auto it = items.begin(); it != items.end(); ++it ) - { - if ( operation( *it ) ) - { - opCount++; - } - - opCount += countTransform( it->children, operation ); - } - return opCount; -} - -static PartitionSplitterItem -findTransform( QVector< PartitionSplitterItem >& items, std::function< bool( PartitionSplitterItem& ) > condition ) -{ - for ( auto it = items.begin(); it != items.end(); ++it ) - { - if ( condition( *it ) ) - { - return *it; - } - - PartitionSplitterItem candidate = findTransform( it->children, condition ); - if ( !candidate.isNull() ) - { - return candidate; - } - } - return PartitionSplitterItem::null(); -} - -PartitionSplitterWidget::PartitionSplitterWidget( QWidget* parent ) - : QWidget( parent ) - , m_itemToResize( PartitionSplitterItem::null() ) - , m_itemToResizeNext( PartitionSplitterItem::null() ) - , m_itemMinSize( 0 ) - , m_itemMaxSize( 0 ) - , m_itemPrefSize( 0 ) - , m_resizing( false ) - , m_resizeHandleX( 0 ) - , HANDLE_SNAP( QApplication::startDragDistance() ) - , m_drawNestedPartitions( false ) -{ - setMouseTracking( true ); -} - -void -PartitionSplitterWidget::init( Device* dev, bool drawNestedPartitions ) -{ - m_drawNestedPartitions = drawNestedPartitions; - QVector< PartitionSplitterItem > allPartitionItems; - PartitionSplitterItem* extendedPartitionItem = nullptr; - for ( auto it = PartitionIterator::begin( dev ); it != PartitionIterator::end( dev ); ++it ) - { - PartitionSplitterItem newItem = { ( *it )->partitionPath(), - ColorUtils::colorForPartition( *it ), - Calamares::Partition::isPartitionFreeSpace( *it ), - ( *it )->capacity(), - PartitionSplitterItem::Normal, - {} }; - - // If we don't draw child partitions of a partitions as child partitions, we - // need to flatten the items tree into an items list - if ( drawNestedPartitions ) - { - if ( ( *it )->roles().has( PartitionRole::Logical ) && extendedPartitionItem ) - { - extendedPartitionItem->children.append( newItem ); - } - else - { - allPartitionItems.append( newItem ); - if ( ( *it )->roles().has( PartitionRole::Extended ) ) - { - extendedPartitionItem = &allPartitionItems.last(); - } - } - } - else - { - if ( !( *it )->roles().has( PartitionRole::Extended ) ) - { - allPartitionItems.append( newItem ); - } - } - } - - setupItems( allPartitionItems ); -} - -void -PartitionSplitterWidget::setupItems( const QVector< PartitionSplitterItem >& items ) -{ - m_itemToResize = PartitionSplitterItem::null(); - m_itemToResizeNext = PartitionSplitterItem::null(); - m_itemToResizePath.clear(); - - m_items.clear(); - m_items = items; - repaint(); - for ( const PartitionSplitterItem& item : items ) - { - cDebug() << "PSI added item" << item.itemPath << "size" << item.size; - } -} - -void -PartitionSplitterWidget::setSplitPartition( const QString& path, qint64 minSize, qint64 maxSize, qint64 preferredSize ) -{ - cDebug() << "path:" << path << Logger::Continuation << "minSize:" << minSize << Logger::Continuation - << "maxSize:" << maxSize << Logger::Continuation << "prfSize:" << preferredSize; - - if ( m_itemToResize && m_itemToResizeNext ) - { - cDebug() << "NOTICE: trying to split partition but partition to split is already set."; - - // We need to remove the itemToResizeNext from wherever it is - for ( int i = 0; i < m_items.count(); ++i ) - { - if ( m_items[ i ].itemPath == m_itemToResize.itemPath - && m_items[ i ].status == PartitionSplitterItem::Resizing && i + 1 < m_items.count() ) - { - m_items[ i ].size = m_items[ i ].size + m_itemToResizeNext.size; - m_items[ i ].status = PartitionSplitterItem::Normal; - m_items.removeAt( i + 1 ); - m_itemToResizeNext = PartitionSplitterItem::null(); - break; - } - else if ( !m_items[ i ].children.isEmpty() ) - { - for ( int j = 0; j < m_items[ i ].children.count(); ++j ) - { - if ( m_items[ i ].children[ j ].itemPath == m_itemToResize.itemPath - && j + 1 < m_items[ i ].children.count() ) - { - m_items[ i ].children[ j ].size = m_items[ i ].children[ j ].size + m_itemToResizeNext.size; - m_items[ i ].children[ j ].status = PartitionSplitterItem::Normal; - m_items[ i ].children.removeAt( j + 1 ); - m_itemToResizeNext = PartitionSplitterItem::null(); - break; - } - } - if ( m_itemToResizeNext.isNull() ) - { - break; - } - } - } - - m_itemToResize = PartitionSplitterItem::null(); - m_itemToResizePath.clear(); - } - - PartitionSplitterItem itemToResize = findTransform( m_items, - [ path ]( PartitionSplitterItem& item ) -> bool - { - if ( path == item.itemPath ) - { - item.status = PartitionSplitterItem::Resizing; - return true; - } - return false; - } ); - - if ( itemToResize.isNull() ) - { - return; - } - cDebug() << "itemToResize:" << itemToResize.itemPath; - - m_itemToResize = itemToResize; - m_itemToResizePath = path; - - if ( preferredSize > maxSize ) - { - preferredSize = maxSize; - } - - qint64 newSize = m_itemToResize.size - preferredSize; - m_itemToResize.size = preferredSize; - int opCount = countTransform( m_items, - [ preferredSize ]( PartitionSplitterItem& item ) -> bool - { - if ( item.status == PartitionSplitterItem::Resizing ) - { - item.size = preferredSize; - return true; - } - return false; - } ); - cDebug() << "each splitter item opcount:" << opCount; - m_itemMinSize = minSize; - m_itemMaxSize = maxSize; - m_itemPrefSize = preferredSize; - - for ( int i = 0; i < m_items.count(); ++i ) - { - if ( m_items[ i ].itemPath == itemToResize.itemPath ) - { - m_items.insert( i + 1, - { "", QColor( "#c0392b" ), false, newSize, PartitionSplitterItem::ResizingNext, {} } ); - m_itemToResizeNext = m_items[ i + 1 ]; - break; - } - else if ( !m_items[ i ].children.isEmpty() ) - { - for ( int j = 0; j < m_items[ i ].children.count(); ++j ) - { - if ( m_items[ i ].children[ j ].itemPath == itemToResize.itemPath ) - { - m_items[ i ].children.insert( - j + 1, { "", QColor( "#c0392b" ), false, newSize, PartitionSplitterItem::ResizingNext, {} } ); - m_itemToResizeNext = m_items[ i ].children[ j + 1 ]; - break; - } - } - if ( !m_itemToResizeNext.isNull() ) - { - break; - } - } - } - - Q_EMIT partitionResized( m_itemToResize.itemPath, m_itemToResize.size, m_itemToResizeNext.size ); - - cDebug() << "Items updated. Status:"; - foreach ( const PartitionSplitterItem& item, m_items ) - { - cDebug() << "item" << item.itemPath << "size" << item.size << "status:" << item.status; - } - - cDebug() << "m_itemToResize: " << !m_itemToResize.isNull() << m_itemToResize.itemPath; - cDebug() << "m_itemToResizeNext:" << !m_itemToResizeNext.isNull() << m_itemToResizeNext.itemPath; - - repaint(); -} - -qint64 -PartitionSplitterWidget::splitPartitionSize() const -{ - if ( !m_itemToResize ) - { - return -1; - } - return m_itemToResize.size; -} - -qint64 -PartitionSplitterWidget::newPartitionSize() const -{ - if ( !m_itemToResizeNext ) - { - return -1; - } - return m_itemToResizeNext.size; -} - -QSize -PartitionSplitterWidget::sizeHint() const -{ - return QSize( -1, VIEW_HEIGHT ); -} - -QSize -PartitionSplitterWidget::minimumSizeHint() const -{ - return sizeHint(); -} - -void -PartitionSplitterWidget::paintEvent( QPaintEvent* event ) -{ - Q_UNUSED( event ) - - QPainter painter( this ); - painter.fillRect( rect(), palette().window() ); - painter.setRenderHint( QPainter::Antialiasing ); - - drawPartitions( &painter, rect(), m_items ); -} - -void -PartitionSplitterWidget::mousePressEvent( QMouseEvent* event ) -{ - if ( m_itemToResize && m_itemToResizeNext && event->button() == Qt::LeftButton ) - { -#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) - if ( qAbs( event->x() - m_resizeHandleX ) < HANDLE_SNAP ) -#else - if ( qAbs( event->position().x() - m_resizeHandleX ) < HANDLE_SNAP ) -#endif - { - m_resizing = true; - } - } -} - -void -PartitionSplitterWidget::mouseMoveEvent( QMouseEvent* event ) -{ - if ( m_resizing ) - { - qint64 start = 0; - QString itemPath = m_itemToResize.itemPath; - for ( auto it = m_items.constBegin(); it != m_items.constEnd(); ++it ) - { - if ( it->itemPath == itemPath ) - { - break; - } - else if ( !it->children.isEmpty() ) - { - bool done = false; - for ( auto jt = it->children.constBegin(); jt != it->children.constEnd(); ++jt ) - { - if ( jt->itemPath == itemPath ) - { - done = true; - break; - } - start += jt->size; - } - if ( done ) - { - break; - } - } - else - { - start += it->size; - } - } - - qint64 total = 0; - for ( auto it = m_items.constBegin(); it != m_items.constEnd(); ++it ) - { - total += it->size; - } - - int ew = rect().width(); //effective width - qreal bpp = total / static_cast< qreal >( ew ); //bytes per pixel - -#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) - qreal mx = event->x() * bpp - start; -#else - qreal mx = event->position().x() * bpp - start; -#endif - - // make sure we are within resize range - mx = qBound( static_cast< qreal >( m_itemMinSize ), mx, static_cast< qreal >( m_itemMaxSize ) ); - - qint64 span = m_itemPrefSize; - qreal percent = mx / span; - qint64 oldsize = m_itemToResize.size; - - m_itemToResize.size = qRound64( span * percent ); - m_itemToResizeNext.size -= m_itemToResize.size - oldsize; - countTransform( m_items, - [ this ]( PartitionSplitterItem& item ) -> bool - { - if ( item.status == PartitionSplitterItem::Resizing ) - { - item.size = m_itemToResize.size; - return true; - } - else if ( item.status == PartitionSplitterItem::ResizingNext ) - { - item.size = m_itemToResizeNext.size; - return true; - } - return false; - } ); - - repaint(); - - Q_EMIT partitionResized( itemPath, m_itemToResize.size, m_itemToResizeNext.size ); - } - else - { - if ( m_itemToResize && m_itemToResizeNext ) - { -#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) - if ( qAbs( event->x() - m_resizeHandleX ) < HANDLE_SNAP ) -#else - if ( qAbs( event->position().x() - m_resizeHandleX ) < HANDLE_SNAP ) -#endif - { - setCursor( Qt::SplitHCursor ); - } - else if ( cursor().shape() != Qt::ArrowCursor ) - { - setCursor( Qt::ArrowCursor ); - } - } - } -} - -void -PartitionSplitterWidget::mouseReleaseEvent( QMouseEvent* event ) -{ - Q_UNUSED( event ) - - m_resizing = false; -} - -void -PartitionSplitterWidget::drawSection( QPainter* painter, - const QRect& rect_, - int x, - int width, - const PartitionSplitterItem& item ) -{ - QColor color = item.color; - bool isFreeSpace = item.isFreeSpace; - - QRect rect = rect_; - const int y = rect.y(); - const int rectHeight = rect.height(); - const int radius = qMax( 1, CORNER_RADIUS - ( height() - rectHeight ) / 2 ); - painter->setClipRect( x, y, width, rectHeight ); - painter->translate( 0.5, 0.5 ); - - rect.adjust( 0, 0, -1, -1 ); - const QColor borderColor = color.darker(); - painter->setPen( borderColor ); - painter->setBrush( color ); - painter->drawRoundedRect( rect, radius, radius ); - - // Draw shade - if ( !isFreeSpace ) - { - rect.adjust( 2, 2, -2, -2 ); - } - - QLinearGradient gradient( 0, 0, 0, rectHeight / 2 ); - - qreal c = isFreeSpace ? 0 : 1; - gradient.setColorAt( 0, QColor::fromRgbF( c, c, c, 0.3 ) ); - gradient.setColorAt( 1, QColor::fromRgbF( c, c, c, 0 ) ); - - painter->setPen( Qt::NoPen ); - painter->setBrush( gradient ); - painter->drawRoundedRect( rect, radius, radius ); - - painter->translate( -0.5, -0.5 ); -} - -void -PartitionSplitterWidget::drawResizeHandle( QPainter* painter, const QRect& rect_, int x ) -{ - if ( !m_itemToResize ) - { - return; - } - - painter->setPen( Qt::NoPen ); - painter->setBrush( Qt::black ); - painter->setClipRect( rect_ ); - - painter->setRenderHint( QPainter::Antialiasing, true ); - - qreal h = VIEW_HEIGHT; // Put the arrow in the center regardless of inner box height - int scaleFactor = qRound( height() / static_cast< qreal >( VIEW_HEIGHT ) ); - QList< QPair< qreal, qreal > > arrow_offsets - = { qMakePair( 0, h / 2 - 1 ), qMakePair( 4, h / 2 - 1 ), qMakePair( 4, h / 2 - 3 ), qMakePair( 8, h / 2 ), - qMakePair( 4, h / 2 + 3 ), qMakePair( 4, h / 2 + 1 ), qMakePair( 0, h / 2 + 1 ) }; - for ( int i = 0; i < arrow_offsets.count(); ++i ) - { - arrow_offsets[ i ] = qMakePair( arrow_offsets[ i ].first * scaleFactor, - ( arrow_offsets[ i ].second - h / 2 ) * scaleFactor + h / 2 ); - } - - auto p1 = arrow_offsets[ 0 ]; - if ( m_itemToResize.size > m_itemMinSize ) - { - auto arrow = QPainterPath( QPointF( x + -1 * p1.first, p1.second ) ); - for ( auto p : arrow_offsets ) - { - arrow.lineTo( x + -1 * p.first + 1, p.second ); - } - painter->drawPath( arrow ); - } - - if ( m_itemToResize.size < m_itemMaxSize ) - { - auto arrow = QPainterPath( QPointF( x + p1.first, p1.second ) ); - for ( auto p : arrow_offsets ) - { - arrow.lineTo( x + p.first, p.second ); - } - painter->drawPath( arrow ); - } - - painter->setRenderHint( QPainter::Antialiasing, false ); - painter->setPen( Qt::black ); - painter->drawLine( x, 0, x, int( h ) - 1 ); -} - -void -PartitionSplitterWidget::drawPartitions( QPainter* painter, - const QRect& rect, - const QVector< PartitionSplitterItem >& itemList ) -{ - const int count = itemList.count(); - const int totalWidth = rect.width(); - - auto pair = computeItemsVector( itemList ); - QVector< PartitionSplitterItem >& items = pair.first; - qreal total = pair.second; - - int x = rect.x(); - for ( int row = 0; row < count; ++row ) - { - const PartitionSplitterItem& item = items[ row ]; - qreal width; - if ( row < count - 1 ) - { - width = totalWidth * ( item.size / total ); - } - else - // Make sure we fill the last pixel column - { - width = rect.right() - x + 1; - } - - drawSection( painter, rect, x, int( width ), item ); - if ( !item.children.isEmpty() ) - { - QRect subRect( x + EXTENDED_PARTITION_MARGIN, - rect.y() + EXTENDED_PARTITION_MARGIN, - int( width ) - 2 * EXTENDED_PARTITION_MARGIN, - rect.height() - 2 * EXTENDED_PARTITION_MARGIN ); - drawPartitions( painter, subRect, item.children ); - } - - // If an item to resize and the following new item both exist, - // and this is not the very first partition, - // and the partition preceding this one is the item to resize... - if ( m_itemToResize && m_itemToResizeNext && row > 0 && !items[ row - 1 ].isFreeSpace - && !items[ row - 1 ].itemPath.isEmpty() && items[ row - 1 ].itemPath == m_itemToResize.itemPath ) - { - m_resizeHandleX = x; - drawResizeHandle( painter, rect, m_resizeHandleX ); - } - - x += width; - } -} - -QPair< QVector< PartitionSplitterItem >, qreal > -PartitionSplitterWidget::computeItemsVector( const QVector< PartitionSplitterItem >& originalItems ) const -{ - QVector< PartitionSplitterItem > items; - - qreal total = 0; - for ( int row = 0; row < originalItems.count(); ++row ) - { - if ( originalItems[ row ].children.isEmpty() ) - { - items += originalItems[ row ]; - total += originalItems[ row ].size; - } - else - { - PartitionSplitterItem thisItem = originalItems[ row ]; - QPair< QVector< PartitionSplitterItem >, qreal > pair = computeItemsVector( thisItem.children ); - thisItem.children = pair.first; - thisItem.size = qint64( pair.second ); - items += thisItem; - total += thisItem.size; - } - } - - // The sizes we have are perfect, but now we have to hardcode a minimum size for small - // partitions and compensate for it in the total. - qreal adjustedTotal = total; - for ( int row = 0; row < items.count(); ++row ) - { - if ( items[ row ].size < 0.01 * total ) // If this item is smaller than 1% of everything, - { - // force its width to 1%. - adjustedTotal -= items[ row ].size; - items[ row ].size = qint64( 0.01 * total ); - adjustedTotal += items[ row ].size; - } - } - - return qMakePair( items, adjustedTotal ); -} diff --git a/src/modules/partition/gui/PartitionSplitterWidget.h b/src/modules/partition/gui/PartitionSplitterWidget.h deleted file mode 100644 index 53f5b0b372..0000000000 --- a/src/modules/partition/gui/PartitionSplitterWidget.h +++ /dev/null @@ -1,94 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2016 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef PARTITIONSPLITTERWIDGET_H -#define PARTITIONSPLITTERWIDGET_H - -#include - -#include - -class Device; - -struct PartitionSplitterItem -{ - enum Status - { - Normal = 0, - Resizing, - ResizingNext - }; - - QString itemPath; - QColor color; - bool isFreeSpace; - qint64 size; - Status status; - - using ChildVector = QVector< PartitionSplitterItem >; - ChildVector children; - - static PartitionSplitterItem null() { return { QString(), QColor(), false, 0, Normal, ChildVector() }; } - - bool isNull() const { return itemPath.isEmpty() && size == 0 && status == Normal; } - operator bool() const { return !isNull(); } -}; - -class PartitionSplitterWidget : public QWidget -{ - Q_OBJECT -public: - explicit PartitionSplitterWidget( QWidget* parent = nullptr ); - - void init( Device* dev, bool drawNestedPartitions ); - - void setSplitPartition( const QString& path, qint64 minSize, qint64 maxSize, qint64 preferredSize ); - - qint64 splitPartitionSize() const; - qint64 newPartitionSize() const; - - QSize sizeHint() const override; - QSize minimumSizeHint() const override; - -signals: - void partitionResized( const QString&, qint64, qint64 ); - -protected: - void paintEvent( QPaintEvent* event ) override; - void mousePressEvent( QMouseEvent* event ) override; - void mouseMoveEvent( QMouseEvent* event ) override; - void mouseReleaseEvent( QMouseEvent* event ) override; - -private: - void setupItems( const QVector< PartitionSplitterItem >& items ); - - void drawPartitions( QPainter* painter, const QRect& rect, const QVector< PartitionSplitterItem >& itemList ); - void drawSection( QPainter* painter, const QRect& rect_, int x, int width, const PartitionSplitterItem& item ); - void drawResizeHandle( QPainter* painter, const QRect& rect_, int x ); - - QPair< QVector< PartitionSplitterItem >, qreal > - computeItemsVector( const QVector< PartitionSplitterItem >& originalItems ) const; - - QVector< PartitionSplitterItem > m_items; - QString m_itemToResizePath; - PartitionSplitterItem m_itemToResize; - PartitionSplitterItem m_itemToResizeNext; - - qint64 m_itemMinSize; - qint64 m_itemMaxSize; - qint64 m_itemPrefSize; - bool m_resizing; - int m_resizeHandleX; - - const int HANDLE_SNAP; - - bool m_drawNestedPartitions; -}; - -#endif // PARTITIONSPLITTERWIDGET_H diff --git a/src/modules/partition/gui/PartitionViewSelectionFilter.h b/src/modules/partition/gui/PartitionViewSelectionFilter.h deleted file mode 100644 index fc2f5bcb30..0000000000 --- a/src/modules/partition/gui/PartitionViewSelectionFilter.h +++ /dev/null @@ -1,19 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2016 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef PARTITIONVIEWSELECTIONFILTER_H -#define PARTITIONVIEWSELECTIONFILTER_H - -#include - -#include - -typedef std::function< bool( const QModelIndex& ) > SelectionFilter; - -#endif // PARTITIONVIEWSELECTIONFILTER_H diff --git a/src/modules/partition/gui/ResizeVolumeGroupDialog.cpp b/src/modules/partition/gui/ResizeVolumeGroupDialog.cpp deleted file mode 100644 index d0d7e7e308..0000000000 --- a/src/modules/partition/gui/ResizeVolumeGroupDialog.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "ResizeVolumeGroupDialog.h" - -#include "gui/ListPhysicalVolumeWidgetItem.h" - -#include -#include - -#include -#include -#include -#include - -ResizeVolumeGroupDialog::ResizeVolumeGroupDialog( LvmDevice* device, - const PartitionVector& availablePVs, - PartitionVector& selectedPVs, - QWidget* parent ) - : VolumeGroupBaseDialog( device->name(), device->physicalVolumes(), parent ) - , m_selectedPVs( selectedPVs ) -{ - setWindowTitle( tr( "Resize Volume Group", "@title" ) ); - - for ( int i = 0; i < pvList()->count(); i++ ) - { - pvList()->item( i )->setCheckState( Qt::Checked ); - } - - for ( const Partition* p : availablePVs ) - { - pvList()->addItem( new ListPhysicalVolumeWidgetItem( p, false ) ); - } - - peSize()->setValue( - static_cast< int >( device->peSize() / Capacity::unitFactor( Capacity::Unit::Byte, Capacity::Unit::MiB ) ) ); - - vgName()->setEnabled( false ); - peSize()->setEnabled( false ); - vgType()->setEnabled( false ); - - setUsedSizeValue( device->allocatedPE() * device->peSize() ); - setLVQuantity( device->partitionTable()->children().count() ); -} - -void -ResizeVolumeGroupDialog::accept() -{ - m_selectedPVs << checkedItems(); - - QDialog::accept(); -} diff --git a/src/modules/partition/gui/ResizeVolumeGroupDialog.h b/src/modules/partition/gui/ResizeVolumeGroupDialog.h deleted file mode 100644 index 7b8ecf6d6b..0000000000 --- a/src/modules/partition/gui/ResizeVolumeGroupDialog.h +++ /dev/null @@ -1,35 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef RESIZEVOLUMEGROUPDIALOG_H -#define RESIZEVOLUMEGROUPDIALOG_H - -#include "gui/VolumeGroupBaseDialog.h" - -class LvmDevice; - -class ResizeVolumeGroupDialog : public VolumeGroupBaseDialog -{ - Q_OBJECT -public: - using PartitionVector = QVector< const Partition* >; - - ResizeVolumeGroupDialog( LvmDevice* device, - const PartitionVector& availablePVs, - PartitionVector& selectedPVs, - QWidget* parent ); - - void accept() override; - -private: - PartitionVector& m_selectedPVs; -}; - -#endif // RESIZEVOLUMEGROUPDIALOG_H diff --git a/src/modules/partition/gui/ScanningDialog.cpp b/src/modules/partition/gui/ScanningDialog.cpp deleted file mode 100644 index 8418d8ec8d..0000000000 --- a/src/modules/partition/gui/ScanningDialog.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "ScanningDialog.h" - -#include "widgets/waitingspinnerwidget.h" - -#include -#include -#include -#include - - -ScanningDialog::ScanningDialog( const QString& text, const QString& windowTitle, QWidget* parent ) - : QDialog( parent ) -{ - setModal( true ); - setWindowTitle( windowTitle ); - - QHBoxLayout* dialogLayout = new QHBoxLayout; - setLayout( dialogLayout ); - - WaitingSpinnerWidget* spinner = new WaitingSpinnerWidget(); - dialogLayout->addWidget( spinner ); - spinner->start(); - - QLabel* rescanningLabel = new QLabel( text, this ); - dialogLayout->addWidget( rescanningLabel ); -} - - -void -ScanningDialog::run( const QFuture< void >& future, - const QString& text, - const QString& windowTitle, - const std::function< void() >& callback, - QWidget* parent ) -{ - ScanningDialog* theDialog = new ScanningDialog( text, windowTitle, parent ); - theDialog->show(); - - QFutureWatcher< void >* watcher = new QFutureWatcher< void >(); - connect( watcher, - &QFutureWatcher< void >::finished, - theDialog, - [ watcher, theDialog, callback ] - { - watcher->deleteLater(); - theDialog->hide(); - theDialog->deleteLater(); - callback(); - } ); - - watcher->setFuture( future ); -} - - -void -ScanningDialog::run( const QFuture< void >& future, const std::function< void() >& callback, QWidget* parent ) -{ - ScanningDialog::run( future, tr( "Scanning storage devices…", "@status" ), tr( "Partitioning…", "@status" ), callback, parent ); -} - -void -ScanningDialog::setVisible( bool visible ) -{ - QDialog::setVisible( visible ); - Q_EMIT visibilityChanged(); -} diff --git a/src/modules/partition/gui/ScanningDialog.h b/src/modules/partition/gui/ScanningDialog.h deleted file mode 100644 index 757b94eb63..0000000000 --- a/src/modules/partition/gui/ScanningDialog.h +++ /dev/null @@ -1,43 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2015 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef SCANNINGDIALOG_H -#define SCANNINGDIALOG_H - -#include -#include - -#include - -class ScanningDialog : public QDialog -{ - Q_OBJECT -public: - explicit ScanningDialog( const QString& text, const QString& windowTitle, QWidget* parent = nullptr ); - - static void run( - const QFuture< void >& future, - const QString& text, - const QString& windowTitle, - const std::function< void() >& callback = [] {}, - QWidget* parent = nullptr ); - - static void run( - const QFuture< void >& future, - const std::function< void() >& callback = [] {}, - QWidget* parent = nullptr ); - -public slots: - void setVisible( bool visible ) override; - -signals: - void visibilityChanged(); -}; - -#endif // SCANNINGDIALOG_H diff --git a/src/modules/partition/gui/VolumeGroupBaseDialog.cpp b/src/modules/partition/gui/VolumeGroupBaseDialog.cpp deleted file mode 100644 index 818a60483f..0000000000 --- a/src/modules/partition/gui/VolumeGroupBaseDialog.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "VolumeGroupBaseDialog.h" -#include "ui_VolumeGroupBaseDialog.h" - -#include "core/SizeUtils.h" -#include "gui/ListPhysicalVolumeWidgetItem.h" - -#include -#include -#include -#include -#include -#include - -VolumeGroupBaseDialog::VolumeGroupBaseDialog( QString& vgName, QVector< const Partition* > pvList, QWidget* parent ) - : QDialog( parent ) - , ui( new Ui::VolumeGroupBaseDialog ) - , m_vgNameValue( vgName ) - , m_totalSizeValue( 0 ) - , m_usedSizeValue( 0 ) -{ - ui->setupUi( this ); - - for ( const Partition* p : pvList ) - { - ui->pvList->addItem( new ListPhysicalVolumeWidgetItem( p, false ) ); - } - - ui->vgType->addItems( QStringList() << "LVM" - << "RAID" ); - ui->vgType->setCurrentIndex( 0 ); - - QRegularExpression re( R"(^(?!_|\.)[\w\-.+]+)" ); - ui->vgName->setValidator( new QRegularExpressionValidator( re, this ) ); - ui->vgName->setText( m_vgNameValue ); - - updateOkButton(); - updateTotalSize(); - - connect( ui->pvList, - &QListWidget::itemChanged, - this, - [ & ]( QListWidgetItem* ) - { - updateTotalSize(); - updateOkButton(); - } ); - - connect( ui->peSize, - qOverload< int >( &QSpinBox::valueChanged ), - this, - [ & ]( int ) - { - updateTotalSectors(); - updateOkButton(); - } ); - - connect( ui->vgName, &QLineEdit::textChanged, this, [ & ]( const QString& ) { updateOkButton(); } ); -} - -VolumeGroupBaseDialog::~VolumeGroupBaseDialog() -{ - delete ui; -} - -QVector< const Partition* > -VolumeGroupBaseDialog::checkedItems() const -{ - QVector< const Partition* > items; - - for ( int i = 0; i < ui->pvList->count(); i++ ) - { - ListPhysicalVolumeWidgetItem* item = dynamic_cast< ListPhysicalVolumeWidgetItem* >( ui->pvList->item( i ) ); - - if ( item && item->checkState() == Qt::Checked ) - { - items << item->partition(); - } - } - - return items; -} - -bool -VolumeGroupBaseDialog::isSizeValid() const -{ - return m_totalSizeValue >= m_usedSizeValue; -} - -void -VolumeGroupBaseDialog::updateOkButton() -{ - okButton()->setEnabled( isSizeValid() && !checkedItems().empty() && !ui->vgName->text().isEmpty() - && ui->peSize->value() > 0 ); -} - -void -VolumeGroupBaseDialog::setUsedSizeValue( qint64 usedSize ) -{ - m_usedSizeValue = usedSize; - - ui->usedSize->setText( formatByteSize( m_usedSizeValue ) ); -} - -void -VolumeGroupBaseDialog::setLVQuantity( qint32 lvQuantity ) -{ - ui->lvQuantity->setText( QString::number( lvQuantity ) ); -} - -void -VolumeGroupBaseDialog::updateTotalSize() -{ - m_totalSizeValue = 0; - - for ( const Partition* p : checkedItems() ) - { - m_totalSizeValue += p->capacity() - - p->capacity() - % ( ui->peSize->value() * Capacity::unitFactor( Capacity::Unit::Byte, Capacity::Unit::MiB ) ); - } - - ui->totalSize->setText( formatByteSize( m_totalSizeValue ) ); - - updateTotalSectors(); -} - -void -VolumeGroupBaseDialog::updateTotalSectors() -{ - qint64 totalSectors = 0; - - qint64 extentSize = ui->peSize->value() * Capacity::unitFactor( Capacity::Unit::Byte, Capacity::Unit::MiB ); - - if ( extentSize > 0 ) - { - totalSectors = m_totalSizeValue / extentSize; - } - - ui->totalSectors->setText( QString::number( totalSectors ) ); -} - -QString& -VolumeGroupBaseDialog::vgNameValue() const -{ - return m_vgNameValue; -} - -QLineEdit* -VolumeGroupBaseDialog::vgName() const -{ - return ui->vgName; -} - -QComboBox* -VolumeGroupBaseDialog::vgType() const -{ - return ui->vgType; -} - -QSpinBox* -VolumeGroupBaseDialog::peSize() const -{ - return ui->peSize; -} - -QListWidget* -VolumeGroupBaseDialog::pvList() const -{ - return ui->pvList; -} - -QPushButton* -VolumeGroupBaseDialog::okButton() const -{ - return ui->buttonBox->button( QDialogButtonBox::StandardButton::Ok ); -} diff --git a/src/modules/partition/gui/VolumeGroupBaseDialog.h b/src/modules/partition/gui/VolumeGroupBaseDialog.h deleted file mode 100644 index 56379e75fb..0000000000 --- a/src/modules/partition/gui/VolumeGroupBaseDialog.h +++ /dev/null @@ -1,71 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef VOLUMEGROUPBASEDIALOG_H -#define VOLUMEGROUPBASEDIALOG_H - -#include - -#include - -namespace Ui -{ -class VolumeGroupBaseDialog; -} // namespace Ui - -class QComboBox; -class QLineEdit; -class QListWidget; -class QSpinBox; - -class VolumeGroupBaseDialog : public QDialog -{ - Q_OBJECT - -public: - explicit VolumeGroupBaseDialog( QString& vgName, QVector< const Partition* > pvList, QWidget* parent = nullptr ); - ~VolumeGroupBaseDialog() override; - -protected: - virtual void updateOkButton(); - - void setUsedSizeValue( qint64 usedSize ); - - void setLVQuantity( qint32 lvQuantity ); - - void updateTotalSize(); - - void updateTotalSectors(); - - QVector< const Partition* > checkedItems() const; - - bool isSizeValid() const; - - QString& vgNameValue() const; - - QLineEdit* vgName() const; - - QComboBox* vgType() const; - - QSpinBox* peSize() const; - - QListWidget* pvList() const; - - QPushButton* okButton() const; - -private: - Ui::VolumeGroupBaseDialog* ui; - - QString& m_vgNameValue; - - qint64 m_totalSizeValue; - qint64 m_usedSizeValue; -}; - -#endif // VOLUMEGROUPBASEDIALOG_H diff --git a/src/modules/partition/gui/VolumeGroupBaseDialog.ui b/src/modules/partition/gui/VolumeGroupBaseDialog.ui deleted file mode 100644 index f1bb6b2510..0000000000 --- a/src/modules/partition/gui/VolumeGroupBaseDialog.ui +++ /dev/null @@ -1,210 +0,0 @@ - - - -SPDX-FileCopyrightText: 2018 Caio <caiojcarvalho@gmail.com> -SPDX-License-Identifier: GPL-3.0-or-later - - VolumeGroupBaseDialog - - - - 0 - 0 - 611 - 367 - - - - Create Volume Group - - - - - - List of Physical Volumes - - - - - - - - - - Volume Group Name: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - Volume Group Type: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - Physical Extent Size: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - MiB - - - 1 - - - 999 - - - 4 - - - - - - - Total Size: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - --- - - - Qt::AlignCenter - - - - - - - Used Size: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - --- - - - Qt::AlignCenter - - - - - - - Total Sectors: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - --- - - - Qt::AlignCenter - - - - - - - Quantity of LVs: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - --- - - - Qt::AlignCenter - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - VolumeGroupBaseDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - VolumeGroupBaseDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/src/modules/partition/jobs/AutoMountManagementJob.cpp b/src/modules/partition/jobs/AutoMountManagementJob.cpp deleted file mode 100644 index c62c41b89e..0000000000 --- a/src/modules/partition/jobs/AutoMountManagementJob.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2021 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "AutoMountManagementJob.h" - -#include "utils/Logger.h" - -AutoMountManagementJob::AutoMountManagementJob( bool disable ) - : m_disable( disable ) -{ -} - -QString -AutoMountManagementJob::prettyName() const -{ - return tr( "Managing auto-mount settings…", "@status" ); -} - -Calamares::JobResult -AutoMountManagementJob::exec() -{ - if ( m_stored ) - { - cDebug() << "Restore automount settings"; - Calamares::Partition::automountRestore( m_stored ); - m_stored.reset(); - } - else - { - cDebug() << "Set automount to" << ( m_disable ? "disable" : "enable" ); - m_stored = Calamares::Partition::automountDisable( m_disable ); - } - return Calamares::JobResult::ok(); -} diff --git a/src/modules/partition/jobs/AutoMountManagementJob.h b/src/modules/partition/jobs/AutoMountManagementJob.h deleted file mode 100644 index 9b7c18cf7d..0000000000 --- a/src/modules/partition/jobs/AutoMountManagementJob.h +++ /dev/null @@ -1,42 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2021 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef PARTITION_AUTOMOUNTMANAGEMENTJOB_H -#define PARTITION_AUTOMOUNTMANAGEMENTJOB_H - -#include "Job.h" - -#include "partition/AutoMount.h" - -/** - * This job sets automounting to a specific value, and when run a - * second time, **re**sets to the original value. See the documentation - * for Calamares::Partition::automountDisable() for details. - * Use @c true to **disable** automounting. - * - * Effectively: queue the **same** job twice; the first time it runs - * it will set the automount behavior, and the second time it - * restores the original. - * - */ -class AutoMountManagementJob : public Calamares::Job -{ - Q_OBJECT -public: - AutoMountManagementJob( bool disable = true ); - - QString prettyName() const override; - Calamares::JobResult exec() override; - -private: - bool m_disable; - decltype( Calamares::Partition::automountDisable( true ) ) m_stored; -}; - -#endif /* PARTITION_AUTOMOUNTMANAGEMENTJOB_H */ diff --git a/src/modules/partition/jobs/ChangeFilesystemLabelJob.cpp b/src/modules/partition/jobs/ChangeFilesystemLabelJob.cpp deleted file mode 100644 index 915cad4b79..0000000000 --- a/src/modules/partition/jobs/ChangeFilesystemLabelJob.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2016, Lisa Vitolo - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "ChangeFilesystemLabelJob.h" - -#include "core/KPMHelpers.h" - -#include "utils/Logger.h" - -#include -#include -#include -#include -#include -#include - -ChangeFilesystemLabelJob::ChangeFilesystemLabelJob( Device* device, Partition* partition, const QString& newLabel ) - : PartitionJob( partition ) - , m_device( device ) - , m_label( newLabel ) -{ -} - - -QString -ChangeFilesystemLabelJob::prettyName() const -{ - return tr( "Set filesystem label on %1", "@title" ).arg( partition()->partitionPath() ); -} - - -QString -ChangeFilesystemLabelJob::prettyDescription() const -{ - return tr( "Set filesystem label %1 to partition %2", "@info" ) - .arg( m_label ) - .arg( partition()->partitionPath() ); -} - - -QString -ChangeFilesystemLabelJob::prettyStatusMessage() const -{ - return tr( "Setting filesystem label %1 to partition %2…", "@status" ) - .arg( m_label ) - .arg( partition()->partitionPath() ); -} - - -Calamares::JobResult -ChangeFilesystemLabelJob::exec() -{ - if ( m_label == partition()->fileSystem().label() ) - { - return Calamares::JobResult::ok(); - } - - // Check for luks device - if ( partition()->fileSystem().type() == FileSystem::Luks ) - { - if ( KPMHelpers::cryptLabel( partition(), m_label ) ) - { - return Calamares::JobResult::ok(); - } - return Calamares::JobResult::error( - tr( "The installer failed to update partition table on disk '%1'.", "@info" ).arg( m_device->name() ) ); - } - - Report report( nullptr ); - SetFileSystemLabelOperation op( *partition(), m_label ); - op.setStatus( Operation::StatusRunning ); - - if ( op.execute( report ) ) - { - return Calamares::JobResult::ok(); - } - return Calamares::JobResult::error( - tr( "The installer failed to update partition table on disk '%1'.", "@info" ).arg( m_device->name() ), - report.toText() ); -} diff --git a/src/modules/partition/jobs/ChangeFilesystemLabelJob.h b/src/modules/partition/jobs/ChangeFilesystemLabelJob.h deleted file mode 100644 index ac39605380..0000000000 --- a/src/modules/partition/jobs/ChangeFilesystemLabelJob.h +++ /dev/null @@ -1,40 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2016, Lisa Vitolo - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef CHANGEFILESYSTEMLABELJOB_H -#define CHANGEFILESYSTEMLABELJOB_H - -#include "PartitionJob.h" - -#include - -class Device; -class Partition; - -/** - * This job changes the flags on an existing partition. - */ -class ChangeFilesystemLabelJob : public PartitionJob -{ - Q_OBJECT -public: - ChangeFilesystemLabelJob( Device* device, Partition* partition, const QString& newLabel ); - QString prettyName() const override; - QString prettyDescription() const override; - QString prettyStatusMessage() const override; - Calamares::JobResult exec() override; - - Device* device() const; - -private: - Device* m_device; - QString m_label; -}; - -#endif // CHANGEFILESYSTEMLABELJOB_H diff --git a/src/modules/partition/jobs/ClearMountsJob.cpp b/src/modules/partition/jobs/ClearMountsJob.cpp deleted file mode 100644 index ce1355b2b9..0000000000 --- a/src/modules/partition/jobs/ClearMountsJob.cpp +++ /dev/null @@ -1,396 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2018 Adriaan de Groot - * SPDX-FileCopyrightText: 2019 Kevin Kofler - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "ClearMountsJob.h" - -#include "core/PartitionInfo.h" - -#include "partition/PartitionIterator.h" -#include "partition/Sync.h" -#include "utils/Logger.h" -#include "utils/String.h" - -// KPMcore -#include -#include -#include - -#include -#include -#include -#include - -using Calamares::Partition::PartitionIterator; - - -/** @brief Returns list of partitions on a given @p deviceName - * - * The @p deviceName is a (whole-block) device, like "sda", and the partitions - * returned are then "sdaX". The whole-block device itself is ignored, if - * present. Partitions are returned with their full /dev/ path (e.g. /dev/sda1). - * - * The format for /etc/partitions is, e.g. - * major minor #blocks name - * 8 0 33554422 sda - * 8 1 33554400 sda1 - */ -STATICTEST QStringList -getPartitionsForDevice( const QString& deviceName ) -{ - QStringList partitions; - - QFile dev_partitions( "/proc/partitions" ); - if ( dev_partitions.open( QFile::ReadOnly ) ) - { - cDebug() << "Reading from" << dev_partitions.fileName() << "looking for" << deviceName; - QTextStream in( &dev_partitions ); - (void)in.readLine(); // That's the header line, skip it - while ( !in.atEnd() ) - { - // The fourth column (index from 0, so index 3) is the name of the device; - // keep it if it is followed by something. - QStringList columns = in.readLine().split( ' ', SplitSkipEmptyParts ); - if ( ( columns.count() >= 4 ) && ( columns[ 3 ].startsWith( deviceName ) ) - && ( columns[ 3 ] != deviceName ) ) - { - partitions.append( QStringLiteral( "/dev/" ) + columns[ 3 ] ); - } - } - } - else - { - cDebug() << "Could not open" << dev_partitions.fileName(); - } - - return partitions; -} - -STATICTEST QStringList -getSwapsForDevice( const QString& deviceName ) -{ - QProcess process; - - // Build a list of partitions of type 82 (Linux swap / Solaris). - // We then need to clear them just in case they contain something resumable from a - // previous suspend-to-disk. - QStringList swapPartitions; - process.start( "sfdisk", { "-d", deviceName } ); - process.waitForFinished(); - // Sample output: - // % sudo sfdisk -d /dev/sda - // label: dos - // label-id: 0x000ced89 - // device: /dev/sda - // unit: sectors - - // /dev/sda1 : start= 63, size= 29329345, type=83, bootable - // /dev/sda2 : start= 29331456, size= 2125824, type=82 - - swapPartitions = QString::fromLocal8Bit( process.readAllStandardOutput() ).split( '\n' ); - swapPartitions = swapPartitions.filter( "type=82" ); - for ( QStringList::iterator it = swapPartitions.begin(); it != swapPartitions.end(); ++it ) - { - *it = ( *it ).simplified().split( ' ' ).first(); - } - - return swapPartitions; -} - -static inline bool -isControl( const QString& baseName ) -{ - return baseName == "control"; -} - -static inline bool -isFedoraSpecial( const QString& baseName ) -{ - // Fedora live images use /dev/mapper/live-* internally. We must not - // unmount those devices, because they are used by the live image and - // because we need /dev/mapper/live-base in the unpackfs module. - return baseName.startsWith( "live-" ); -} - -/** @brief Returns a list of unneeded crypto devices - * - * These are the crypto devices to unmount and close; some are "needed" - * for system operation: on Fedora, the live- mappers are special. - * Some other devices are special, too, so those do not end up in - * the list. - */ -STATICTEST QStringList -getCryptoDevices( const QStringList& mapperExceptions ) -{ - QDir mapperDir( "/dev/mapper" ); - const QFileInfoList fiList = mapperDir.entryInfoList( QDir::Files ); - QStringList list; - for ( const QFileInfo& fi : fiList ) - { - QString baseName = fi.baseName(); - if ( isControl( baseName ) || isFedoraSpecial( baseName ) || mapperExceptions.contains( baseName ) ) - { - continue; - } - list.append( fi.absoluteFilePath() ); - } - return list; -} - -STATICTEST QStringList -getLVMVolumes() -{ - QProcess process; - - // First we umount all LVM logical volumes we can find - process.start( "lvscan", { "-a" } ); - process.waitForFinished(); - if ( process.exitCode() == 0 ) //means LVM2 tools are installed - { - QStringList lvscanLines = QString::fromLocal8Bit( process.readAllStandardOutput() ).split( '\n' ); - // Get the second column (`value(1)`) sinec that is the device name, - // remove quoting. - std::transform( lvscanLines.begin(), - lvscanLines.end(), - lvscanLines.begin(), - []( const QString& lvscanLine ) - { return lvscanLine.simplified().split( ' ' ).value( 1 ).replace( '\'', "" ); } ); - return lvscanLines; - } - else - { - cWarning() << "this system does not seem to have LVM2 tools."; - } - return QStringList(); -} -STATICTEST QStringList -getPVGroups( const QString& deviceName ) -{ - QProcess process; - // Then we go looking for volume groups that use this device for physical volumes - process.start( "pvdisplay", { "-C", "--noheadings" } ); - process.waitForFinished(); - if ( process.exitCode() == 0 ) //means LVM2 tools are installed - { - QString pvdisplayOutput = process.readAllStandardOutput(); - if ( !pvdisplayOutput.simplified().isEmpty() ) //means there is at least one LVM PV - { - QSet< QString > vgSet; - - const QStringList pvdisplayLines = pvdisplayOutput.split( '\n' ); - for ( const QString& pvdisplayLine : pvdisplayLines ) - { - QString pvPath = pvdisplayLine.simplified().split( ' ' ).value( 0 ); - QString vgName = pvdisplayLine.simplified().split( ' ' ).value( 1 ); - if ( !pvPath.contains( deviceName ) ) - { - continue; - } - - vgSet.insert( vgName ); - } - return QStringList { vgSet.cbegin(), vgSet.cend() }; - } - } - else - { - cWarning() << "this system does not seem to have LVM2 tools."; - } - return QStringList(); -} - -/* - * The tryX() free functions, below, return an empty QString on - * failure, or a non-empty QString on success. The string is - * meant **only** for debugging and is not displayed to the user, - * which is why no translation is applied. - * - * The MessageAndPath class stores a C-style pointer to a character - * array -- from QT_TRANSLATE_NOOP() -- and a path to substitute into it. - * - * When the tryX() functions return an "empty string", it is an - * empty MessageAndPath which acts like an empty string (in particular, - * isEmpty() is true). - */ - -class MessageAndPath -{ -public: - ///@brief An unsuccessful attempt at something - MessageAndPath() {} - ///@brief A success at doing @p thing to @p path - MessageAndPath( const char* thing, const QString& path ) - : m_message( thing ) - , m_path( path ) - { - } - - bool isEmpty() const { return !m_message; } - - explicit operator QString() const - { - return isEmpty() ? QString() : QCoreApplication::translate( "ClearMountsJob", m_message ).arg( m_path ); - } - -private: - const char* m_message = nullptr; - QString m_path; -}; - -STATICTEST inline QDebug& -operator<<( QDebug& s, const MessageAndPath& m ) -{ - if ( m.isEmpty() ) - { - return s; - } - return s << QString( m ); -} - - -///@brief Returns a debug-string if @p partPath could be unmounted -STATICTEST MessageAndPath -tryUmount( const QString& partPath ) -{ - QProcess process; - process.start( "umount", { partPath } ); - process.waitForFinished(); - if ( process.exitCode() == 0 ) - { - return { QT_TRANSLATE_NOOP( "ClearMountsJob", "Successfully unmounted %1." ), partPath }; - } - - process.start( "swapoff", { partPath } ); - process.waitForFinished(); - if ( process.exitCode() == 0 ) - { - return { QT_TRANSLATE_NOOP( "ClearMountsJob", "Successfully disabled swap %1." ), partPath }; - } - - return {}; -} - -///@brief Returns a debug-string if @p partPath was swap and could be cleared -STATICTEST MessageAndPath -tryClearSwap( const QString& partPath ) -{ - QProcess process; - process.start( "blkid", { "-s", "UUID", "-o", "value", partPath } ); - process.waitForFinished(); - QString swapPartUuid = QString::fromLocal8Bit( process.readAllStandardOutput() ).simplified(); - if ( process.exitCode() != 0 || swapPartUuid.isEmpty() ) - { - return {}; - } - - process.start( "mkswap", { "-U", swapPartUuid, partPath } ); - process.waitForFinished(); - if ( process.exitCode() != 0 ) - { - return {}; - } - - return { QT_TRANSLATE_NOOP( "ClearMountsJob", "Successfully cleared swap %1." ), partPath }; -} - -///@brief Returns a debug-string if @p mapperPath could be closed -STATICTEST MessageAndPath -tryCryptoClose( const QString& mapperPath ) -{ - /* ignored */ tryUmount( mapperPath ); - - QProcess process; - process.start( "cryptsetup", { "close", mapperPath } ); - process.waitForFinished(); - if ( process.exitCode() == 0 ) - { - return { QT_TRANSLATE_NOOP( "ClearMountsJob", "Successfully closed mapper device %1." ), mapperPath }; - } - - return {}; -} - -STATICTEST MessageAndPath -tryVGDisable( const QString& vgName ) -{ - QProcess vgProcess; - vgProcess.start( "vgchange", { "-an", vgName } ); - vgProcess.waitForFinished(); - return ( vgProcess.exitCode() == 0 ) - ? MessageAndPath { QT_TRANSLATE_NOOP( "ClearMountsJob", "Successfully disabled volume group %1." ), vgName } - : MessageAndPath {}; -} - -///@brief Apply @p f to all the @p paths, appending successes to @p news -template < typename F > -void -apply( const QStringList& paths, F f, QList< MessageAndPath >& news ) -{ - for ( const QString& p : qAsConst( paths ) ) - { - auto n = f( p ); - if ( !n.isEmpty() ) - { - news.append( n ); - } - } -} - -STATICTEST QStringList -stringify( const QList< MessageAndPath >& news ) -{ - QStringList l; - for ( const auto& m : qAsConst( news ) ) - { - l << QString( m ); - } - return l; -} - -ClearMountsJob::ClearMountsJob( Device* device ) - : Calamares::Job() - , m_deviceNode( device->deviceNode() ) -{ -} - -QString -ClearMountsJob::prettyName() const -{ - return tr( "Clear mounts for partitioning operations on %1", "@title" ).arg( m_deviceNode ); -} - -QString -ClearMountsJob::prettyStatusMessage() const -{ - return tr( "Clearing mounts for partitioning operations on %1…", "@status" ).arg( m_deviceNode ); -} - -Calamares::JobResult -ClearMountsJob::exec() -{ - const QString deviceName = m_deviceNode.split( '/' ).last(); - Calamares::Partition::Syncer s; - QList< MessageAndPath > goodNews; - - apply( getCryptoDevices( m_mapperExceptions ), tryCryptoClose, goodNews ); - apply( getLVMVolumes(), tryUmount, goodNews ); - apply( getPVGroups( deviceName ), tryVGDisable, goodNews ); - - apply( getCryptoDevices( m_mapperExceptions ), tryCryptoClose, goodNews ); - apply( getPartitionsForDevice( deviceName ), tryUmount, goodNews ); - apply( getSwapsForDevice( m_deviceNode ), tryClearSwap, goodNews ); - - Calamares::JobResult ok = Calamares::JobResult::ok(); - ok.setMessage( tr( "Cleared all mounts for %1" ).arg( m_deviceNode ) ); - ok.setDetails( stringify( goodNews ).join( "\n" ) ); - cDebug() << "ClearMountsJob finished. Here's what was done:" << Logger::DebugListT< MessageAndPath >( goodNews ); - - return ok; -} diff --git a/src/modules/partition/jobs/ClearMountsJob.h b/src/modules/partition/jobs/ClearMountsJob.h deleted file mode 100644 index fb3aca1e44..0000000000 --- a/src/modules/partition/jobs/ClearMountsJob.h +++ /dev/null @@ -1,59 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef CLEARMOUNTSJOB_H -#define CLEARMOUNTSJOB_H - -#include "Job.h" - -class Device; - -/** - * This job tries to free all mounts for the given device, so partitioning - * operations can proceed. - * - * - partitions on the device are unmounted - * - swap on the device is disabled and cleared - * - physical volumes for LVM on the device are disabled - * - * In addition, regardless of device: - * - almost all(*) /dev/mapper entries (crypto / LUKS, also LVM) are closed - * - all logical volumes for LVM are unmounted - * Exceptions to "all /dev/mapper" may be configured through - * the setMapperExceptions() method. Pass in names of mapper - * files that should not be closed (e.g. "myvg-mylv"). - * - * (*) Some exceptions always exist: /dev/mapper/control is never - * closed. /dev/mapper/live-* is never closed. - * - */ -class ClearMountsJob : public Calamares::Job -{ - Q_OBJECT -public: - /** @brief Creates a job freeing mounts on @p device - * - * No ownership is transferred; the @p device is used only to access - * the device node (name). - */ - explicit ClearMountsJob( Device* device ); - - QString prettyName() const override; - QString prettyStatusMessage() const override; - Calamares::JobResult exec() override; - - ///@brief Sets the list of exceptions (names) when closing /dev/mapper - void setMapperExceptions( const QStringList& names ) { m_mapperExceptions = names; } - -private: - const QString m_deviceNode; - QStringList m_mapperExceptions; -}; - -#endif // CLEARMOUNTSJOB_H diff --git a/src/modules/partition/jobs/ClearTempMountsJob.cpp b/src/modules/partition/jobs/ClearTempMountsJob.cpp deleted file mode 100644 index cb0fb572e4..0000000000 --- a/src/modules/partition/jobs/ClearTempMountsJob.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "ClearTempMountsJob.h" - -#include "partition/Mount.h" -#include "utils/Logger.h" -#include "utils/String.h" - -#include - -#include -#include -#include - -#include - -ClearTempMountsJob::ClearTempMountsJob() - : Calamares::Job() -{ -} - - -QString -ClearTempMountsJob::prettyName() const -{ - return tr( "Clearing all temporary mounts…", "@status" ); -} - - -QString -ClearTempMountsJob::prettyStatusMessage() const -{ - return tr( "Clearing all temporary mounts…", "@status" ); -} - - -Calamares::JobResult -ClearTempMountsJob::exec() -{ - Logger::Once o; - // Fetch a list of current mounts to Calamares temporary directories. - using MtabInfo = Calamares::Partition::MtabInfo; - auto targetMounts = MtabInfo::fromMtabFilteredByPrefix( QStringLiteral( "/tmp/calamares-" ) ); - - if ( targetMounts.isEmpty() ) - { - return Calamares::JobResult::ok(); - } - std::sort( targetMounts.begin(), targetMounts.end(), MtabInfo::mountPointOrder ); - - QStringList goodNews; - for ( const auto& m : qAsConst( targetMounts ) ) - { - cDebug() << o << "Will try to umount path" << m.mountPoint; - if ( Calamares::Partition::unmount( m.mountPoint, { "-lv" } ) == 0 ) - { - // Returns the program's exit code, so 0 is success - goodNews.append( QString( "Successfully unmounted %1." ).arg( m.mountPoint ) ); - } - } - - Calamares::JobResult ok = Calamares::JobResult::ok(); - ok.setMessage( tr( "Cleared all temporary mounts." ) ); - ok.setDetails( goodNews.join( "\n" ) ); - - cDebug() << o << "ClearTempMountsJob finished. Here's what was done:\n" << Logger::DebugList( goodNews ); - - return ok; -} diff --git a/src/modules/partition/jobs/ClearTempMountsJob.h b/src/modules/partition/jobs/ClearTempMountsJob.h deleted file mode 100644 index 0726975c77..0000000000 --- a/src/modules/partition/jobs/ClearTempMountsJob.h +++ /dev/null @@ -1,31 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef CLEARTEMPMOUNTSJOB_H -#define CLEARTEMPMOUNTSJOB_H - -#include "Job.h" - -class Device; - -/** - * This job tries to free all temporary mounts used by Calamares, so partitioning - * operations can proceed. - */ -class ClearTempMountsJob : public Calamares::Job -{ - Q_OBJECT -public: - explicit ClearTempMountsJob(); - QString prettyName() const override; - QString prettyStatusMessage() const override; - Calamares::JobResult exec() override; -}; - -#endif // CLEARTEMPMOUNTSJOB_H diff --git a/src/modules/partition/jobs/CreatePartitionJob.cpp b/src/modules/partition/jobs/CreatePartitionJob.cpp deleted file mode 100644 index 429bf26ffb..0000000000 --- a/src/modules/partition/jobs/CreatePartitionJob.cpp +++ /dev/null @@ -1,283 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017 2020, Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "CreatePartitionJob.h" - -#include "core/KPMHelpers.h" -#include "core/PartitionInfo.h" - -#include "partition/FileSystem.h" -#include "partition/PartitionQuery.h" -#include "utils/Logger.h" -#include "utils/System.h" -#include "utils/Units.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -using Calamares::Partition::untranslatedFS; -using Calamares::Partition::userVisibleFS; - -/** @brief Create - * - * Uses sfdisk to remove @p partition. This should only be used in cases - * where using kpmcore to remove the partition would not be appropriate - * - */ -static Calamares::JobResult -createZfs( Partition* partition, Device* device ) -{ - auto r = Calamares::System::instance()->runCommand( - { "sh", - "-c", - "echo start=" + QString::number( partition->firstSector() ) + " size=" - + QString::number( partition->length() ) + " | sfdisk --append --force " + partition->devicePath() }, - std::chrono::seconds( 5 ) ); - if ( r.getExitCode() != 0 ) - { - return Calamares::JobResult::error( - QCoreApplication::translate( CreatePartitionJob::staticMetaObject.className(), - "Failed to create partition" ), - QCoreApplication::translate( CreatePartitionJob::staticMetaObject.className(), - "Failed to create zfs partition with output: " - + r.getOutput().toLocal8Bit() ) ); - } - - // Now we need to do some things that would normally be done by kpmcore - - // First we get the device node from the output and set it as the partition path - QString deviceNode; - { - QRegularExpression re( QStringLiteral( "Created a new partition (\\d+)" ) ); - QRegularExpressionMatch rem = re.match( r.getOutput() ); - - if ( rem.hasMatch() ) - { - if ( partition->devicePath().back().isDigit() ) - { - deviceNode = partition->devicePath() + QLatin1Char( 'p' ) + rem.captured( 1 ); - } - else - { - deviceNode = partition->devicePath() + rem.captured( 1 ); - } - } - partition->setPartitionPath( deviceNode ); - } - // If it is a gpt device, set the partition UUID - if ( device->partitionTable()->type() == PartitionTable::gpt && partition->uuid().isEmpty() ) - { - r = Calamares::System::instance()->runCommand( - { "sfdisk", "--list", "--output", "Device,UUID", partition->devicePath() }, std::chrono::seconds( 5 ) ); - if ( r.getExitCode() == 0 ) - { - QRegularExpression re( deviceNode + QStringLiteral( " +(.+)" ) ); - QRegularExpressionMatch rem = re.match( r.getOutput() ); - - if ( rem.hasMatch() ) - { - partition->setUUID( rem.captured( 1 ) ); - } - } - } - - return Calamares::JobResult::ok(); -} - -CreatePartitionJob::CreatePartitionJob( Device* device, Partition* partition ) - : PartitionJob( partition ) - , m_device( device ) -{ -} - -static QString -prettyGptType( const Partition* partition ) -{ - static const QMap< QString, QString > gptTypePrettyStrings = { - { "44479540-f297-41b2-9af7-d131d5f0458a", "Linux Root Partition (x86)" }, - { "4f68bce3-e8cd-4db1-96e7-fbcaf984b709", "Linux Root Partition (x86-64)" }, - { "69dad710-2ce4-4e3c-b16c-21a1d49abed3", "Linux Root Partition (32-bit ARM)" }, - { "b921b045-1df0-41c3-af44-4c6f280d3fae", "Linux Root Partition (64-bit ARM)" }, - { "993d8d3d-f80e-4225-855a-9daf8ed7ea97", "Linux Root Partition (Itanium/IA-64)" }, - { "d13c5d3b-b5d1-422a-b29f-9454fdc89d76", "Linux Root Verity Partition (x86)" }, - { "2c7357ed-ebd2-46d9-aec1-23d437ec2bf5", "Linux Root Verity Partition (x86-64)" }, - { "7386cdf2-203c-47a9-a498-f2ecce45a2d6", "Linux Root Verity Partition (32-bit ARM)" }, - { "df3300ce-d69f-4c92-978c-9bfb0f38d820", "Linux Root Verity Partition (64-bit ARM/AArch64)" }, - { "86ed10d5-b607-45bb-8957-d350f23d0571", "Linux Root Verity Partition (Itanium/IA-64)" }, - { "75250d76-8cc6-458e-bd66-bd47cc81a812", "Linux /usr Partition (x86)" }, - { "8484680c-9521-48c6-9c11-b0720656f69e", "Linux /usr Partition (x86-64)" }, - { "7d0359a3-02b3-4f0a-865c-654403e70625", "Linux /usr Partition (32-bit ARM)" }, - { "b0e01050-ee5f-4390-949a-9101b17104e9", "Linux /usr Partition (64-bit ARM/AArch64)" }, - { "4301d2a6-4e3b-4b2a-bb94-9e0b2c4225ea", "Linux /usr Partition (Itanium/IA-64)" }, - { "8f461b0d-14ee-4e81-9aa9-049b6fb97abd", "Linux /usr Verity Partition (x86)" }, - { "77ff5f63-e7b6-4633-acf4-1565b864c0e6", "Linux /usr Verity Partition (x86-64)" }, - { "c215d751-7bcd-4649-be90-6627490a4c05", "Linux /usr Verity Partition (32-bit ARM)" }, - { "6e11a4e7-fbca-4ded-b9e9-e1a512bb664e", "Linux /usr Verity Partition (64-bit ARM/AArch64)" }, - { "6a491e03-3be7-4545-8e38-83320e0ea880", "Linux /usr Verity Partition (Itanium/IA-64)" }, - { "933ac7e1-2eb4-4f13-b844-0e14e2aef915", "Linux Home Partition" }, - { "3b8f8425-20e0-4f3b-907f-1a25a76f98e8", "Linux Server Data Partition" }, - { "4d21b016-b534-45c2-a9fb-5c16e091fd2d", "Linux Variable Data Partition" }, - { "7ec6f557-3bc5-4aca-b293-16ef5df639d1", "Linux Temporary Data Partition" }, - { "0657fd6d-a4ab-43c4-84e5-0933c84b4f4f", "Linux Swap" }, - { "c12a7328-f81f-11d2-ba4b-00a0c93ec93b", "EFI System Partition" }, - { "bc13c2ff-59e6-4262-a352-b275fd6f7172", "Extended Boot Loader Partition" }, - { "0fc63daf-8483-4772-8e79-3d69d8477de4", "Other Data Partitions" }, - { "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7", "Microsoft basic data" }, - }; - - auto type = partition->type(); - return gptTypePrettyStrings.value( type.toLower(), type ); -} - -static QString -prettyGptEntries( const Partition* partition ) -{ - if ( !partition ) - { - return QString(); - } - - QStringList list; - - if ( !partition->label().isEmpty() ) - { - list += partition->label(); - } - - QString type = prettyGptType( partition ); - if ( !type.isEmpty() ) - { - list += type; - } - - return list.join( QStringLiteral( ", " ) ); -} - -QString -CreatePartitionJob::prettyName() const -{ - const PartitionTable* table = Calamares::Partition::getPartitionTable( m_partition ); - if ( table && table->type() == PartitionTable::TableType::gpt ) - { - QString entries = prettyGptEntries( m_partition ); - if ( !entries.isEmpty() ) - { - return tr( "Create new %1MiB partition on %3 (%2) with entries %4", "@title" ) - .arg( Calamares::BytesToMiB( m_partition->capacity() ) ) - .arg( m_device->name() ) - .arg( m_device->deviceNode() ) - .arg( entries ); - } - else - { - return tr( "Create new %1MiB partition on %3 (%2)", "@title" ) - .arg( Calamares::BytesToMiB( m_partition->capacity() ) ) - .arg( m_device->name() ) - .arg( m_device->deviceNode() ); - } - } - - return tr( "Create new %2MiB partition on %4 (%3) with file system %1", "@title" ) - .arg( userVisibleFS( m_partition->fileSystem() ) ) - .arg( Calamares::BytesToMiB( m_partition->capacity() ) ) - .arg( m_device->name() ) - .arg( m_device->deviceNode() ); -} - -QString -CreatePartitionJob::prettyDescription() const -{ - const PartitionTable* table = Calamares::Partition::getPartitionTable( m_partition ); - if ( table && table->type() == PartitionTable::TableType::gpt ) - { - QString entries = prettyGptEntries( m_partition ); - if ( !entries.isEmpty() ) - { - return tr( "Create new %1MiB partition on %3 (%2) with entries " - "%4", - "@info" ) - .arg( Calamares::BytesToMiB( m_partition->capacity() ) ) - .arg( m_device->name() ) - .arg( m_device->deviceNode() ) - .arg( entries ); - } - else - { - return tr( "Create new %1MiB partition on %3 (%2)", "@info" ) - .arg( Calamares::BytesToMiB( m_partition->capacity() ) ) - .arg( m_device->name() ) - .arg( m_device->deviceNode() ); - } - } - - return tr( "Create new %2MiB partition on %4 " - "(%3) with file system %1", - "@info" ) - .arg( userVisibleFS( m_partition->fileSystem() ) ) - .arg( Calamares::BytesToMiB( m_partition->capacity() ) ) - .arg( m_device->name() ) - .arg( m_device->deviceNode() ); -} - -QString -CreatePartitionJob::prettyStatusMessage() const -{ - const PartitionTable* table = Calamares::Partition::getPartitionTable( m_partition ); - if ( table && table->type() == PartitionTable::TableType::gpt ) - { - QString type = prettyGptType( m_partition ); - if ( type.isEmpty() ) - { - type = m_partition->label(); - } - if ( type.isEmpty() ) - { - type = userVisibleFS( m_partition->fileSystem() ); - } - - return tr( "Creating new %1 partition on %2…", "@status" ).arg( type ).arg( m_device->deviceNode() ); - } - - return tr( "Creating new %1 partition on %2…", "@status" ) - .arg( userVisibleFS( m_partition->fileSystem() ) ) - .arg( m_device->deviceNode() ); -} - -Calamares::JobResult -CreatePartitionJob::exec() -{ - // kpmcore doesn't currently handle this case properly so for now, we manually create the partion - // The zfs module can later deal with creating a zpool in the partition - if ( m_partition->fileSystem().type() == FileSystem::Type::Zfs ) - { - return createZfs( m_partition, m_device ); - } - - return KPMHelpers::execute( - NewOperation( *m_device, m_partition ), - tr( "The installer failed to create partition on disk '%1'.", "@info" ).arg( m_device->name() ) ); -} - -void -CreatePartitionJob::updatePreview() -{ - m_device->partitionTable()->removeUnallocated(); - m_partition->parent()->insert( m_partition ); - m_device->partitionTable()->updateUnallocated( *m_device ); -} diff --git a/src/modules/partition/jobs/CreatePartitionJob.h b/src/modules/partition/jobs/CreatePartitionJob.h deleted file mode 100644 index 3d6199804a..0000000000 --- a/src/modules/partition/jobs/CreatePartitionJob.h +++ /dev/null @@ -1,44 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2015 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef CREATEPARTITIONJOB_H -#define CREATEPARTITIONJOB_H - -#include "PartitionJob.h" - -class Device; -class Partition; -class FileSystem; - -/** - * Creates a partition on a device. - * - * This job does two things: - * 1. Create the partition - * 2. Create the filesystem on the partition - */ -class CreatePartitionJob : public PartitionJob -{ - Q_OBJECT -public: - CreatePartitionJob( Device* device, Partition* partition ); - QString prettyName() const override; - QString prettyDescription() const override; - QString prettyStatusMessage() const override; - Calamares::JobResult exec() override; - - void updatePreview(); - Device* device() const { return m_device; } - -private: - Device* m_device; -}; - -#endif /* CREATEPARTITIONJOB_H */ diff --git a/src/modules/partition/jobs/CreatePartitionTableJob.cpp b/src/modules/partition/jobs/CreatePartitionTableJob.cpp deleted file mode 100644 index f75e647a93..0000000000 --- a/src/modules/partition/jobs/CreatePartitionTableJob.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "CreatePartitionTableJob.h" - -#include "partition/PartitionIterator.h" -#include "utils/Logger.h" -#include "utils/System.h" - -#include "core/KPMHelpers.h" - -#include -#include -#include -#include -#include -#include - -// Qt -#include - -using Calamares::Partition::PartitionIterator; - -CreatePartitionTableJob::CreatePartitionTableJob( Device* device, PartitionTable::TableType type ) - : m_device( device ) - , m_type( type ) -{ -} - -QString -CreatePartitionTableJob::prettyName() const -{ - return tr( "Creating new %1 partition table on %2…", "@status" ) - .arg( PartitionTable::tableTypeToName( m_type ) ) - .arg( m_device->deviceNode() ); -} - -QString -CreatePartitionTableJob::prettyDescription() const -{ - return tr( "Creating new %1 partition table on %2 (%3)…", "@status" ) - .arg( PartitionTable::tableTypeToName( m_type ).toUpper() ) - .arg( m_device->deviceNode() ) - .arg( m_device->name() ); -} - -QString -CreatePartitionTableJob::prettyStatusMessage() const -{ - return tr( "Creating new %1 partition table on %2…", "@status" ) - .arg( PartitionTable::tableTypeToName( m_type ).toUpper() ) - .arg( m_device->deviceNode() ); -} - -Calamares::JobResult -CreatePartitionTableJob::exec() -{ - - PartitionTable* table = m_device->partitionTable(); - - if ( Logger::logLevelEnabled( Logger::LOGDEBUG ) ) - { - cDebug() << "Creating new partition table of type" << table->typeName() << ", uncommitted partitions:"; - for ( auto it = PartitionIterator::begin( table ); it != PartitionIterator::end( table ); ++it ) - { - cDebug() << Logger::SubEntry << ( ( *it ) ? ( *it )->deviceNode() : QString( "" ) ); - } - - auto lsblkResult = Calamares::System::runCommand( { "lsblk" }, std::chrono::seconds( 30 ) ); - cDebug() << Logger::SubEntry << "lsblk output:\n" << Logger::NoQuote << lsblkResult.getOutput(); - - auto mountResult = Calamares::System::runCommand( { "mount" }, std::chrono::seconds( 30 ) ); - cDebug() << Logger::SubEntry << "mount output:\n" << Logger::NoQuote << mountResult.getOutput(); - } - - return KPMHelpers::execute( - CreatePartitionTableOperation( *m_device, table ), - tr( "The installer failed to create a partition table on %1." ).arg( m_device->name() ) ); -} - -void -CreatePartitionTableJob::updatePreview() -{ - // Device takes ownership of its table, but does not destroy the current - // one when setPartitionTable() is called, so do it ourself - delete m_device->partitionTable(); - m_device->setPartitionTable( createTable() ); - m_device->partitionTable()->updateUnallocated( *m_device ); -} - -PartitionTable* -CreatePartitionTableJob::createTable() -{ - cDebug() << "CreatePartitionTableJob::createTable trying to make table for device" << m_device->deviceNode(); - return new PartitionTable( m_type, - PartitionTable::defaultFirstUsable( *m_device, m_type ), - PartitionTable::defaultLastUsable( *m_device, m_type ) ); -} diff --git a/src/modules/partition/jobs/CreatePartitionTableJob.h b/src/modules/partition/jobs/CreatePartitionTableJob.h deleted file mode 100644 index 4acb1e5a83..0000000000 --- a/src/modules/partition/jobs/CreatePartitionTableJob.h +++ /dev/null @@ -1,48 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2015 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef CREATEPARTITIONTABLEJOB_H -#define CREATEPARTITIONTABLEJOB_H - -#include "Job.h" -#include "partition/KPMManager.h" - -// KPMcore -#include - -class Device; - -/** - * Creates a partition table on a device. It supports MBR and GPT partition - * tables. - * - * This wipes all the data from the device. - */ -class CreatePartitionTableJob : public Calamares::Job -{ - Q_OBJECT -public: - CreatePartitionTableJob( Device* device, PartitionTable::TableType type ); - QString prettyName() const override; - QString prettyDescription() const override; - QString prettyStatusMessage() const override; - Calamares::JobResult exec() override; - - void updatePreview(); - Device* device() const { return m_device; } - -private: - Calamares::Partition::KPMManager m_kpmcore; - Device* m_device; - PartitionTable::TableType m_type; - PartitionTable* createTable(); -}; - -#endif /* CREATEPARTITIONTABLEJOB_H */ diff --git a/src/modules/partition/jobs/CreateVolumeGroupJob.cpp b/src/modules/partition/jobs/CreateVolumeGroupJob.cpp deleted file mode 100644 index 638d05e6b7..0000000000 --- a/src/modules/partition/jobs/CreateVolumeGroupJob.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "CreateVolumeGroupJob.h" - -#include "core/KPMHelpers.h" - -#include -#include -#include -#include - -CreateVolumeGroupJob::CreateVolumeGroupJob( Device*, - QString& vgName, - QVector< const Partition* > pvList, - const qint32 peSize ) - : m_vgName( vgName ) - , m_pvList( pvList ) - , m_peSize( peSize ) -{ -} - -QString -CreateVolumeGroupJob::prettyName() const -{ - return tr( "Creating new volume group named %1…", "@status" ).arg( m_vgName ); -} - -QString -CreateVolumeGroupJob::prettyDescription() const -{ - return tr( "Creating new volume group named %1…", "@status" ).arg( m_vgName ); -} - -QString -CreateVolumeGroupJob::prettyStatusMessage() const -{ - return tr( "Creating new volume group named %1…", "@status" ).arg( m_vgName ); -} - -Calamares::JobResult -CreateVolumeGroupJob::exec() -{ - return KPMHelpers::execute( CreateVolumeGroupOperation( m_vgName, m_pvList, m_peSize ), - tr( "The installer failed to create a volume group named '%1'." ).arg( m_vgName ) ); -} - -void -CreateVolumeGroupJob::updatePreview() -{ - LvmDevice::s_DirtyPVs << m_pvList; -} - -void -CreateVolumeGroupJob::undoPreview() -{ - for ( const auto& pv : m_pvList ) - { - if ( LvmDevice::s_DirtyPVs.contains( pv ) ) - { - LvmDevice::s_DirtyPVs.removeAll( pv ); - } - } -} diff --git a/src/modules/partition/jobs/CreateVolumeGroupJob.h b/src/modules/partition/jobs/CreateVolumeGroupJob.h deleted file mode 100644 index c4b4c36ed0..0000000000 --- a/src/modules/partition/jobs/CreateVolumeGroupJob.h +++ /dev/null @@ -1,42 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef CREATEVOLUMEGROUPJOB_H -#define CREATEVOLUMEGROUPJOB_H - -#include "Job.h" -#include "partition/KPMManager.h" - -#include - -class Device; -class Partition; - -class CreateVolumeGroupJob : public Calamares::Job -{ - Q_OBJECT -public: - CreateVolumeGroupJob( Device*, QString& vgName, QVector< const Partition* > pvList, const qint32 peSize ); - - QString prettyName() const override; - QString prettyDescription() const override; - QString prettyStatusMessage() const override; - Calamares::JobResult exec() override; - - void updatePreview(); - void undoPreview(); - -private: - Calamares::Partition::KPMManager m_kpmcore; - QString m_vgName; - QVector< const Partition* > m_pvList; - qint32 m_peSize; -}; - -#endif // CREATEVOLUMEGROUPJOB_H diff --git a/src/modules/partition/jobs/DeactivateVolumeGroupJob.cpp b/src/modules/partition/jobs/DeactivateVolumeGroupJob.cpp deleted file mode 100644 index 6a4203bc3d..0000000000 --- a/src/modules/partition/jobs/DeactivateVolumeGroupJob.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "DeactivateVolumeGroupJob.h" - -#include "core/KPMHelpers.h" - -#include -#include -#include - -DeactivateVolumeGroupJob::DeactivateVolumeGroupJob( LvmDevice* device ) - : m_device( device ) -{ -} - -QString -DeactivateVolumeGroupJob::prettyName() const -{ - return tr( "Deactivating volume group named %1…", "@status" ).arg( m_device->name() ); -} - -QString -DeactivateVolumeGroupJob::prettyDescription() const -{ - return tr( "Deactivating volume group named %1…", "@status" ).arg( m_device->name() ); -} - -QString -DeactivateVolumeGroupJob::prettyStatusMessage() const -{ - return tr( "Deactivating volume group named %1…", "@status" ).arg( m_device->name() ); -} - -Calamares::JobResult -DeactivateVolumeGroupJob::exec() -{ - DeactivateVolumeGroupOperation op( *m_device ); - auto r = KPMHelpers::execute( - op, tr( "The installer failed to deactivate a volume group named %1." ).arg( m_device->name() ) ); - if ( r ) - { - op.preview(); - } - return r; -} diff --git a/src/modules/partition/jobs/DeactivateVolumeGroupJob.h b/src/modules/partition/jobs/DeactivateVolumeGroupJob.h deleted file mode 100644 index 175c4c6a53..0000000000 --- a/src/modules/partition/jobs/DeactivateVolumeGroupJob.h +++ /dev/null @@ -1,34 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef DEACTIVATEVOLUMEGROUPJOB_H -#define DEACTIVATEVOLUMEGROUPJOB_H - -#include "Job.h" -#include "partition/KPMManager.h" - -class LvmDevice; - -class DeactivateVolumeGroupJob : public Calamares::Job -{ - Q_OBJECT -public: - DeactivateVolumeGroupJob( LvmDevice* device ); - - QString prettyName() const override; - QString prettyDescription() const override; - QString prettyStatusMessage() const override; - Calamares::JobResult exec() override; - -private: - Calamares::Partition::KPMManager m_kpmcore; - LvmDevice* m_device; -}; - -#endif // DEACTIVATEVOLUMEGROUPJOB_H diff --git a/src/modules/partition/jobs/DeletePartitionJob.cpp b/src/modules/partition/jobs/DeletePartitionJob.cpp deleted file mode 100644 index f806dab629..0000000000 --- a/src/modules/partition/jobs/DeletePartitionJob.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "DeletePartitionJob.h" - -#include "core/KPMHelpers.h" - -#include "utils/System.h" - -#include -#include -#include -#include -#include -#include - -#include - -/** @brief Determine if the given partition is of type Zfs - * - * Returns true if @p partition is of type Zfs - * - */ -static bool -isZfs( Partition* partition ) -{ - return partition->fileSystem().type() == FileSystem::Type::Zfs; -} - -/** @brief Remove the given partition manually - * - * Uses sfdisk to remove @p partition. This should only be used in cases - * where using kpmcore to remove the partition would not be appropriate - * - */ -static Calamares::JobResult -removePartition( Partition* partition ) -{ - auto r = Calamares::System::instance()->runCommand( - { "sfdisk", "--delete", "--force", partition->devicePath(), QString::number( partition->number() ) }, - std::chrono::seconds( 5 ) ); - if ( r.getExitCode() != 0 || r.getOutput().contains( "failed" ) ) - { - return Calamares::JobResult::error( - QCoreApplication::translate( DeletePartitionJob::staticMetaObject.className(), "Deletion Failed" ), - QCoreApplication::translate( DeletePartitionJob::staticMetaObject.className(), - "Failed to delete the partition with output: " ) - + r.getOutput() ); - } - else - { - return Calamares::JobResult::ok(); - } -} - -DeletePartitionJob::DeletePartitionJob( Device* device, Partition* partition ) - : PartitionJob( partition ) - , m_device( device ) -{ -} - -QString -DeletePartitionJob::prettyName() const -{ - return tr( "Deleting partition %1…", "@status" ).arg( m_partition->partitionPath() ); -} - -QString -DeletePartitionJob::prettyDescription() const -{ - return tr( "Deleting partition %1…", "@status" ).arg( m_partition->partitionPath() ); -} - -QString -DeletePartitionJob::prettyStatusMessage() const -{ - return tr( "Deleting partition %1…", "@status" ).arg( m_partition->partitionPath() ); -} - -Calamares::JobResult -DeletePartitionJob::exec() -{ - // The current implementation of remove() for zfs in kpmcore trys to destroy the zpool by label - // This isn't what we want here so we delete the partition instead. - if ( isZfs( m_partition ) ) - { - return removePartition( m_partition ); - } - - return KPMHelpers::execute( DeleteOperation( *m_device, m_partition ), - tr( "The installer failed to delete partition %1." ).arg( m_partition->devicePath() ) ); -} - -void -DeletePartitionJob::updatePreview() -{ - m_partition->parent()->remove( m_partition ); - m_device->partitionTable()->updateUnallocated( *m_device ); - - // Copied from PM DeleteOperation::checkAdjustLogicalNumbers(): - // - // If the deleted partition is a logical one, we need to adjust the numbers - // of the other logical partitions in the extended one, if there are any, - // because the OS will do that, too: Logicals must be numbered without gaps, - // i.e., a numbering like sda5, sda6, sda8 (after sda7 is deleted) will - // become sda5, sda6, sda7 - Partition* parentPartition = dynamic_cast< Partition* >( m_partition->parent() ); - if ( parentPartition && parentPartition->roles().has( PartitionRole::Extended ) ) - { - parentPartition->adjustLogicalNumbers( m_partition->number(), -1 ); - } -} diff --git a/src/modules/partition/jobs/DeletePartitionJob.h b/src/modules/partition/jobs/DeletePartitionJob.h deleted file mode 100644 index 6d5ff1377e..0000000000 --- a/src/modules/partition/jobs/DeletePartitionJob.h +++ /dev/null @@ -1,44 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2015 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef DELETEPARTITIONJOB_H -#define DELETEPARTITIONJOB_H - -#include "PartitionJob.h" - -class Device; -class Partition; -class FileSystem; - -/** - * Deletes an existing partition. - * - * This is only used for partitions which already existed before the installer - * was started: partitions created within the installer and then removed are - * simply forgotten. - */ -class DeletePartitionJob : public PartitionJob -{ - Q_OBJECT -public: - DeletePartitionJob( Device* device, Partition* partition ); - QString prettyName() const override; - QString prettyDescription() const override; - QString prettyStatusMessage() const override; - Calamares::JobResult exec() override; - - void updatePreview(); - Device* device() const { return m_device; } - -private: - Device* m_device; -}; - -#endif /* DELETEPARTITIONJOB_H */ diff --git a/src/modules/partition/jobs/FillGlobalStorageJob.cpp b/src/modules/partition/jobs/FillGlobalStorageJob.cpp deleted file mode 100644 index 357c1e2109..0000000000 --- a/src/modules/partition/jobs/FillGlobalStorageJob.cpp +++ /dev/null @@ -1,400 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017 2019-2020, Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "FillGlobalStorageJob.h" - -#include "compat/Variant.h" -#include "core/KPMHelpers.h" -#include "core/PartitionInfo.h" - -#include "Branding.h" -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "partition/FileSystem.h" -#include "partition/Global.h" -#include "partition/PartitionIterator.h" -#include "utils/Logger.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -using Calamares::Partition::PartitionIterator; -using Calamares::Partition::untranslatedFS; -using Calamares::Partition::userVisibleFS; - -typedef QHash< QString, QString > UuidForPartitionHash; - -static UuidForPartitionHash -findPartitionUuids( QList< Device* > devices ) -{ - UuidForPartitionHash hash; - foreach ( Device* device, devices ) - { - for ( auto it = PartitionIterator::begin( device ); it != PartitionIterator::end( device ); ++it ) - { - Partition* p = *it; - QString path = p->partitionPath(); - QString uuid = p->fileSystem().readUUID( p->partitionPath() ); - hash.insert( path, uuid ); - } - } - - if ( hash.isEmpty() ) - { - cDebug() << "No UUIDs found for existing partitions."; - } - return hash; -} - - -static QString -getLuksUuid( const QString& path ) -{ - QProcess process; - process.setProgram( "cryptsetup" ); - process.setArguments( { "luksUUID", path } ); - process.start(); - process.waitForFinished(); - if ( process.exitStatus() != QProcess::NormalExit || process.exitCode() ) - { - return QString(); - } - QString uuid = QString::fromLocal8Bit( process.readAllStandardOutput() ).trimmed(); - return uuid; -} - - -static QVariant -mapForPartition( Partition* partition, const QString& uuid ) -{ - QVariantMap map; - map[ "device" ] = partition->partitionPath(); - map[ "partlabel" ] = partition->label(); - map[ "partuuid" ] = partition->uuid(); - map[ "mountPoint" ] = PartitionInfo::mountPoint( partition ); - map[ "fsName" ] = userVisibleFS( partition->fileSystem() ); - map[ "fs" ] = untranslatedFS( partition->fileSystem() ); - map[ "parttype" ] = partition->type(); - map[ "partattrs" ] = partition->attributes(); - map[ "features" ] = partition->fileSystem().features(); - - if ( partition->fileSystem().type() == FileSystem::Luks - && dynamic_cast< FS::luks& >( partition->fileSystem() ).innerFS() ) - { - map[ "fs" ] = untranslatedFS( dynamic_cast< FS::luks& >( partition->fileSystem() ).innerFS() ); - } - if ( partition->fileSystem().type() == FileSystem::Luks2 - && dynamic_cast< FS::luks2& >( partition->fileSystem() ).innerFS() ) - { - map[ "fs" ] = untranslatedFS( dynamic_cast< FS::luks2& >( partition->fileSystem() ).innerFS() ); - } - - map[ "uuid" ] = uuid; - map[ "claimed" ] = PartitionInfo::format( partition ); // If we formatted it, it's ours - - // Debugging for inside the loop in createPartitionList(), - // so indent a bit - Logger::CDebug deb; - using TR = Logger::DebugRow< const char* const, const QString >; - // clang-format off - deb << Logger::SubEntry << "mapping for" << partition->partitionPath() << partition->deviceNode() - << TR( "partlabel", map[ "partlabel" ].toString() ) - << TR( "partition-uuid (partuuid)", Logger::RedactedName( "PartUUID", map[ "partuuid" ].toString() ) ) - << TR( "parttype", map[ "parttype" ].toString() ) - << TR( "partattrs", map[ "partattrs" ].toString() ) - << TR( "mountPoint:", PartitionInfo::mountPoint( partition ) ) - << TR( "fs:", map[ "fs" ].toString() ) - << TR( "fsName", map[ "fsName" ].toString() ) - << TR( "filesystem-uuid (uuid)", Logger::RedactedName( "FSUUID", uuid ) ) - << TR( "claimed", map[ "claimed" ].toString() ); - // clang-format on - if ( partition->roles().has( PartitionRole::Luks ) ) - { - const FileSystem& fsRef = partition->fileSystem(); - const FS::luks* luksFs = dynamic_cast< const FS::luks* >( &fsRef ); - if ( luksFs ) - { - map[ "luksMapperName" ] = luksFs->mapperName().split( "/" ).last(); - map[ "luksUuid" ] = getLuksUuid( partition->partitionPath() ); - map[ "luksPassphrase" ] = luksFs->passphrase(); - deb << TR( "luksMapperName:", map[ "luksMapperName" ].toString() ); - } - } - - return map; -} - -static QString -prettyFileSystemFeatures( const QVariantMap& features ) -{ - QStringList list; - for ( const auto& key : features.keys() ) - { - const auto& value = features.value( key ); - if ( Calamares::typeOf( value ) == Calamares::BoolVariantType ) - { - if ( value.toBool() ) - { - list += key; - } - else - { - list += QString( "not " ) + key; - } - } - else - { - list += key + QString( "=" ) + value.toString(); - } - } - - return list.join( QStringLiteral( ", " ) ); -} - -FillGlobalStorageJob::FillGlobalStorageJob( const Config*, QList< Device* > devices, const QString& bootLoaderPath ) - : m_devices( devices ) - , m_bootLoaderPath( bootLoaderPath ) -{ -} - -QString -FillGlobalStorageJob::prettyName() const -{ - return tr( "Set partition information", "@title" ); -} - - -QString -FillGlobalStorageJob::prettyDescription() const -{ - QStringList lines; - - const auto partitionList = createPartitionList(); - for ( const QVariant& partitionItem : partitionList ) - { - if ( Calamares::typeOf( partitionItem ) == Calamares::MapVariantType ) - { - QVariantMap partitionMap = partitionItem.toMap(); - QString path = partitionMap.value( "device" ).toString(); - QString mountPoint = partitionMap.value( "mountPoint" ).toString(); - QString fsType = partitionMap.value( "fs" ).toString(); - QString features = prettyFileSystemFeatures( partitionMap.value( "features" ).toMap() ); - if ( mountPoint.isEmpty() || fsType.isEmpty() || fsType == QString( "unformatted" ) ) - { - continue; - } - if ( path.isEmpty() ) - { - if ( mountPoint == "/" ) - { - if ( !features.isEmpty() ) - { - lines.append( tr( "Install %1 on new %2 system partition " - "with features %3", - "@info" ) - .arg( Calamares::Branding::instance()->shortProductName() ) - .arg( fsType ) - .arg( features ) ); - } - else - { - lines.append( tr( "Install %1 on new %2 system partition", "@info" ) - .arg( Calamares::Branding::instance()->shortProductName() ) - .arg( fsType ) ); - } - } - else - { - if ( !features.isEmpty() ) - { - lines.append( tr( "Set up new %2 partition with mount point " - "%1 and features %3", - "@info" ) - .arg( mountPoint ) - .arg( fsType ) - .arg( features ) ); - } - else - { - lines.append( tr( "Set up new %2 partition with mount point " - "%1%3", - "@info" ) - .arg( mountPoint ) - .arg( fsType ) - .arg( features ) ); - } - } - } - else - { - if ( mountPoint == "/" ) - { - if ( !features.isEmpty() ) - { - lines.append( tr( "Install %2 on %3 system partition %1" - " with features %4", - "@info" ) - .arg( path ) - .arg( Calamares::Branding::instance()->shortProductName() ) - .arg( fsType ) - .arg( features ) ); - } - else - { - lines.append( tr( "Install %2 on %3 system partition %1", "@info" ) - .arg( path ) - .arg( Calamares::Branding::instance()->shortProductName() ) - .arg( fsType ) ); - } - } - else - { - if ( !features.isEmpty() ) - { - lines.append( tr( "Set up %3 partition %1 with mount point " - "%2 and features %4", - "@info" ) - .arg( path ) - .arg( mountPoint ) - .arg( fsType ) - .arg( features ) ); - } - else - { - lines.append( tr( "Set up %3 partition %1 with mount point " - "%2%4…", - "@info" ) - .arg( path ) - .arg( mountPoint ) - .arg( fsType ) - .arg( QString() ) ); - } - } - } - } - } - - QVariant bootloaderMap = createBootLoaderMap(); - if ( !m_bootLoaderPath.isEmpty() ) - { - lines.append( tr( "Install boot loader on %1…", "@info" ).arg( m_bootLoaderPath ) ); - } - return lines.join( "
    " ); -} - - -QString -FillGlobalStorageJob::prettyStatusMessage() const -{ - return tr( "Setting up mount points…", "@status" ); -} - - -/** @brief note which FS'ses are in use in GS - * - * .. mark as "1" if it's on the system, somewhere - * .. mark as "2" if it's one of the claimed / in-use FSses - * - * Stores a GS key called "filesystem_use" with this mapping. - * @see Calamares::Partition::useFilesystemGS() - */ -static void -storeFSUse( Calamares::GlobalStorage* storage, const QVariantList& partitions ) -{ - if ( storage ) - { - Calamares::Partition::clearFilesystemGS( storage ); - for ( const auto& p : partitions ) - { - const auto pmap = p.toMap(); - - QString fs = pmap.value( "fs" ).toString(); - - if ( fs.isEmpty() ) - { - continue; - } - - Calamares::Partition::useFilesystemGS( storage, fs, true ); - } - } -} - -Calamares::JobResult -FillGlobalStorageJob::exec() -{ - Calamares::GlobalStorage* storage = Calamares::JobQueue::instance()->globalStorage(); - const auto partitions = createPartitionList(); - cDebug() << "Saving partition information map to GlobalStorage[\"partitions\"]"; - storage->insert( "partitions", partitions ); - storeFSUse( storage, partitions ); - - if ( !m_bootLoaderPath.isEmpty() ) - { - QVariant var = createBootLoaderMap(); - if ( !var.isValid() ) - { - cDebug() << "Failed to find path for boot loader"; - } - cDebug() << "FillGlobalStorageJob writing bootLoader path:" << var; - storage->insert( "bootLoader", var ); - } - else - { - cDebug() << "FillGlobalStorageJob writing empty bootLoader value"; - storage->insert( "bootLoader", QVariant() ); - } - return Calamares::JobResult::ok(); -} - -QVariantList -FillGlobalStorageJob::createPartitionList() const -{ - UuidForPartitionHash hash = findPartitionUuids( m_devices ); - QVariantList lst; - cDebug() << "Building partition information map"; - for ( auto device : m_devices ) - { - cDebug() << Logger::SubEntry << "partitions on" << device->deviceNode(); - for ( auto it = PartitionIterator::begin( device ); it != PartitionIterator::end( device ); ++it ) - { - // Debug-logging is done when creating the map - lst << mapForPartition( *it, hash.value( ( *it )->partitionPath() ) ); - } - } - return lst; -} - -QVariant -FillGlobalStorageJob::createBootLoaderMap() const -{ - QVariantMap map; - QString path = m_bootLoaderPath; - if ( !path.startsWith( "/dev/" ) ) - { - Partition* partition = KPMHelpers::findPartitionByMountPoint( m_devices, path ); - if ( !partition ) - { - return QVariant(); - } - path = partition->partitionPath(); - } - map[ "installPath" ] = path; - return map; -} diff --git a/src/modules/partition/jobs/FillGlobalStorageJob.h b/src/modules/partition/jobs/FillGlobalStorageJob.h deleted file mode 100644 index 039fb18d82..0000000000 --- a/src/modules/partition/jobs/FillGlobalStorageJob.h +++ /dev/null @@ -1,49 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2015 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef FILLGLOBALSTORAGEJOB_H -#define FILLGLOBALSTORAGEJOB_H - -#include "Job.h" - -#include -#include - -class Config; -class Device; -class Partition; - -/** - * This job does not touch devices. It inserts in GlobalStorage the - * partition-related keys (see hacking/GlobalStorage.md) - * - * Inserting the keys after partitioning makes it possible to access - * information such as the partition path or the UUID. - */ -class FillGlobalStorageJob : public Calamares::Job -{ - Q_OBJECT -public: - FillGlobalStorageJob( const Config* config, QList< Device* > devices, const QString& bootLoaderPath ); - - QString prettyName() const override; - QString prettyDescription() const override; - QString prettyStatusMessage() const override; - Calamares::JobResult exec() override; - -private: - QList< Device* > m_devices; - QString m_bootLoaderPath; - - QVariantList createPartitionList() const; - QVariant createBootLoaderMap() const; -}; - -#endif /* FILLGLOBALSTORAGEJOB_H */ diff --git a/src/modules/partition/jobs/FormatPartitionJob.cpp b/src/modules/partition/jobs/FormatPartitionJob.cpp deleted file mode 100644 index e373cec403..0000000000 --- a/src/modules/partition/jobs/FormatPartitionJob.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "FormatPartitionJob.h" - -#include "core/KPMHelpers.h" - -#include "partition/FileSystem.h" -#include "utils/Logger.h" -#include "utils/System.h" - -#include -#include -#include -#include -#include -#include - -using Calamares::Partition::untranslatedFS; -using Calamares::Partition::userVisibleFS; - -FormatPartitionJob::FormatPartitionJob( Device* device, Partition* partition ) - : PartitionJob( partition ) - , m_device( device ) -{ -} - -QString -FormatPartitionJob::prettyName() const -{ - return tr( "Format partition %1 (file system: %2, size: %3 MiB) on %4", "@title" ) - .arg( m_partition->partitionPath() ) - .arg( userVisibleFS( m_partition->fileSystem() ) ) - .arg( m_partition->capacity() / 1024 / 1024 ) - .arg( m_device->name() ); -} - -QString -FormatPartitionJob::prettyDescription() const -{ - return tr( "Format %3MiB partition %1 with " - "file system %2", - "@info" ) - .arg( m_partition->partitionPath() ) - .arg( userVisibleFS( m_partition->fileSystem() ) ) - .arg( m_partition->capacity() / 1024 / 1024 ); -} - -QString -FormatPartitionJob::prettyStatusMessage() const -{ - QString partitionLabel = m_partition->label().isEmpty() - ? m_partition->partitionPath() - : tr( "%1 (%2)", "partition label %1 (device path %2)" ) - .arg( m_partition->label(), m_partition->partitionPath() ); - return tr( "Formatting partition %1 with file system %2…", "@status" ) - .arg( partitionLabel, userVisibleFS( m_partition->fileSystem() ) ); -} - -Calamares::JobResult -FormatPartitionJob::exec() -{ - const auto fsType = m_partition->fileSystem().type(); - auto r = KPMHelpers::execute( CreateFileSystemOperation( *m_device, *m_partition, fsType ), - tr( "The installer failed to format partition %1 on disk '%2'." ) - .arg( m_partition->partitionPath(), m_device->name() ) ); - if ( fsType == FileSystem::Xfs && r.succeeded() ) - { - // We are going to try to set modern timestamps for the filesystem, - // (ignoring whether this succeeds). Requires a sufficiently-new - // xfs_admin and xfs_repair and might be made obsolete by newer - // kpmcore releases. - Calamares::System::runCommand( { "xfs_admin", "-O", "bigtime=1", m_partition->partitionPath() }, - std::chrono::seconds( 60 ) ); - } - return r; -} diff --git a/src/modules/partition/jobs/FormatPartitionJob.h b/src/modules/partition/jobs/FormatPartitionJob.h deleted file mode 100644 index 38b2ee1a95..0000000000 --- a/src/modules/partition/jobs/FormatPartitionJob.h +++ /dev/null @@ -1,42 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2015 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef FORMATPARTITIONJOB_H -#define FORMATPARTITIONJOB_H - -#include "PartitionJob.h" - -class Device; -class Partition; -class FileSystem; - -/** - * This job formats an existing partition. - * - * It is only used for existing partitions: newly created partitions are - * formatted by the CreatePartitionJob. - */ -class FormatPartitionJob : public PartitionJob -{ - Q_OBJECT -public: - FormatPartitionJob( Device* device, Partition* partition ); - QString prettyName() const override; - QString prettyDescription() const override; - QString prettyStatusMessage() const override; - Calamares::JobResult exec() override; - - Device* device() const { return m_device; } - -private: - Device* m_device; -}; - -#endif /* FORMATPARTITIONJOB_H */ diff --git a/src/modules/partition/jobs/PartitionJob.cpp b/src/modules/partition/jobs/PartitionJob.cpp deleted file mode 100644 index ca9b00944c..0000000000 --- a/src/modules/partition/jobs/PartitionJob.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "PartitionJob.h" - -PartitionJob::PartitionJob( Partition* partition ) - : m_partition( partition ) -{ -} - -void -PartitionJob::iprogress( int percent ) -{ - if ( percent < 0 ) - { - percent = 0; - } - if ( percent > 100 ) - { - percent = 100; - } - Q_EMIT progress( qreal( percent / 100.0 ) ); -} diff --git a/src/modules/partition/jobs/PartitionJob.h b/src/modules/partition/jobs/PartitionJob.h deleted file mode 100644 index f808a798f0..0000000000 --- a/src/modules/partition/jobs/PartitionJob.h +++ /dev/null @@ -1,43 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef PARTITIONJOB_H -#define PARTITIONJOB_H - -#include "Job.h" -#include "partition/KPMManager.h" - -class Partition; - -/** - * Base class for jobs which affect a partition and which use KPMCore. - */ -class PartitionJob : public Calamares::Job -{ - Q_OBJECT -public: - PartitionJob( Partition* partition ); - - Partition* partition() const { return m_partition; } - -public slots: - /** @brief Translate from KPMCore to Calamares progress. - * - * KPMCore presents progress as an integer percent from 0 .. 100, - * while Calamares uses a qreal from 0 .. 1.00 . - */ - void iprogress( int percent ); - -protected: - Calamares::Partition::KPMManager m_kpmcore; - Partition* m_partition; -}; - -#endif /* PARTITIONJOB_H */ diff --git a/src/modules/partition/jobs/RemoveVolumeGroupJob.cpp b/src/modules/partition/jobs/RemoveVolumeGroupJob.cpp deleted file mode 100644 index b139d93a86..0000000000 --- a/src/modules/partition/jobs/RemoveVolumeGroupJob.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "RemoveVolumeGroupJob.h" - -#include "core/KPMHelpers.h" - -#include -#include -#include - -RemoveVolumeGroupJob::RemoveVolumeGroupJob( Device*, LvmDevice* device ) - : m_device( device ) -{ -} - -QString -RemoveVolumeGroupJob::prettyName() const -{ - return tr( "Removing Volume Group named %1…", "@status" ).arg( m_device->name() ); -} - -QString -RemoveVolumeGroupJob::prettyDescription() const -{ - return tr( "Removing Volume Group named %1…", "@status" ).arg( m_device->name() ); -} - -QString -RemoveVolumeGroupJob::prettyStatusMessage() const -{ - return tr( "Removing Volume Group named %1…", "@status" ).arg( m_device->name() ); -} - -Calamares::JobResult -RemoveVolumeGroupJob::exec() -{ - return KPMHelpers::execute( - RemoveVolumeGroupOperation( *m_device ), - tr( "The installer failed to remove a volume group named '%1'." ).arg( m_device->name() ) ); -} diff --git a/src/modules/partition/jobs/RemoveVolumeGroupJob.h b/src/modules/partition/jobs/RemoveVolumeGroupJob.h deleted file mode 100644 index a1f586f0c6..0000000000 --- a/src/modules/partition/jobs/RemoveVolumeGroupJob.h +++ /dev/null @@ -1,35 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef REMOVEVOLUMEGROUPJOB_H -#define REMOVEVOLUMEGROUPJOB_H - -#include "Job.h" -#include "partition/KPMManager.h" - -class Device; -class LvmDevice; - -class RemoveVolumeGroupJob : public Calamares::Job -{ - Q_OBJECT -public: - RemoveVolumeGroupJob( Device*, LvmDevice* device ); - - QString prettyName() const override; - QString prettyDescription() const override; - QString prettyStatusMessage() const override; - Calamares::JobResult exec() override; - -private: - Calamares::Partition::KPMManager m_kpmcore; - LvmDevice* m_device; -}; - -#endif // REMOVEVOLUMEGROUPJOB_H diff --git a/src/modules/partition/jobs/ResizePartitionJob.cpp b/src/modules/partition/jobs/ResizePartitionJob.cpp deleted file mode 100644 index 3aec413588..0000000000 --- a/src/modules/partition/jobs/ResizePartitionJob.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017 Andrius Štikonas - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "ResizePartitionJob.h" - -#include "core/KPMHelpers.h" - -#include "utils/Units.h" - -#include -#include -#include - -using Calamares::BytesToMiB; - -//- ResizePartitionJob --------------------------------------------------------- -ResizePartitionJob::ResizePartitionJob( Device* device, Partition* partition, qint64 firstSector, qint64 lastSector ) - : PartitionJob( partition ) - , m_device( device ) - , m_oldFirstSector( - partition->firstSector() ) // Keep a copy of old sectors because they will be overwritten in updatePreview() - , m_oldLastSector( partition->lastSector() ) - , m_newFirstSector( firstSector ) - , m_newLastSector( lastSector ) -{ -} - -QString -ResizePartitionJob::prettyName() const -{ - return tr( "Resize partition %1", "@title" ).arg( partition()->partitionPath() ); -} - -QString -ResizePartitionJob::prettyDescription() const -{ - return tr( "Resize %2MiB partition %1 to %3MiB", "@info" ) - .arg( partition()->partitionPath() ) - .arg( ( BytesToMiB( m_oldLastSector - m_oldFirstSector + 1 ) * partition()->sectorSize() ) ) - .arg( ( BytesToMiB( m_newLastSector - m_newFirstSector + 1 ) * partition()->sectorSize() ) ); -} - -QString -ResizePartitionJob::prettyStatusMessage() const -{ - return tr( "Resizing %2MiB partition %1 to %3MiB…", "@status" ) - .arg( partition()->partitionPath() ) - .arg( ( BytesToMiB( m_oldLastSector - m_oldFirstSector + 1 ) * partition()->sectorSize() ) ) - .arg( ( BytesToMiB( m_newLastSector - m_newFirstSector + 1 ) * partition()->sectorSize() ) ); -} - -Calamares::JobResult -ResizePartitionJob::exec() -{ - // Restore partition sectors that were modified for preview - m_partition->setFirstSector( m_oldFirstSector ); - m_partition->setLastSector( m_oldLastSector ); - - ResizeOperation op( *m_device, *m_partition, m_newFirstSector, m_newLastSector ); - connect( &op, &Operation::progress, this, &ResizePartitionJob::iprogress ); - return KPMHelpers::execute( op, - tr( "The installer failed to resize partition %1 on disk '%2'." ) - .arg( m_partition->partitionPath() ) - .arg( m_device->name() ) ); -} - -void -ResizePartitionJob::updatePreview() -{ - m_device->partitionTable()->removeUnallocated(); - m_partition->parent()->remove( m_partition ); - m_partition->setFirstSector( m_newFirstSector ); - m_partition->setLastSector( m_newLastSector ); - m_partition->parent()->insert( m_partition ); - m_device->partitionTable()->updateUnallocated( *m_device ); -} - -Device* -ResizePartitionJob::device() const -{ - return m_device; -} diff --git a/src/modules/partition/jobs/ResizePartitionJob.h b/src/modules/partition/jobs/ResizePartitionJob.h deleted file mode 100644 index 9e24b2d04f..0000000000 --- a/src/modules/partition/jobs/ResizePartitionJob.h +++ /dev/null @@ -1,47 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2015 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef RESIZEPARTITIONJOB_H -#define RESIZEPARTITIONJOB_H - -#include "PartitionJob.h" - -class Device; -class Partition; -class FileSystem; - -/** - * This job resizes an existing partition. - * - * It can grow, shrink and/or move a partition while preserving its content. - */ -class ResizePartitionJob : public PartitionJob -{ - Q_OBJECT -public: - ResizePartitionJob( Device* device, Partition* partition, qint64 firstSector, qint64 lastSector ); - QString prettyName() const override; - QString prettyDescription() const override; - QString prettyStatusMessage() const override; - Calamares::JobResult exec() override; - - void updatePreview(); - - Device* device() const; - -private: - Device* m_device; - qint64 m_oldFirstSector; - qint64 m_oldLastSector; - qint64 m_newFirstSector; - qint64 m_newLastSector; -}; - -#endif /* RESIZEPARTITIONJOB_H */ diff --git a/src/modules/partition/jobs/ResizeVolumeGroupJob.cpp b/src/modules/partition/jobs/ResizeVolumeGroupJob.cpp deleted file mode 100644 index a6427116ee..0000000000 --- a/src/modules/partition/jobs/ResizeVolumeGroupJob.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "ResizeVolumeGroupJob.h" - -#include "core/KPMHelpers.h" - -#include -#include -#include -#include - -ResizeVolumeGroupJob::ResizeVolumeGroupJob( Device*, LvmDevice* device, QVector< const Partition* >& partitionList ) - : m_device( device ) - , m_partitionList( partitionList ) -{ -} - -QString -ResizeVolumeGroupJob::prettyName() const -{ - return tr( "Resize volume group named %1 from %2 to %3", "@title" ) - .arg( m_device->name() ) - .arg( currentPartitions() ) - .arg( targetPartitions() ); -} - -QString -ResizeVolumeGroupJob::prettyDescription() const -{ - return tr( "Resize volume group named %1 from %2 to %3", - "@info" ) - .arg( m_device->name() ) - .arg( currentPartitions() ) - .arg( targetPartitions() ); -} - -QString -ResizeVolumeGroupJob::prettyStatusMessage() const -{ - return tr( "Resizing volume group named %1 from %2 to %3…", "@status" ) - .arg( m_device->name() ) - .arg( currentPartitions() ) - .arg( targetPartitions() ); -} - -Calamares::JobResult -ResizeVolumeGroupJob::exec() -{ - return KPMHelpers::execute( - ResizeVolumeGroupOperation( *m_device, m_partitionList ), - tr( "The installer failed to resize a volume group named '%1'." ).arg( m_device->name() ) ); -} - -QString -ResizeVolumeGroupJob::currentPartitions() const -{ - QString result; - - for ( const Partition* p : m_device->physicalVolumes() ) - { - result += p->deviceNode() + ", "; - } - - result.chop( 2 ); - - return result; -} - -QString -ResizeVolumeGroupJob::targetPartitions() const -{ - QString result; - - for ( const Partition* p : m_partitionList ) - { - result += p->deviceNode() + ", "; - } - - result.chop( 2 ); - - return result; -} diff --git a/src/modules/partition/jobs/ResizeVolumeGroupJob.h b/src/modules/partition/jobs/ResizeVolumeGroupJob.h deleted file mode 100644 index 07765cff40..0000000000 --- a/src/modules/partition/jobs/ResizeVolumeGroupJob.h +++ /dev/null @@ -1,43 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef RESIZEVOLUMEGROUPJOB_H -#define RESIZEVOLUMEGROUPJOB_H - -#include "Job.h" -#include "partition/KPMManager.h" - -#include - -class Device; -class LvmDevice; -class Partition; - -class ResizeVolumeGroupJob : public Calamares::Job -{ - Q_OBJECT -public: - ResizeVolumeGroupJob( Device*, LvmDevice* device, QVector< const Partition* >& partitionList ); - - QString prettyName() const override; - QString prettyDescription() const override; - QString prettyStatusMessage() const override; - Calamares::JobResult exec() override; - -private: - QString currentPartitions() const; - QString targetPartitions() const; - -private: - Calamares::Partition::KPMManager m_kpmcore; - LvmDevice* m_device; - QVector< const Partition* > m_partitionList; -}; - -#endif // RESIZEVOLUMEGROUPJOB_H diff --git a/src/modules/partition/jobs/SetPartitionFlagsJob.cpp b/src/modules/partition/jobs/SetPartitionFlagsJob.cpp deleted file mode 100644 index 1eafc6394b..0000000000 --- a/src/modules/partition/jobs/SetPartitionFlagsJob.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2008 2010, Volker Lanz - * SPDX-FileCopyrightText: 2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Based on the SetPartFlagsJob class from KDE Partition Manager - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "SetPartitionFlagsJob.h" - -#include "core/KPMHelpers.h" - -#include "partition/FileSystem.h" -#include "utils/Logger.h" -#include "utils/Units.h" - -#include -#include -#include -#include -#include - -using Calamares::BytesToMiB; -using Calamares::Partition::untranslatedFS; -using Calamares::Partition::userVisibleFS; - -SetPartFlagsJob::SetPartFlagsJob( Device* device, Partition* partition, PartitionTable::Flags flags ) - : PartitionJob( partition ) - , m_device( device ) - , m_flags( flags ) -{ -} - -QString -SetPartFlagsJob::prettyName() const -{ - if ( !partition()->partitionPath().isEmpty() ) - { - return tr( "Set flags on partition %1", "@title" ).arg( partition()->partitionPath() ); - } - - QString fsNameForUser = userVisibleFS( partition()->fileSystem() ); - if ( !fsNameForUser.isEmpty() ) - { - return tr( "Set flags on %1MiB %2 partition", "@title" ) - .arg( BytesToMiB( partition()->capacity() ) ) - .arg( fsNameForUser ); - } - return tr( "Set flags on new partition", "@title" ); -} - -QString -SetPartFlagsJob::prettyDescription() const -{ - QStringList flagsList = PartitionTable::flagNames( m_flags ); - if ( flagsList.count() == 0 ) - { - if ( !partition()->partitionPath().isEmpty() ) - { - return tr( "Clear flags on partition %1", "@info" ).arg( partition()->partitionPath() ); - } - - QString fsNameForUser = userVisibleFS( partition()->fileSystem() ); - if ( !fsNameForUser.isEmpty() ) - { - return tr( "Clear flags on %1MiB %2 partition", "@info" ) - .arg( BytesToMiB( partition()->capacity() ) ) - .arg( fsNameForUser ); - } - return tr( "Clear flags on new partition", "@info" ); - } - - if ( !partition()->partitionPath().isEmpty() ) - { - return tr( "Set flags on partition %1 to %2", "@info" ) - .arg( partition()->partitionPath() ) - .arg( flagsList.join( ", " ) ); - } - - QString fsNameForUser = userVisibleFS( partition()->fileSystem() ); - if ( !fsNameForUser.isEmpty() ) - { - return tr( "Set flags on %1MiB %2 partition to %3", "@info" ) - .arg( BytesToMiB( partition()->capacity() ) ) - .arg( fsNameForUser ) - .arg( flagsList.join( ", " ) ); - } - - return tr( "Set flags on new partition to %1", "@info" ).arg( flagsList.join( ", " ) ); -} - -QString -SetPartFlagsJob::prettyStatusMessage() const -{ - QStringList flagsList = PartitionTable::flagNames( m_flags ); - if ( flagsList.count() == 0 ) - { - if ( !partition()->partitionPath().isEmpty() ) - { - return tr( "Clearing flags on partition %1…", "@status" ) - .arg( partition()->partitionPath() ); - } - - QString fsNameForUser = userVisibleFS( partition()->fileSystem() ); - if ( !fsNameForUser.isEmpty() ) - { - return tr( "Clearing flags on %1MiB %2 partition…", "@status" ) - .arg( BytesToMiB( partition()->capacity() ) ) - .arg( fsNameForUser ); - } - - return tr( "Clearing flags on new partition…", "@status" ); - } - - if ( !partition()->partitionPath().isEmpty() ) - { - return tr( "Setting flags %2 on partition %1…", "@status" ) - .arg( partition()->partitionPath() ) - .arg( flagsList.join( ", " ) ); - } - - QString fsNameForUser = userVisibleFS( partition()->fileSystem() ); - if ( !fsNameForUser.isEmpty() ) - { - return tr( "Setting flags %3 on %1MiB %2 partition…", "@status" ) - .arg( BytesToMiB( partition()->capacity() ) ) - .arg( fsNameForUser ) - .arg( flagsList.join( ", " ) ); - } - - return tr( "Setting flags %1 on new partition…", "@status" ).arg( flagsList.join( ", " ) ); -} - -Calamares::JobResult -SetPartFlagsJob::exec() -{ - QStringList flagsList = PartitionTable::flagNames( m_flags ); - cDebug() << "Setting flags on" << m_device->deviceNode() << "partition" << partition()->deviceNode() - << Logger::DebugList( flagsList ); - - SetPartFlagsOperation op( *m_device, *partition(), m_flags ); - connect( &op, &Operation::progress, this, &SetPartFlagsJob::iprogress ); - return KPMHelpers::execute( - op, tr( "The installer failed to set flags on partition %1." ).arg( m_partition->partitionPath() ) ); -} diff --git a/src/modules/partition/jobs/SetPartitionFlagsJob.h b/src/modules/partition/jobs/SetPartitionFlagsJob.h deleted file mode 100644 index eb6d9586c5..0000000000 --- a/src/modules/partition/jobs/SetPartitionFlagsJob.h +++ /dev/null @@ -1,43 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2016 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Based on the SetPartFlagsJob class from KDE Partition Manager, - * SPDX-FileCopyrightText: 2008 2010, Volker Lanz - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef SETPARTITIONFLAGSJOB_H -#define SETPARTITIONFLAGSJOB_H - -#include "PartitionJob.h" - -#include - -class Device; -class Partition; - -/** - * This job changes the flags on an existing partition. - */ -class SetPartFlagsJob : public PartitionJob -{ - Q_OBJECT -public: - SetPartFlagsJob( Device* device, Partition* partition, PartitionTable::Flags flags ); - QString prettyName() const override; - QString prettyDescription() const override; - QString prettyStatusMessage() const override; - Calamares::JobResult exec() override; - - Device* device() const; - -private: - Device* m_device; - PartitionTable::Flags m_flags; -}; - -#endif // SETPARTITIONFLAGSJOB_H diff --git a/src/modules/partition/partition.conf b/src/modules/partition/partition.conf deleted file mode 100644 index 0f23323f84..0000000000 --- a/src/modules/partition/partition.conf +++ /dev/null @@ -1,321 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# - -# Options for EFI system partition. -# -# - *mountPoint* -# This setting specifies the mount point of the EFI system partition. Some -# distributions (Fedora, Debian, Manjaro, etc.) use /boot/efi, others (KaOS, -# etc.) use just /boot. -# -# Defaults to "/boot/efi", may be empty (but weird effects ensue) -# - *recommendedSize* -# This optional setting specifies the size of the EFI system partition. -# If nothing is specified, the default size of 300MiB will be used. -# When writing quantities here, M is treated as MiB, and if you really -# want one-million (10^6) bytes, use MB. -# - *minimumSize* -# This optional setting specifies the absolute minimum size of the EFI -# system partition. If nothing is specified, the *recommendedSize* -# is used instead. -# - *label* -# This optional setting specifies the name of the EFI system partition (see -# PARTLABEL; gpt only; requires KPMCore >= 4.2.0). -# If nothing is specified, the partition name is left unset. -# -# Going below the *recommended* size is allowed, but the user will -# get a warning that it might not work. Going below the *minimum* -# size is not allowed and the user will be told it will not work. -# -# Both quantities must be at least 32MiB, this is enforced by the EFI -# spec. If minimum is not specified, it defaults to the recommended -# size. Distro's that allow more user latitude can set the minimum lower. -efi: - mountPoint: "/boot/efi" - recommendedSize: 300MiB - minimumSize: 32MiB - label: "EFI" - -# Deprecated alias of efi.mountPoint -# efiSystemPartition: "/boot/efi" - -# Deprecated alias of efi.recommendedSize -# efiSystemPartitionSize: 300MiB - -# Deprecated alias of efi.label -# efiSystemPartitionName: EFI - -# In autogenerated partitioning, allow the user to select a swap size? -# If there is exactly one choice, no UI is presented, and the user -# cannot make a choice -- this setting is used. If there is more than -# one choice, a UI is presented. -# -# Legacy settings *neverCreateSwap* and *ensureSuspendToDisk* correspond -# to values of *userSwapChoices* as follows: -# - *neverCreateSwap* is true, means [none] -# - *neverCreateSwap* is false, *ensureSuspendToDisk* is false, [small] -# - *neverCreateSwap* is false, *ensureSuspendToDisk* is true, [suspend] -# -# Autogenerated swap sizes are as follows: -# - *suspend*: Swap is always at least total memory size, -# and up to 4GiB RAM follows the rule-of-thumb 2 * memory; -# from 4GiB to 8 GiB it stays steady at 8GiB, and over 8 GiB memory -# swap is the size of main memory. -# - *small*: Follows the rules above, but Swap is at -# most 8GiB, and no more than 10% of available disk. -# In both cases, a fudge factor (usually 10% extra) is applied so that there -# is some space for administrative overhead (e.g. 8 GiB swap will allocate -# 8.8GiB on disk in the end). -# -# If *file* is enabled here, make sure to have the *fstab* module -# as well (later in the exec phase) so that the swap file is -# actually created. -userSwapChoices: - - none # Create no swap, use no swap - - small # Up to 4GB - - suspend # At least main memory size - # - reuse # Re-use existing swap, but don't create any (unsupported right now) - - file # To swap file instead of partition - -# This optional setting specifies the name of the swap partition (see -# PARTLABEL; gpt only; requires KPMCore >= 4.2.0). -# If nothing is specified, the partition name is left unset. -# swapPartitionName: swap - -# LEGACY SETTINGS (these will generate a warning) -# ensureSuspendToDisk: true -# neverCreateSwap: false - -# This setting specifies the LUKS generation (i.e LUKS1, LUKS2) used internally by -# cryptsetup when creating an encrypted partition. -# -# This option is set to luks1 by default, as grub doesn't support LUKS2 + Argon2id -# currently. On the other hand grub does support LUKS2 with PBKDF2 and could therefore be -# also set to luks2. Also there are some patches for grub and Argon2. -# See: https://aur.archlinux.org/packages/grub-improved-luks2-git -# -# Choices: luks1, luks2 (in addition, "luks" means "luks1") -# -# The default is luks1 -# -luksGeneration: luks1 - -# This setting determines if encryption should be allowed when using zfs. This -# setting has no effect unless zfs support is provided. -# -# This setting is to handle the fact that some bootloaders(such as grub) do not -# support zfs encryption. -# -# The default is true -# -# allowZfsEncryption: true - -# Correctly draw nested (e.g. logical) partitions as such. -drawNestedPartitions: false - -# Show/hide partition labels on manual partitioning page. -alwaysShowPartitionLabels: true - -# Allow manual partitioning. -# -# When set to false, this option hides the "Manual partitioning" button, -# limiting the user's choice to "Erase", "Replace" or "Alongside". -# This can be useful when using a custom partition layout we don't want -# the user to modify. -# -# If nothing is specified, manual partitioning is enabled. -#allowManualPartitioning: true - -# Show not encrypted boot partition warning. -# -# When set to false, this option does not show the -# "Boot partition not encrypted" warning when encrypting the -# root partition but not /boot partition. -# -# If nothing is specified, the warning is shown. -#showNotEncryptedBootMessage: true - -# Initial selection on the Choice page -# -# There are four radio buttons (in principle: erase, replace, alongside, manual), -# and you can pick which of them, if any, is initially selected. For most -# installers, "none" is the right choice: it makes the user pick something specific, -# rather than accidentally being able to click past an important choice (in particular, -# "erase" is a dangerous choice). -# -# The default is "none" -# -initialPartitioningChoice: none -# -# Similarly, some of the installation choices may offer a choice of swap; -# the available choices depend on *userSwapChoices*, above, and this -# setting can be used to pick a specific one. -# -# The default is "none" (no swap) if that is one of the enabled options, otherwise -# one of the items from the options. -initialSwapChoice: none - -# armInstall -# -# Leaves 16MB empty at the start of a drive when partitioning -# where usually the u-boot loader goes -# -# armInstall: false - -# Default partition table type, used when a "erase" disk is made. -# -# When erasing a disk, a new partition table is created on disk. -# In other cases, e.g. Replace and Alongside, as well as when using -# manual partitioning, this partition table exists already on disk -# and it is left unmodified. -# -# Suggested values: gpt, msdos -# If nothing is specified, Calamares defaults to "gpt" if system is -# efi or "msdos". -# -# Names are case-sensitive and defined by KPMCore. -# defaultPartitionTableType: msdos - -# Requirement for partition table type -# -# Restrict the installation on disks that match the type of partition -# tables that are specified. -# -# Possible values: msdos, gpt. Names are case-sensitive and defined by KPMCore. -# -# If nothing is specified, Calamares defaults to both "msdos" and "gpt". -# -# requiredPartitionTableType: gpt -# requiredPartitionTableType: -# - msdos -# - gpt - -# Default filesystem type, used when a "new" partition is made. -# -# When replacing a partition, the new filesystem type will be from the -# defaultFileSystemType value. In other cases, e.g. Erase and Alongside, -# as well as when using manual partitioning and creating a new -# partition, this filesystem type is pre-selected. Note that -# editing a partition in manual-creation mode will not automatically -# change the filesystem type to this default value -- it is not -# creating a new partition. -# -# Suggested values: ext2, ext3, ext4, reiser, xfs, jfs, btrfs -# If nothing is specified, Calamares defaults to "ext4". -# -# Names are case-sensitive and defined by KPMCore. -defaultFileSystemType: "ext4" - -# Selectable filesystem type, used when "erase" is done. -# -# When erasing the disk, the *defaultFileSystemType* is used (see -# above), but it is also possible to give users a choice: -# list suitable filesystems here. A drop-down is provided -# to pick which is the filesystems will be used. -# -# The value *defaultFileSystemType* is added to this list (with a warning) -# if not present; the default pick is the *defaultFileSystemType*. -# -# If not specified at all, uses *defaultFileSystemType* without a -# warning (this matches traditional no-choice-available behavior best). -# availableFileSystemTypes: ["ext4","f2fs"] - -# Show/hide LUKS related functionality in automated partitioning modes. -# Disable this if you choose not to deploy early unlocking support in GRUB2 -# and/or your distribution's initramfs solution. -# -# BIG FAT WARNING: -# -# This option is unsupported, as it cuts out a crucial security feature. -# Disabling LUKS and shipping Calamares without a correctly configured GRUB2 -# and initramfs is considered suboptimal use of the Calamares software. The -# Calamares team will not provide user support for any potential issue that -# may arise as a consequence of setting this option to false. -# It is strongly recommended that system integrators put in the work to support -# LUKS unlocking support in GRUB2 and initramfs/dracut/mkinitcpio/etc. -# For more information on setting up GRUB2 for Calamares with LUKS, see -# https://github.com/calamares/calamares/wiki/Deploy-LUKS -# -# If nothing is specified, LUKS is enabled in automated modes. -#enableLuksAutomatedPartitioning: true - -# Partition layout. -# -# This optional setting specifies a custom partition layout. -# -# If nothing is specified, the default partition layout is a single partition -# for root that uses 100% of the space and uses the filesystem defined by -# defaultFileSystemType. -# -# Note: the EFI system partition is prepend automatically to the layout if -# needed; the swap partition is appended to the layout if enabled (small of -# suspend). -# -# Otherwise, the partition layout is defined as follow: -# -# partitionLayout: -# - name: "rootfs" -# type: "4f68bce3-e8cd-4db1-96e7-fbcaf984b709" -# filesystem: "ext4" -# noEncrypt: false -# mountPoint: "/" -# size: 20% -# minSize: 500M -# maxSize: 10G -# attributes: 0xffff000000000003 -# - name: "home" -# type: "933ac7e1-2eb4-4f13-b844-0e14e2aef915" -# filesystem: "ext4" -# noEncrypt: false -# mountPoint: "/home" -# size: 3G -# minSize: 1.5G -# features: -# 64bit: false -# casefold: true -# - name: "data" -# filesystem: "fat32" -# mountPoint: "/data" -# features: -# sector-size: 4096 -# sectors-per-cluster: 128 -# size: 100% -# -# There can be any number of partitions, each entry having the following attributes: -# - name: filesystem label -# and -# partition name (gpt only; since KPMCore 4.2.0) -# - uuid: partition uuid (optional parameter; gpt only; requires KPMCore >= 4.2.0) -# - type: partition type (optional parameter; gpt only; requires KPMCore >= 4.2.0) -# - attributes: partition attributes (optional parameter; gpt only; requires KPMCore >= 4.2.0) -# - filesystem: filesystem type (optional parameter) -# - if not set at all, treat as "unformatted" -# - if "unformatted", no filesystem will be created -# - if "unknown" (or an unknown FS name, like "elephant") then the -# default filesystem type, or the user's choice, will be applied instead -# of "unknown" (e.g. the user might pick ext4, or xfs). -# - noEncrypt: whether this partition is exempt from encryption if enabled (optional parameter; default is false) -# - mountPoint: partition mount point (optional parameter; not mounted if unset) -# - size: partition size in bytes (append 'K', 'M' or 'G' for KiB, MiB or GiB) -# or -# % of the available drive space if a '%' is appended to the value -# - minSize: minimum partition size (optional parameter) -# - maxSize: maximum partition size (optional parameter) -# - features: filesystem features (optional parameter; requires KPMCore >= 4.2.0) -# name: boolean or integer or string - -# Checking for available storage -# -# This overlaps with the setting of the same name in the welcome module's -# requirements section. If nothing is set by the welcome module, this -# value is used instead. It is still a problem if there is no required -# size set at all, and the replace and resize options will not be offered -# if no required size is set. -# -# The value is in Gibibytes (GiB). -# -# BIG FAT WARNING: except for OEM-phase-0 use, you should be using -# the welcome module, **and** configure this value in -# `welcome.conf`, not here. -# requiredStorage: 3.5 diff --git a/src/modules/partition/partition.schema.yaml b/src/modules/partition/partition.schema.yaml deleted file mode 100644 index 769c1abae5..0000000000 --- a/src/modules/partition/partition.schema.yaml +++ /dev/null @@ -1,46 +0,0 @@ -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-FileCopyrightText: 2023 Evan James -# SPDX-License-Identifier: GPL-3.0-or-later ---- -$schema: https://json-schema.org/schema# -$id: https://calamares.io/schemas/partition -additionalProperties: false -type: object -properties: - efiSystemPartition: { type: string } # Deprecated alias of efi.mountPoint - efiSystemPartitionSize: { type: string } # Deprecated alias of efi.recommendedSize - efiSystemPartitionName: { type: string } # Deprecated alias of efi.label - - efi: - type: object - properties: - recommendedSize: { type: string } - minimumSize: { type: string } - label: { type: string } - mountPoint: { type: string } - additionalProperties: false - - userSwapChoices: { type: array, items: { type: string, enum: [ none, reuse, small, suspend, file ] } } - # ensureSuspendToDisk: { type: boolean, default: true } # Legacy - # neverCreateSwap: { type: boolean, default: false } # Legacy - armInstall: { type: boolean, default: false } - - allowZfsEncryption: { type: boolean, default: true } - drawNestedPartitions: { type: boolean, default: false } - alwaysShowPartitionLabels: { type: boolean, default: true } - - defaultFileSystemType: { type: string } - availableFileSystemTypes: { type: array, items: { type: string } } - - luksGeneration: { type: string, enum: [luks1, luks2] } # Also allows "luks" as alias of "luks1" - enableLuksAutomatedPartitioning: { type: boolean, default: false } - - allowManualPartitioning: { type: boolean, default: true } - showNotEncryptedBootMessage: { type: boolean, default: true } - partitionLayout: { type: array } # TODO: specify items - initialPartitioningChoice: { type: string, enum: [ none, erase, replace, alongside, manual ] } - initialSwapChoice: { type: string, enum: [ none, small, suspend, reuse, file ] } - - requiredStorage: { type: number } -required: - - userSwapChoices diff --git a/src/modules/partition/tests/1a-legacy.conf b/src/modules/partition/tests/1a-legacy.conf deleted file mode 100644 index f3435a262c..0000000000 --- a/src/modules/partition/tests/1a-legacy.conf +++ /dev/null @@ -1,2 +0,0 @@ ---- -efiSystemPartitionSize: 100MiB diff --git a/src/modules/partition/tests/1b-legacy.conf b/src/modules/partition/tests/1b-legacy.conf deleted file mode 100644 index 9792e81557..0000000000 --- a/src/modules/partition/tests/1b-legacy.conf +++ /dev/null @@ -1,2 +0,0 @@ ---- -efiSystemPartitionSize: 100MB diff --git a/src/modules/partition/tests/2a-legacy.conf b/src/modules/partition/tests/2a-legacy.conf deleted file mode 100644 index 47111a66fb..0000000000 --- a/src/modules/partition/tests/2a-legacy.conf +++ /dev/null @@ -1,9 +0,0 @@ ---- -# Deprecated alias of efi.mountPoint -efiSystemPartition: "/boot/thisisatest" - -# Deprecated alias of efi.recommendedSize -efiSystemPartitionSize: 75MiB - -# Deprecated alias of efi.label -efiSystemPartitionName: testLabel diff --git a/src/modules/partition/tests/2b-modern.conf b/src/modules/partition/tests/2b-modern.conf deleted file mode 100644 index 5b6a6ddf64..0000000000 --- a/src/modules/partition/tests/2b-modern.conf +++ /dev/null @@ -1,6 +0,0 @@ ---- -efi: - mountPoint: "/boot/thisismodern" - recommendedSize: 80MiB - minimumSize: 65MiB - label: "UEFI" diff --git a/src/modules/partition/tests/2c-mixed.conf b/src/modules/partition/tests/2c-mixed.conf deleted file mode 100644 index f472ebef6b..0000000000 --- a/src/modules/partition/tests/2c-mixed.conf +++ /dev/null @@ -1,7 +0,0 @@ ---- -efi: - mountPoint: "/boot/thisismixed" - minimumSize: 80MiB - -efiSystemPartitionSize: 175MiB -efiSystemPartitionName: legacy diff --git a/src/modules/partition/tests/2d-overlap.conf b/src/modules/partition/tests/2d-overlap.conf deleted file mode 100644 index 9ddfa56df0..0000000000 --- a/src/modules/partition/tests/2d-overlap.conf +++ /dev/null @@ -1,9 +0,0 @@ ---- -efi: - mountPoint: "/boot/thisoverlaps" - minimumSize: 100MiB - recommendedSize: 300MiB - -efiSystemPartition: "/boot/ignored" -efiSystemPartitionSize: 175MiB -efiSystemPartitionName: legacy diff --git a/src/modules/partition/tests/3a-min-too-large.conf b/src/modules/partition/tests/3a-min-too-large.conf deleted file mode 100644 index 096f823d7d..0000000000 --- a/src/modules/partition/tests/3a-min-too-large.conf +++ /dev/null @@ -1,5 +0,0 @@ ---- -efi: - recommendedSize: 133MiB - minimumSize: 200MiB - label: "bigmin" diff --git a/src/modules/partition/tests/AutoMountTests.cpp b/src/modules/partition/tests/AutoMountTests.cpp deleted file mode 100644 index 68c929f44a..0000000000 --- a/src/modules/partition/tests/AutoMountTests.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "jobs/AutoMountManagementJob.h" - -#include "JobQueue.h" -#include "utils/Logger.h" - -#include -#include - -class AutoMountJobTests : public QObject -{ - Q_OBJECT -public: - AutoMountJobTests(); - -private Q_SLOTS: - void testRunThrice(); - void testRunQueue(); -}; - -AutoMountJobTests::AutoMountJobTests() {} - -/* This doesn't really test anything, since automount management - * is supposed to be opaque: the job always returns true. What - * is interesting is the debug output, where the job informs - * about the pointer it holds. - * - * That should output 0, then non-zero, then 0 again. - * - */ -void -AutoMountJobTests::testRunThrice() -{ - Logger::setupLogLevel( Logger::LOGVERBOSE ); - - auto original = Calamares::Partition::automountDisable( true ); - cDebug() << "Got automount info" << Logger::Pointer( original ); - - AutoMountManagementJob j( false ); - QVERIFY( j.exec() ); - QVERIFY( j.exec() ); - QVERIFY( j.exec() ); - - Calamares::Partition::automountRestore( original ); -} - -void -AutoMountJobTests::testRunQueue() -{ - Calamares::JobQueue q; - Calamares::job_ptr jp( new AutoMountManagementJob( false ) ); - QSignalSpy progress( &q, &Calamares::JobQueue::progress ); - QSignalSpy finish( &q, &Calamares::JobQueue::finished ); - QSignalSpy fail( &q, &Calamares::JobQueue::failed ); - - Logger::setupLogLevel( Logger::LOGVERBOSE ); - cDebug() << "Got automount job" << jp; - - QVERIFY( !q.isRunning() ); - q.enqueue( 2, { jp, jp } ); - QVERIFY( !q.isRunning() ); - - QEventLoop loop; - QTimer::singleShot( std::chrono::milliseconds( 100 ), [ &q ]() { q.start(); } ); - QTimer::singleShot( std::chrono::milliseconds( 5000 ), [ &loop ]() { loop.quit(); } ); - connect( &q, &Calamares::JobQueue::finished, &loop, &QEventLoop::quit ); - loop.exec(); - - QCOMPARE( fail.count(), 0 ); - QCOMPARE( finish.count(), 1 ); - // 5 progress: 0% and 100% for each *job* and then 100% overall - QCOMPARE( progress.count(), 5 ); -} - - -QTEST_GUILESS_MAIN( AutoMountJobTests ) - -#include "utils/moc-warnings.h" - -#include "AutoMountTests.moc" diff --git a/src/modules/partition/tests/CMakeLists.txt b/src/modules/partition/tests/CMakeLists.txt deleted file mode 100644 index 1cb4ff7a15..0000000000 --- a/src/modules/partition/tests/CMakeLists.txt +++ /dev/null @@ -1,76 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# -find_package(${qtname} COMPONENTS Gui REQUIRED) - -set(PartitionModule_SOURCE_DIR ..) - -include_directories( - ${${qtname}Gui_INCLUDE_DIRS} - ${PartitionModule_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_BINARY_DIR} -) - -calamares_add_test( - partitionjobtest - SOURCES - PartitionJobTests.cpp - ${PartitionModule_SOURCE_DIR}/core/KPMHelpers.cpp - ${PartitionModule_SOURCE_DIR}/core/PartitionInfo.cpp - ${PartitionModule_SOURCE_DIR}/jobs/CreatePartitionJob.cpp - ${PartitionModule_SOURCE_DIR}/jobs/CreatePartitionTableJob.cpp - ${PartitionModule_SOURCE_DIR}/jobs/DeletePartitionJob.cpp - ${PartitionModule_SOURCE_DIR}/jobs/PartitionJob.cpp - ${PartitionModule_SOURCE_DIR}/jobs/ResizePartitionJob.cpp - LIBRARIES calamares::kpmcore - DEFINITIONS ${_partition_defs} -) - -calamares_add_test( - partitionclearmountsjobtest - SOURCES ${PartitionModule_SOURCE_DIR}/jobs/ClearMountsJob.cpp ClearMountsJobTests.cpp - LIBRARIES calamares::kpmcore - DEFINITIONS ${_partition_defs} -) - -calamares_add_test( - partitioncreatelayoutstest - SOURCES - CreateLayoutsTests.cpp - ${PartitionModule_SOURCE_DIR}/core/KPMHelpers.cpp - ${PartitionModule_SOURCE_DIR}/core/PartitionInfo.cpp - ${PartitionModule_SOURCE_DIR}/core/PartitionLayout.cpp - ${PartitionModule_SOURCE_DIR}/core/PartUtils.cpp - ${PartitionModule_SOURCE_DIR}/core/DeviceModel.cpp - LIBRARIES calamares::kpmcore Calamares::calamaresui - DEFINITIONS ${_partition_defs} -) - -calamares_add_test( - partitionautomounttest - SOURCES ${PartitionModule_SOURCE_DIR}/jobs/AutoMountManagementJob.cpp AutoMountTests.cpp - DEFINITIONS ${_partition_defs} -) - -calamares_add_test( - partitiondevicestest - SOURCES DevicesTests.cpp ${PartitionModule_SOURCE_DIR}/core/DeviceList.cpp - LIBRARIES calamares::kpmcore - DEFINITIONS ${_partition_defs} -) - -calamares_add_test( - partitionconfigtest - SOURCES - ConfigTests.cpp - ${PartitionModule_SOURCE_DIR}/core/DeviceModel.cpp - ${PartitionModule_SOURCE_DIR}/core/PartitionInfo.cpp - ${PartitionModule_SOURCE_DIR}/core/PartUtils.cpp - ${PartitionModule_SOURCE_DIR}/Config.cpp - LIBRARIES calamares::kpmcore Calamares::calamaresui - DEFINITIONS - ${_partition_defs} -) diff --git a/src/modules/partition/tests/ClearMountsJobTests.cpp b/src/modules/partition/tests/ClearMountsJobTests.cpp deleted file mode 100644 index 17565e756c..0000000000 --- a/src/modules/partition/tests/ClearMountsJobTests.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "ClearMountsJobTests.h" - -#include "utils/Logger.h" - -#include - -QTEST_GUILESS_MAIN( ClearMountsJobTests ) - - -/* Not exactly public API */ -QStringList getPartitionsForDevice( const QString& deviceName ); - -/* At one point, the partitions-list was read from /proc/partitions by - * running awk and grep, as below. Check that the current implementation - * matches that crufty one. - * - * Update 2021-11-02: the newer implementation prepends /dev/ to the - * names of the partitions, for simplicity elsewhere, so that needs - * to be added in to the awk(1) program, too. - */ -QStringList -getPartitionsForDevice_other( const QString& deviceName ) -{ - QProcess process; - process.setProgram( "sh" ); - process.setArguments( { "-c", - QString( "echo $(awk '{print \"/dev/\"$4}' /proc/partitions | sed -e '/name/d' -e '/^$/d' " - "-e '/[1-9]/!d' | grep %1)" ) - .arg( deviceName ) } ); - process.start(); - process.waitForFinished(); - - const QString partitions = process.readAllStandardOutput().trimmed(); - if ( partitions.isEmpty() ) - { - return QStringList(); - } - const QStringList partitionsList = partitions.simplified().split( ' ' ); - - return partitionsList; -} - - -ClearMountsJobTests::ClearMountsJobTests() -{ - Logger::setupLogLevel( Logger::LOGDEBUG ); -} - -void -ClearMountsJobTests::testFindPartitions() -{ - QStringList partitions = getPartitionsForDevice( "sda" ); - QStringList other_part = getPartitionsForDevice_other( "sda" ); - - cDebug() << "Initial implementation:" << Logger::DebugList( partitions ); - cDebug() << "Other implementation:" << Logger::DebugList( other_part ); - - QCOMPARE( partitions, other_part ); -} diff --git a/src/modules/partition/tests/ClearMountsJobTests.h b/src/modules/partition/tests/ClearMountsJobTests.h deleted file mode 100644 index 4b13fdc3d1..0000000000 --- a/src/modules/partition/tests/ClearMountsJobTests.h +++ /dev/null @@ -1,25 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef CLEARMOUNTSJOBTESTS_H -#define CLEARMOUNTSJOBTESTS_H - -#include - -class ClearMountsJobTests : public QObject -{ - Q_OBJECT -public: - ClearMountsJobTests(); - -private Q_SLOTS: - void testFindPartitions(); -}; - -#endif diff --git a/src/modules/partition/tests/ConfigTests.cpp b/src/modules/partition/tests/ConfigTests.cpp deleted file mode 100644 index eae912f712..0000000000 --- a/src/modules/partition/tests/ConfigTests.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2023 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "Config.h" - -#include "core/PartUtils.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "utils/Logger.h" -#include "utils/System.h" -#include "utils/Yaml.h" - -#include -#include - -using Calamares::Units::operator""_MiB; - -class ConfigTests : public QObject -{ - Q_OBJECT - -public: - ConfigTests(); - -private Q_SLOTS: - void initTestCase(); - void testEmptyConfig(); - void testLegacySize(); - void testAll(); - void testWeirdConfig(); -}; - -ConfigTests::ConfigTests() = default; - -void -ConfigTests::initTestCase() -{ - Logger::setupLogLevel( Logger::LOGVERBOSE ); - - // Ensure we have a system object, expect it to be a "bogus" one - Calamares::System* system = Calamares::System::instance(); - QVERIFY( system ); - QVERIFY( system->doChroot() ); - - // Ensure we have a system-wide GlobalStorage with /tmp as root - if ( !Calamares::JobQueue::instance() ) - { - cDebug() << "Creating new JobQueue"; - (void)new Calamares::JobQueue(); - } - Calamares::GlobalStorage* gs - = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; - QVERIFY( gs ); -} - - -void -ConfigTests::testEmptyConfig() -{ - Config c( nullptr ); - c.setConfigurationMap( {} ); - - const auto* gs = Calamares::JobQueue::instanceGlobalStorage(); - QVERIFY( gs ); - - QVERIFY( c.initialInstallChoice() == Config::InstallChoice::NoChoice ); - QVERIFY( !gs->value( PartUtils::efiFilesystemRecommendedSizeGSKey() ).isValid() ); // Nothing filled in - QCOMPARE( PartUtils::efiFilesystemRecommendedSize(), 300_MiB ); // Default value - QCOMPARE( PartUtils::efiFilesystemMinimumSize(), 300_MiB ); // Default value - - const auto firmware = gs->value( "firmwareType" ).toString(); - QVERIFY( firmware == "efi" || firmware == "bios" ); - - QCOMPARE( gs->value( "efiSystemPartition" ).toString(), "/boot/efi" ); // Default -} - -void -ConfigTests::testLegacySize() -{ - Config c( nullptr ); - - auto* gs = Calamares::JobQueue::instanceGlobalStorage(); - QVERIFY( gs ); - - - // Config with just one legacy key - { - const auto file = QStringLiteral( BUILD_AS_TEST "/1a-legacy.conf" ); - bool ok = false; - c.setConfigurationMap( Calamares::YAML::load( file, &ok ) ); - - cDebug() << "Tried to load" << file << "success?" << ok; - - QVERIFY( ok ); - - QVERIFY( gs->value( PartUtils::efiFilesystemRecommendedSizeGSKey() ).isValid() ); // Something was filled in - QCOMPARE( PartUtils::efiFilesystemRecommendedSize(), 100_MiB ); // From config - QCOMPARE( PartUtils::efiFilesystemMinimumSize(), 100_MiB ); // Taken from config - } - - // Different legacy key value - { - bool ok = false; - c.setConfigurationMap( Calamares::YAML::load( QStringLiteral( BUILD_AS_TEST "/1b-legacy.conf" ), &ok ) ); - - QVERIFY( ok ); - - QCOMPARE( PartUtils::efiFilesystemRecommendedSize(), 100000000 ); // From config, MB - QCOMPARE( PartUtils::efiFilesystemMinimumSize(), 100000000 ); // Taken from config - } -} - -void -ConfigTests::testAll() -{ - Config c( nullptr ); - - auto* gs = Calamares::JobQueue::instanceGlobalStorage(); - QVERIFY( gs ); - - - // Legacy only - { - gs->clear(); - const auto file = QStringLiteral( BUILD_AS_TEST "/2a-legacy.conf" ); - bool ok = false; - c.setConfigurationMap( Calamares::YAML::load( file, &ok ) ); - - cDebug() << "Tried to load" << file << "success?" << ok; - - QVERIFY( ok ); - - QVERIFY( gs->value( PartUtils::efiFilesystemRecommendedSizeGSKey() ).isValid() ); // Something was filled in - QCOMPARE( PartUtils::efiFilesystemRecommendedSize(), 75_MiB ); // From config - QCOMPARE( PartUtils::efiFilesystemMinimumSize(), 75_MiB ); // No separate setting - - QCOMPARE( gs->value( "efiSystemPartition" ).toString(), QStringLiteral( "/boot/thisisatest" ) ); - QCOMPARE( gs->value( "efiSystemPartitionName" ).toString(), QStringLiteral( "testLabel" ) ); - } - - // Modern only - { - gs->clear(); - bool ok = false; - c.setConfigurationMap( Calamares::YAML::load( QStringLiteral( BUILD_AS_TEST "/2b-modern.conf" ), &ok ) ); - - QVERIFY( ok ); - - QVERIFY( PartUtils::efiFilesystemRecommendedSizeGSKey() != PartUtils::efiFilesystemMinimumSizeGSKey() ); - QCOMPARE( gs->value( PartUtils::efiFilesystemRecommendedSizeGSKey() ).toString(), - QStringLiteral( "83886080" ) ); - QCOMPARE( gs->value( PartUtils::efiFilesystemMinimumSizeGSKey() ).toString(), QStringLiteral( "68157440" ) ); - - QCOMPARE( PartUtils::efiFilesystemRecommendedSize(), 80_MiB ); // From config - QCOMPARE( PartUtils::efiFilesystemMinimumSize(), 65_MiB ); // Taken from config - - QCOMPARE( gs->value( "efiSystemPartition" ).toString(), QStringLiteral( "/boot/thisismodern" ) ); - QCOMPARE( gs->value( "efiSystemPartitionName" ).toString(), QStringLiteral( "UEFI" ) ); - } - - // Mixed settings - { - gs->clear(); - bool ok = false; - c.setConfigurationMap( Calamares::YAML::load( QStringLiteral( BUILD_AS_TEST "/2c-mixed.conf" ), &ok ) ); - - QVERIFY( ok ); - - QCOMPARE( PartUtils::efiFilesystemRecommendedSize(), 175_MiB ); // From config - QCOMPARE( PartUtils::efiFilesystemMinimumSize(), 80_MiB ); // Taken from config - - QCOMPARE( gs->value( "efiSystemPartition" ).toString(), QStringLiteral( "/boot/thisismixed" ) ); - QCOMPARE( gs->value( "efiSystemPartitionName" ).toString(), QStringLiteral( "legacy" ) ); - } - - // Mixed settings with overlap - { - gs->clear(); - bool ok = false; - c.setConfigurationMap( Calamares::YAML::load( QStringLiteral( BUILD_AS_TEST "/2d-overlap.conf" ), &ok ) ); - - QVERIFY( ok ); - - QCOMPARE( PartUtils::efiFilesystemRecommendedSize(), 300_MiB ); // From modern config - QCOMPARE( PartUtils::efiFilesystemMinimumSize(), 100_MiB ); // Taken from modern config, legacy ignored - - QCOMPARE( gs->value( "efiSystemPartition" ).toString(), QStringLiteral( "/boot/thisoverlaps" ) ); - QCOMPARE( gs->value( "efiSystemPartitionName" ).toString(), QStringLiteral( "legacy" ) ); - } -} - -void -ConfigTests::testWeirdConfig() -{ - Config c( nullptr ); - - auto* gs = Calamares::JobQueue::instanceGlobalStorage(); - QVERIFY( gs ); - gs->clear(); - - - // Config with an invalid minimum size - { - const auto file = QStringLiteral( BUILD_AS_TEST "/3a-min-too-large.conf" ); - bool ok = false; - c.setConfigurationMap( Calamares::YAML::load( file, &ok ) ); - - cDebug() << "Tried to load" << file << "success?" << ok; - QVERIFY( ok ); - - QCOMPARE( PartUtils::efiFilesystemRecommendedSize(), 133_MiB ); - QCOMPARE( PartUtils::efiFilesystemMinimumSize(), 133_MiB ); // Config setting was ignored - - QCOMPARE( gs->value( "efiSystemPartitionName" ).toString(), QStringLiteral( "bigmin" ) ); - } -} - - -QTEST_GUILESS_MAIN( ConfigTests ) - -#include "utils/moc-warnings.h" - -#include "ConfigTests.moc" diff --git a/src/modules/partition/tests/CreateLayoutsTests.cpp b/src/modules/partition/tests/CreateLayoutsTests.cpp deleted file mode 100644 index 87a1ea484a..0000000000 --- a/src/modules/partition/tests/CreateLayoutsTests.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 Corentin Noël - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "CreateLayoutsTests.h" - -#include "core/PartitionLayout.h" - -#include "JobQueue.h" -#include "partition/KPMManager.h" -#include "utils/Logger.h" - -#include - -#include - -using namespace Calamares::Units; - -class PartitionTable; -class SmartStatus; - -QTEST_GUILESS_MAIN( CreateLayoutsTests ) - -static Calamares::Partition::KPMManager* kpmcore = nullptr; -static Calamares::JobQueue* jobqueue = nullptr; - -#define LOGICAL_SIZE 512 - -CreateLayoutsTests::CreateLayoutsTests() -{ - Logger::setupLogLevel( Logger::LOGDEBUG ); -} - -void -CreateLayoutsTests::init() -{ - jobqueue = new Calamares::JobQueue( nullptr ); - kpmcore = new Calamares::Partition::KPMManager(); -} - -void -CreateLayoutsTests::cleanup() -{ - delete kpmcore; - delete jobqueue; -} - -void -CreateLayoutsTests::testFixedSizePartition() -{ - PartitionLayout layout = PartitionLayout(); - TestDevice dev( QString( "test" ), LOGICAL_SIZE, 5_GiB / LOGICAL_SIZE ); - PartitionRole role( PartitionRole::Role::Any ); - QList< Partition* > partitions; - - if ( !layout.addEntry( { FileSystem::Type::Ext4, QString( "/" ), QString( "5MiB" ) } ) ) - { - QFAIL( qPrintable( "Unable to create / partition" ) ); - } - - partitions = layout.createPartitions( - static_cast< Device* >( &dev ), 0, dev.totalLogical(), Config::LuksGeneration::Luks1, nullptr, nullptr, role ); - - QCOMPARE( partitions.count(), 1 ); - - QCOMPARE( partitions[ 0 ]->length(), 5_MiB / LOGICAL_SIZE ); -} - -void -CreateLayoutsTests::testPercentSizePartition() -{ - PartitionLayout layout = PartitionLayout(); - TestDevice dev( QString( "test" ), LOGICAL_SIZE, 5_GiB / LOGICAL_SIZE ); - PartitionRole role( PartitionRole::Role::Any ); - QList< Partition* > partitions; - - if ( !layout.addEntry( { FileSystem::Type::Ext4, QString( "/" ), QString( "50%" ) } ) ) - { - QFAIL( qPrintable( "Unable to create / partition" ) ); - } - - partitions = layout.createPartitions( - static_cast< Device* >( &dev ), 0, dev.totalLogical(), Config::LuksGeneration::Luks1, nullptr, nullptr, role ); - - QCOMPARE( partitions.count(), 1 ); - - QCOMPARE( partitions[ 0 ]->length(), ( 5_GiB / 2 ) / LOGICAL_SIZE ); -} - -void -CreateLayoutsTests::testMixedSizePartition() -{ - PartitionLayout layout = PartitionLayout(); - TestDevice dev( QString( "test" ), LOGICAL_SIZE, 5_GiB / LOGICAL_SIZE ); - PartitionRole role( PartitionRole::Role::Any ); - QList< Partition* > partitions; - - if ( !layout.addEntry( { FileSystem::Type::Ext4, QString( "/" ), QString( "5MiB" ) } ) ) - { - QFAIL( qPrintable( "Unable to create / partition" ) ); - } - - if ( !layout.addEntry( { FileSystem::Type::Ext4, QString( "/home" ), QString( "50%" ) } ) ) - { - QFAIL( qPrintable( "Unable to create /home partition" ) ); - } - - if ( !layout.addEntry( { FileSystem::Type::Ext4, QString( "/bkup" ), QString( "50%" ) } ) ) - { - QFAIL( qPrintable( "Unable to create /bkup partition" ) ); - } - - partitions = layout.createPartitions( - static_cast< Device* >( &dev ), 0, dev.totalLogical(), Config::LuksGeneration::Luks1, nullptr, nullptr, role ); - - QCOMPARE( partitions.count(), 3 ); - - QCOMPARE( partitions[ 0 ]->length(), 5_MiB / LOGICAL_SIZE ); - QCOMPARE( partitions[ 1 ]->length(), ( ( 5_GiB - 5_MiB ) / 2 ) / LOGICAL_SIZE ); - QCOMPARE( partitions[ 2 ]->length(), ( ( 5_GiB - 5_MiB ) / 2 ) / LOGICAL_SIZE ); -} - -// TODO: Get a clean way to instantiate a test Device from KPMCore -class DevicePrivate -{ -public: - QString m_Name; - QString m_DeviceNode; - qint64 m_LogicalSectorSize; - qint64 m_TotalLogical; - PartitionTable* m_PartitionTable; - QString m_IconName; - std::shared_ptr< SmartStatus > m_SmartStatus; - Device::Type m_Type; -}; - -TestDevice::TestDevice( const QString& name, const qint64 logicalSectorSize, const qint64 totalLogicalSectors ) - : Device( std::make_shared< DevicePrivate >(), - name, - QString( "node" ), - logicalSectorSize, - totalLogicalSectors, - QString(), - Device::Type::Unknown_Device ) -{ -} - -TestDevice::~TestDevice() {} diff --git a/src/modules/partition/tests/CreateLayoutsTests.h b/src/modules/partition/tests/CreateLayoutsTests.h deleted file mode 100644 index 5953b06a78..0000000000 --- a/src/modules/partition/tests/CreateLayoutsTests.h +++ /dev/null @@ -1,39 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 Corentin Noël - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef CLEARMOUNTSJOBTESTS_H -#define CLEARMOUNTSJOBTESTS_H - -#include "partition/KPMHelper.h" - -#include - -class CreateLayoutsTests : public QObject -{ - Q_OBJECT -public: - CreateLayoutsTests(); - ~CreateLayoutsTests() override = default; - -private Q_SLOTS: - void testFixedSizePartition(); - void testPercentSizePartition(); - void testMixedSizePartition(); - void init(); - void cleanup(); -}; - -class TestDevice : public Device -{ -public: - TestDevice( const QString& name, const qint64 logicalSectorSize, const qint64 totalLogicalSectors ); - ~TestDevice() override; -}; - -#endif diff --git a/src/modules/partition/tests/DevicesTests.cpp b/src/modules/partition/tests/DevicesTests.cpp deleted file mode 100644 index 1f80e2294f..0000000000 --- a/src/modules/partition/tests/DevicesTests.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2021 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "core/DeviceList.h" - -#include "partition/KPMManager.h" -#include "utils/Logger.h" - -#include -#include - -#include -#include - -#include - -#include - -class DevicesTests : public QObject -{ - Q_OBJECT - -public: - DevicesTests(); - -private Q_SLOTS: - void testKPMScanDevices(); - void testPartUtilScanDevices(); - -private: - std::unique_ptr< Calamares::Partition::KPMManager > m_d; - bool m_isRoot = false; -}; - -DevicesTests::DevicesTests() - : m_d( std::make_unique< Calamares::Partition::KPMManager >() ) - , m_isRoot( geteuid() == 0 ) -{ -} - -void -DevicesTests::testKPMScanDevices() -{ - Logger::setupLogLevel( Logger::LOGVERBOSE ); - - cDebug() << "Getting devices via KPMCore"; - CoreBackend* backend = CoreBackendManager::self()->backend(); - QVERIFY( backend ); - auto devices = backend->scanDevices( ScanFlag( ~0 ) ); // These flags try to get "all" - cDebug() << Logger::SubEntry << "Done getting devices."; - - if ( !m_isRoot ) - { - QEXPECT_FAIL( "", "Test invalid when not root", Continue ); - } - QVERIFY( devices.count() > 0 ); -} - -void -DevicesTests::testPartUtilScanDevices() -{ - Logger::setupLogLevel( Logger::LOGVERBOSE ); - - cDebug() << "Getting devices via PartUtils"; - auto devices = PartUtils::getDevices(); - cDebug() << Logger::SubEntry << "Done getting devices."; - - if ( !m_isRoot ) - { - QEXPECT_FAIL( "", "Test invalid when not root", Continue ); - } - QVERIFY( devices.count() > 0 ); -} - -QTEST_GUILESS_MAIN( DevicesTests ) - -#include "utils/moc-warnings.h" - -#include "DevicesTests.moc" diff --git a/src/modules/partition/tests/PartitionJobTests.cpp b/src/modules/partition/tests/PartitionJobTests.cpp deleted file mode 100644 index 24686b57bd..0000000000 --- a/src/modules/partition/tests/PartitionJobTests.cpp +++ /dev/null @@ -1,443 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2017, 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "PartitionJobTests.h" - -#include "core/KPMHelpers.h" -#include "jobs/CreatePartitionJob.h" -#include "jobs/CreatePartitionTableJob.h" -#include "jobs/ResizePartitionJob.h" - -#include "partition/KPMHelper.h" -#include "partition/KPMManager.h" -#include "partition/PartitionQuery.h" -#include "utils/Logger.h" -#include "utils/Units.h" - -#include -#include -#include - -QTEST_GUILESS_MAIN( PartitionJobTests ) - -using Calamares::job_ptr; -using Calamares::JobList; -using namespace Calamares::Units; - -class PartitionMounter -{ -public: - PartitionMounter( const QString& devicePath ) - : m_mountPointDir( "calamares-partitiontests-mountpoint" ) - { - QStringList args = QStringList() << devicePath << m_mountPointDir.path(); - int ret = QProcess::execute( "mount", args ); - m_mounted = ret == 0; - QCOMPARE( ret, 0 ); - } - - ~PartitionMounter() - { - if ( !m_mounted ) - { - return; - } - int ret = QProcess::execute( "umount", QStringList() << m_mountPointDir.path() ); - QCOMPARE( ret, 0 ); - } - - QString mountPoint() const { return m_mounted ? m_mountPointDir.path() : QString(); } - -private: - QString m_devicePath; - QTemporaryDir m_mountPointDir; - bool m_mounted; -}; - -/// @brief Generate random data of given @p size as a QByteArray -static QByteArray -generateTestData( qint64 size ) -{ - QByteArray ba; - ba.resize( static_cast< int >( size ) ); - // Fill the array explicitly to keep Valgrind happy - for ( auto it = ba.data(); it < ba.data() + size; ++it ) - { - *it = char( rand() & 0xff ); - } - return ba; -} - -static void -writeFile( const QString& path, const QByteArray data ) -{ - QFile file( path ); - QVERIFY( file.open( QIODevice::WriteOnly ) ); - - const char* ptr = data.constData(); - const char* end = data.constData() + data.size(); - const qint64 chunkSize = 16384; - - while ( ptr < end ) - { - qint64 count = file.write( ptr, chunkSize ); - if ( count < 0 ) - { - QString msg = QString( "Writing file failed. Only %1 bytes written out of %2. Error: '%3'." ) - .arg( ptr - data.constData() ) - .arg( data.size() ) - .arg( file.errorString() ); - QFAIL( qPrintable( msg ) ); - } - ptr += count; - } -} - -static ::Partition* -firstFreePartition( PartitionNode* parent ) -{ - for ( auto child : parent->children() ) - { - if ( Calamares::Partition::isPartitionFreeSpace( child ) ) - { - return child; - } - } - return nullptr; -} - -//- QueueRunner --------------------------------------------------------------- -QueueRunner::QueueRunner( Calamares::JobQueue* queue ) - : m_queue( queue ) - , m_finished( false ) // Same initalizations as in ::run() - , m_success( true ) -{ - connect( m_queue, &Calamares::JobQueue::finished, this, &QueueRunner::onFinished ); - connect( m_queue, &Calamares::JobQueue::failed, this, &QueueRunner::onFailed ); -} - -QueueRunner::~QueueRunner() -{ - // Nothing to do. We don't own the queue, and disconnect happens automatically -} - -bool -QueueRunner::run() -{ - m_finished = false; - m_success = true; - m_queue->start(); - QEventLoop loop; - while ( !m_finished ) - { - loop.processEvents(); - } - return m_success; -} - -void -QueueRunner::onFinished() -{ - m_finished = true; -} - -void -QueueRunner::onFailed( const QString& message, const QString& details ) -{ - m_success = false; - QString msg = message + "\ndetails: " + details; - QFAIL( qPrintable( msg ) ); -} - -static Calamares::Partition::KPMManager* kpmcore = nullptr; - -//- PartitionJobTests ------------------------------------------------------------------ -PartitionJobTests::PartitionJobTests() - : m_runner( &m_queue ) -{ -} - -void -PartitionJobTests::initTestCase() -{ - QString devicePath = qgetenv( "CALAMARES_TEST_DISK" ); - if ( devicePath.isEmpty() ) - { - // The 0 is to keep the macro parameters happy - QSKIP( "Skipping test, CALAMARES_TEST_DISK is not set. It should point to a disk which can be safely formatted", - 0 ); - } - - kpmcore = new Calamares::Partition::KPMManager(); - FileSystemFactory::init(); - - refreshDevice(); -} - -void -PartitionJobTests::cleanupTestCase() -{ - delete kpmcore; -} - -void -PartitionJobTests::refreshDevice() -{ - QString devicePath = qgetenv( "CALAMARES_TEST_DISK" ); - m_device.reset( kpmcore->backend()->scanDevice( devicePath ) ); - QVERIFY( !m_device.isNull() ); -} - -void -PartitionJobTests::testPartitionTable() -{ - queuePartitionTableCreation( PartitionTable::msdos ); - QVERIFY( m_runner.run() ); - QVERIFY( m_device->partitionTable() ); - QVERIFY( firstFreePartition( m_device->partitionTable() ) ); - - queuePartitionTableCreation( PartitionTable::gpt ); - QVERIFY( m_runner.run() ); - QVERIFY( m_device->partitionTable() ); - QVERIFY( firstFreePartition( m_device->partitionTable() ) ); -} - -void -PartitionJobTests::queuePartitionTableCreation( PartitionTable::TableType type ) -{ - auto job = new CreatePartitionTableJob( m_device.data(), type ); - job->updatePreview(); - m_queue.enqueue( 1, JobList() << job_ptr( job ) ); -} - -CreatePartitionJob* -PartitionJobTests::newCreatePartitionJob( Partition* freeSpacePartition, - PartitionRole role, - FileSystem::Type type, - qint64 size ) -{ - Q_ASSERT( freeSpacePartition ); - - qint64 firstSector = freeSpacePartition->firstSector(); - qint64 lastSector; - - if ( size > 0 ) - { - lastSector = firstSector + size / m_device->logicalSize(); - } - else - { - lastSector = freeSpacePartition->lastSector(); - } - FileSystem* fs = FileSystemFactory::create( type, firstSector, lastSector, m_device->logicalSize() ); - - Partition* partition = new Partition( freeSpacePartition->parent(), - *m_device, - role, - fs, - firstSector, - lastSector, - QString() /* path */, - KPM_PARTITION_FLAG( None ) /* availableFlags */, - QString() /* mountPoint */, - false /* mounted */, - KPM_PARTITION_FLAG( None ) /* activeFlags */, - KPM_PARTITION_STATE( New ) ); - return new CreatePartitionJob( m_device.data(), partition ); -} - -void -PartitionJobTests::testCreatePartition() -{ - queuePartitionTableCreation( PartitionTable::gpt ); - CreatePartitionJob* job; - Partition* freePartition; - - freePartition = firstFreePartition( m_device->partitionTable() ); - QVERIFY( freePartition ); - job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Primary ), FileSystem::Ext4, 1_MiB ); - Partition* partition1 = job->partition(); - QVERIFY( partition1 ); - job->updatePreview(); - m_queue.enqueue( 1, JobList() << job_ptr( job ) ); - - freePartition = firstFreePartition( m_device->partitionTable() ); - QVERIFY( freePartition ); - job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Primary ), FileSystem::LinuxSwap, 1_MiB ); - Partition* partition2 = job->partition(); - QVERIFY( partition2 ); - job->updatePreview(); - m_queue.enqueue( 1, JobList() << job_ptr( job ) ); - - freePartition = firstFreePartition( m_device->partitionTable() ); - QVERIFY( freePartition ); - job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Primary ), FileSystem::Fat32, 1_MiB ); - Partition* partition3 = job->partition(); - QVERIFY( partition3 ); - job->updatePreview(); - m_queue.enqueue( 1, JobList() << job_ptr( job ) ); - - QVERIFY( m_runner.run() ); - - // Check partitionPath has been set. It is not known until the job has - // executed. - QString devicePath = m_device->deviceNode(); - QCOMPARE( partition1->partitionPath(), devicePath + "1" ); - QCOMPARE( partition2->partitionPath(), devicePath + "2" ); - QCOMPARE( partition3->partitionPath(), devicePath + "3" ); -} - -void -PartitionJobTests::testCreatePartitionExtended() -{ - queuePartitionTableCreation( PartitionTable::msdos ); - CreatePartitionJob* job; - Partition* freePartition; - - freePartition = firstFreePartition( m_device->partitionTable() ); - QVERIFY( freePartition ); - job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Primary ), FileSystem::Ext4, 10_MiB ); - Partition* partition1 = job->partition(); - QVERIFY( partition1 ); - job->updatePreview(); - m_queue.enqueue( 1, JobList() << job_ptr( job ) ); - - freePartition = firstFreePartition( m_device->partitionTable() ); - QVERIFY( freePartition ); - job = newCreatePartitionJob( - freePartition, PartitionRole( PartitionRole::Extended ), FileSystem::Extended, 10_MiB ); - job->updatePreview(); - m_queue.enqueue( 1, JobList() << job_ptr( job ) ); - Partition* extendedPartition = job->partition(); - - freePartition = firstFreePartition( extendedPartition ); - QVERIFY( freePartition ); - job = newCreatePartitionJob( freePartition, PartitionRole( PartitionRole::Logical ), FileSystem::Ext4, 0 ); - Partition* partition2 = job->partition(); - QVERIFY( partition2 ); - job->updatePreview(); - m_queue.enqueue( 1, JobList() << job_ptr( job ) ); - - QVERIFY( m_runner.run() ); - - // Check partitionPath has been set. It is not known until the job has - // executed. - QString devicePath = m_device->deviceNode(); - QCOMPARE( partition1->partitionPath(), devicePath + "1" ); - QCOMPARE( extendedPartition->partitionPath(), devicePath + "2" ); - QCOMPARE( partition2->partitionPath(), devicePath + "5" ); -} - -void -PartitionJobTests::testResizePartition_data() -{ - QTest::addColumn< unsigned int >( "oldStartMiB" ); - QTest::addColumn< unsigned int >( "oldSizeMiB" ); - QTest::addColumn< unsigned int >( "newStartMiB" ); - QTest::addColumn< unsigned int >( "newSizeMiB" ); - - QTest::newRow( "grow" ) << 10 << 50 << 10 << 70; - QTest::newRow( "shrink" ) << 10 << 70 << 10 << 50; - QTest::newRow( "moveLeft" ) << 10 << 50 << 8 << 50; - QTest::newRow( "moveRight" ) << 10 << 50 << 12 << 50; -} - -void -PartitionJobTests::testResizePartition() -{ - QFETCH( unsigned int, oldStartMiB ); - QFETCH( unsigned int, oldSizeMiB ); - QFETCH( unsigned int, newStartMiB ); - QFETCH( unsigned int, newSizeMiB ); - - const qint64 sectorsPerMiB = 1_MiB / m_device->logicalSize(); - - qint64 oldFirst = sectorsPerMiB * oldStartMiB; - qint64 oldLast = oldFirst + sectorsPerMiB * oldSizeMiB - 1; - qint64 newFirst = sectorsPerMiB * newStartMiB; - qint64 newLast = newFirst + sectorsPerMiB * newSizeMiB - 1; - - // Make the test data file smaller than the full size of the partition to - // accomodate for the file system overhead - const unsigned long long minSizeMiB = qMin( oldSizeMiB, newSizeMiB ); - const QByteArray testData = generateTestData( Calamares::MiBtoBytes( minSizeMiB ) * 3 / 4 ); - const QString testName = "test.data"; - - // Setup: create the test partition - { - queuePartitionTableCreation( PartitionTable::msdos ); - - Partition* freePartition = firstFreePartition( m_device->partitionTable() ); - QVERIFY( freePartition ); - Partition* partition = KPMHelpers::createNewPartition( freePartition->parent(), - *m_device, - PartitionRole( PartitionRole::Primary ), - FileSystem::Ext4, - QStringLiteral( "testp" ), - oldFirst, - oldLast, - KPM_PARTITION_FLAG( None ) ); - CreatePartitionJob* job = new CreatePartitionJob( m_device.data(), partition ); - job->updatePreview(); - m_queue.enqueue( 1, JobList() << job_ptr( job ) ); - - QVERIFY( m_runner.run() ); - } - - { - // Write a test file in the partition - refreshDevice(); - QVERIFY( m_device->partitionTable() ); - Partition* partition - = m_device->partitionTable()->findPartitionBySector( oldFirst, PartitionRole( PartitionRole::Primary ) ); - QVERIFY( partition ); - QCOMPARE( partition->firstSector(), oldFirst ); - QCOMPARE( partition->lastSector(), oldLast ); - { - PartitionMounter mounter( partition->partitionPath() ); - QString mountPoint = mounter.mountPoint(); - QVERIFY( !mountPoint.isEmpty() ); - writeFile( mountPoint + '/' + testName, testData ); - } - - // Resize - ResizePartitionJob* job = new ResizePartitionJob( m_device.data(), partition, newFirst, newLast ); - job->updatePreview(); - m_queue.enqueue( 1, JobList() << job_ptr( job ) ); - QVERIFY( m_runner.run() ); - - QCOMPARE( partition->firstSector(), newFirst ); - QCOMPARE( partition->lastSector(), newLast ); - } - - // Test - { - refreshDevice(); - QVERIFY( m_device->partitionTable() ); - Partition* partition - = m_device->partitionTable()->findPartitionBySector( newFirst, PartitionRole( PartitionRole::Primary ) ); - QVERIFY( partition ); - QCOMPARE( partition->firstSector(), newFirst ); - QCOMPARE( partition->lastSector(), newLast ); - QCOMPARE( partition->fileSystem().firstSector(), newFirst ); - QCOMPARE( partition->fileSystem().lastSector(), newLast ); - - PartitionMounter mounter( partition->partitionPath() ); - QString mountPoint = mounter.mountPoint(); - QVERIFY( !mountPoint.isEmpty() ); - { - QFile file( mountPoint + '/' + testName ); - QVERIFY( file.open( QIODevice::ReadOnly ) ); - QByteArray outData = file.readAll(); - QCOMPARE( outData.size(), testData.size() ); - QCOMPARE( outData, testData ); - } - } -} diff --git a/src/modules/partition/tests/PartitionJobTests.h b/src/modules/partition/tests/PartitionJobTests.h deleted file mode 100644 index 9e4455ddc7..0000000000 --- a/src/modules/partition/tests/PartitionJobTests.h +++ /dev/null @@ -1,66 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef PARTITIONJOBTESTS_H -#define PARTITIONJOBTESTS_H - -#include "JobQueue.h" - -#include "partition/KPMHelper.h" - -// Qt -#include -#include - -class QueueRunner : public QObject -{ -public: - QueueRunner( Calamares::JobQueue* queue ); - ~QueueRunner() override; - - /** - * Synchronously runs the queue. Returns true on success - */ - bool run(); - -private: - void onFailed( const QString& message, const QString& details ); - void onFinished(); - Calamares::JobQueue* m_queue; - bool m_finished; - bool m_success; -}; - -class PartitionJobTests : public QObject -{ - Q_OBJECT -public: - PartitionJobTests(); - -private Q_SLOTS: - void initTestCase(); - void cleanupTestCase(); - void testPartitionTable(); - void testCreatePartition(); - void testCreatePartitionExtended(); - void testResizePartition_data(); - void testResizePartition(); - -private: - QScopedPointer< Device > m_device; - Calamares::JobQueue m_queue; - QueueRunner m_runner; - - void queuePartitionTableCreation( PartitionTable::TableType type ); - CreatePartitionJob* - newCreatePartitionJob( Partition* freeSpacePartition, PartitionRole, FileSystem::Type type, qint64 size ); - void refreshDevice(); -}; - -#endif /* PARTITIONJOBTESTS_H */ diff --git a/src/modules/plasmalnf/CMakeLists.txt b/src/modules/plasmalnf/CMakeLists.txt deleted file mode 100644 index 50cb630f2c..0000000000 --- a/src/modules/plasmalnf/CMakeLists.txt +++ /dev/null @@ -1,53 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-FileCopyrightText: 2024 Anke Boersma -# SPDX-License-Identifier: BSD-2-Clause -# - -# Requires a sufficiently recent Plasma framework, but also -# needs a runtime support component (which we don't test for). - -if(WITH_QT6) - set(PLASMA_VERSION "5.93.0") - set(_plasma_libraries "Plasma::Plasma") - set(_plasma_name "Plasma") - find_package(${kfname} ${KF_VERSION} QUIET COMPONENTS Config Package) - find_package(Plasma ${PLASMA_VERSION}) -else() - set(_plasma_libraries "${kfname}::Plasma") - set(_plasma_name "KF5Plasma") - find_package(${kfname} ${KF_VERSION} QUIET COMPONENTS Config Plasma Package) -endif() - -set_package_properties(${kfname}Config PROPERTIES PURPOSE "For finding default Plasma Look-and-Feel") -set_package_properties(${_plasma_name} PROPERTIES PURPOSE "For Plasma Look-and-Feel selection") -set_package_properties(${kfname}Package PROPERTIES PURPOSE "For Plasma Look-and-Feel selection") - -if(${_plasma_name}_FOUND AND ${kfname}Package_FOUND) - calamares_add_plugin(plasmalnf - TYPE viewmodule - EXPORT_MACRO PLUGINDLLEXPORT_PRO - COMPILE_DEFINITIONS - ${option_defs} - SOURCES - Config.cpp - PlasmaLnfViewStep.cpp - PlasmaLnfPage.cpp - PlasmaLnfJob.cpp - ThemeInfo.cpp - RESOURCES - page_plasmalnf.qrc - UI - page_plasmalnf.ui - LINK_PRIVATE_LIBRARIES - ${kfname}::Package - ${_plasma_libraries} - SHARED_LIB - ) - if(${kfname}Config_FOUND) - target_compile_definitions(calamares_viewmodule_plasmalnf PRIVATE WITH_KCONFIG) - endif() -else() - calamares_skip_module( "plasmalnf (missing requirements)" ) -endif() diff --git a/src/modules/plasmalnf/Config.cpp b/src/modules/plasmalnf/Config.cpp deleted file mode 100644 index 052e56950a..0000000000 --- a/src/modules/plasmalnf/Config.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "Config.h" - -#include "PlasmaLnfJob.h" -#include "ThemeInfo.h" - -#include "compat/Variant.h" -#include "utils/Logger.h" -#include "utils/System.h" -#include "utils/Variant.h" - -#ifdef WITH_KCONFIG -#include -#include -#endif - -#include - -static QString -currentPlasmaTheme() -{ -#ifdef WITH_KCONFIG - KConfigGroup cg( KSharedConfig::openConfig( QStringLiteral( "kdeglobals" ) ), "KDE" ); - return cg.readEntry( "LookAndFeelPackage", QString() ); -#else - cWarning() << "No KConfig support, cannot determine Plasma theme."; - return QString(); -#endif -} - -Config::Config( QObject* parent ) - : QObject( parent ) - , m_themeModel( new ThemesModel( this ) ) -{ - auto* filter = new QSortFilterProxyModel( m_themeModel ); - filter->setFilterRole( ThemesModel::ShownRole ); - filter->setFilterFixedString( QStringLiteral( "true" ) ); - filter->setSourceModel( m_themeModel ); - filter->setSortRole( ThemesModel::LabelRole ); - filter->sort( 0 ); - - m_filteredModel = filter; -} - -void -Config::setConfigurationMap( const QVariantMap& configurationMap ) -{ - m_lnfPath = Calamares::getString( configurationMap, "lnftool" ); - - if ( m_lnfPath.isEmpty() ) - { - cWarning() << "no lnftool given for plasmalnf module."; - } - - m_liveUser = Calamares::getString( configurationMap, "liveuser" ); - - QString preselect = Calamares::getString( configurationMap, "preselect" ); - if ( preselect == QStringLiteral( "*" ) ) - { - preselect = currentPlasmaTheme(); - } - m_preselectThemeId = preselect; - - if ( configurationMap.contains( "themes" ) - && Calamares::typeOf( configurationMap.value( "themes" ) ) == Calamares::StringVariantType ) - { - QMap< QString, QString > listedThemes; - auto themeList = configurationMap.value( "themes" ).toList(); - // Create the ThemInfo objects for the listed themes; information - // about the themes from Plasma (e.g. human-readable name and description) - // are filled in by update_names() in PlasmaLnfPage. - for ( const auto& i : themeList ) - { - if ( Calamares::typeOf( i ) == Calamares::MapVariantType ) - { - auto iv = i.toMap(); - listedThemes.insert( iv.value( "theme" ).toString(), iv.value( "image" ).toString() ); - } - else if ( Calamares::typeOf( i ) == Calamares::StringVariantType ) - { - listedThemes.insert( i.toString(), QString() ); - } - } - - if ( listedThemes.count() == 1 ) - { - cWarning() << "only one theme enabled in plasmalnf"; - } - m_themeModel->setThemeImage( listedThemes ); - - bool showAll = Calamares::getBool( configurationMap, "showAll", false ); - if ( !listedThemes.isEmpty() && !showAll ) - { - m_themeModel->showOnlyThemes( listedThemes ); - } - } - - m_themeModel->select( m_preselectThemeId ); -} - -Calamares::JobList -Config::createJobs() const -{ - Calamares::JobList l; - - cDebug() << "Creating Plasma LNF jobs .."; - if ( !theme().isEmpty() ) - { - if ( !lnfToolPath().isEmpty() ) - { - l.append( Calamares::job_ptr( new PlasmaLnfJob( lnfToolPath(), theme() ) ) ); - } - else - { - cWarning() << "no lnftool given for plasmalnf module."; - } - } - return l; -} - -void -Config::setTheme( const QString& id ) -{ - if ( m_themeId == id ) - { - return; - } - - m_themeId = id; - if ( lnfToolPath().isEmpty() ) - { - cWarning() << "no lnftool given for plasmalnf module."; - } - else - { - QStringList command; - if ( !m_liveUser.isEmpty() ) - { - command << "sudo" - << "-E" - << "-H" - << "-u" << m_liveUser; - } - command << lnfToolPath() << "--resetLayout" - << "--apply" << id; - auto r = Calamares::System::instance()->runCommand( command, std::chrono::seconds( 10 ) ); - - if ( r.getExitCode() ) - { - cWarning() << "Failed (" << r.getExitCode() << ')'; - } - else - { - cDebug() << "Plasma look-and-feel applied" << id; - } - } - m_themeModel->select( id ); - emit themeChanged( id ); -} diff --git a/src/modules/plasmalnf/Config.h b/src/modules/plasmalnf/Config.h deleted file mode 100644 index aafdf64180..0000000000 --- a/src/modules/plasmalnf/Config.h +++ /dev/null @@ -1,77 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef PLASMALNF_CONFIG_H -#define PLASMALNF_CONFIG_H - -#include "Job.h" - -#include "ThemeInfo.h" - -#include - -class Config : public QObject -{ - Q_OBJECT - - Q_PROPERTY( QString preselectedTheme READ preselectedTheme CONSTANT ) - Q_PROPERTY( QString theme READ theme WRITE setTheme NOTIFY themeChanged ) - Q_PROPERTY( QAbstractItemModel* themeModel READ themeModel CONSTANT ) - -public: - Config( QObject* parent = nullptr ); - virtual ~Config() override = default; // QObject cleans up the model pointer - - void setConfigurationMap( const QVariantMap& ); - Calamares::JobList createJobs() const; - - /** @brief Full path to the lookandfeeltool (if it exists) - * - * This can be configured, or defaults to `lookandfeeltool` to find - * it in $PATH. - */ - QString lnfToolPath() const { return m_lnfPath; } - /** @brief For OEM mode, the name of the (current) live user - * - */ - QString liveUser() const { return m_liveUser; } - - /** @brief The id (in reverse-DNS notation) of the current theme. - */ - QString theme() const { return m_themeId; } - - /** @brief The theme we start with - * - * This can be configured, or is taken from the live environment - * if the environment is (also) KDE Plasma. - */ - QString preselectedTheme() const { return m_preselectThemeId; } - - /** @brief The (list) model of available themes. - */ - QAbstractItemModel* themeModel() const { return m_filteredModel; } - -public slots: - void setTheme( const QString& id ); - -signals: - void themeChanged( const QString& id ); - -private: - QString m_lnfPath; // Path to the lnf tool - QString m_liveUser; // Name of the live user (for OEM mode) - - QString m_preselectThemeId; - QString m_themeId; // Id of selected theme - - QAbstractItemModel* m_filteredModel = nullptr; - ThemesModel* m_themeModel = nullptr; -}; - -#endif diff --git a/src/modules/plasmalnf/PlasmaLnfJob.cpp b/src/modules/plasmalnf/PlasmaLnfJob.cpp deleted file mode 100644 index 4672e34781..0000000000 --- a/src/modules/plasmalnf/PlasmaLnfJob.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2017 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "PlasmaLnfJob.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "utils/Logger.h" -#include "utils/System.h" - -#ifdef WITH_KCONFIG -#include -#include -#endif - -PlasmaLnfJob::PlasmaLnfJob( const QString& lnfPath, const QString& id ) - : m_lnfPath( lnfPath ) - , m_id( id ) -{ -} - -PlasmaLnfJob::~PlasmaLnfJob() {} - -QString -PlasmaLnfJob::prettyName() const -{ - return tr( "Applying Plasma Look-and-Feel…", "@status" ); -} - -Calamares::JobResult -PlasmaLnfJob::exec() -{ - auto* system = Calamares::System::instance(); - auto* gs = Calamares::JobQueue::instance()->globalStorage(); - - QStringList command( { "sudo", - "-E", - "-H", - "-u", - gs->value( "username" ).toString(), - m_lnfPath, - "-platform", - "minimal", - "--resetLayout", - "--apply", - m_id } ); - - int r = system->targetEnvCall( command ); - if ( r ) - { - return Calamares::JobResult::error( tr( "Could not select KDE Plasma Look-and-Feel package" ), - tr( "Could not select KDE Plasma Look-and-Feel package" ) ); - } - -#ifdef WITH_KCONFIG - // This is a workaround for lookandfeeltool **not** writing - // the LookAndFeelPackage key in kdeglobals; this happens - // with the lnftool and Plasma 5.20 (possibly other combinations - // as well). - QString targetConfig = system->targetPath( "/home/" + gs->value( "username" ).toString() + "/.config/kdeglobals" ); - KConfigGroup cg( KSharedConfig::openConfig( targetConfig ), "KDE" ); - cg.writeEntry( "LookAndFeelPackage", m_id ); -#endif - - return Calamares::JobResult::ok(); -} diff --git a/src/modules/plasmalnf/PlasmaLnfJob.h b/src/modules/plasmalnf/PlasmaLnfJob.h deleted file mode 100644 index 4eaf810140..0000000000 --- a/src/modules/plasmalnf/PlasmaLnfJob.h +++ /dev/null @@ -1,35 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2017 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef PLASMALNFJOB_H -#define PLASMALNFJOB_H - -#include -#include - -#include "Job.h" - -class PlasmaLnfJob : public Calamares::Job -{ - Q_OBJECT - -public: - explicit PlasmaLnfJob( const QString& lnfPath, const QString& id ); - ~PlasmaLnfJob() override; - - QString prettyName() const override; - - Calamares::JobResult exec() override; - -private: - QString m_lnfPath; - QString m_id; -}; - -#endif // PLASMALNFJOB_H diff --git a/src/modules/plasmalnf/PlasmaLnfPage.cpp b/src/modules/plasmalnf/PlasmaLnfPage.cpp deleted file mode 100644 index 3665058d41..0000000000 --- a/src/modules/plasmalnf/PlasmaLnfPage.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2017-2018 Adriaan de Groot - * SPDX-FileCopyrightText: 2019 Collabora Ltd - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "PlasmaLnfPage.h" - -#include "Config.h" -#include "ui_page_plasmalnf.h" - -#include "Settings.h" -#include "utils/Logger.h" -#include "utils/Retranslator.h" - -#include -#include -#include - -class ThemeDelegate : public QStyledItemDelegate -{ -public: - using QStyledItemDelegate::QStyledItemDelegate; - - void paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const override; - // The size of the item is constant - QSize sizeHint( const QStyleOptionViewItem&, const QModelIndex& ) const override; -}; - -QSize -ThemeDelegate::sizeHint( const QStyleOptionViewItem&, const QModelIndex& ) const -{ - QSize image( ThemesModel::imageSize() ); - return { 3 * image.width(), image.height() }; -} - -void -ThemeDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const -{ - auto label = index.data( ThemesModel::LabelRole ).toString(); - auto description = index.data( ThemesModel::DescriptionRole ).toString(); - auto selected = index.data( ThemesModel::SelectedRole ).toBool() ? QStyle::State_On : QStyle::State_Off; - auto image_v = index.data( ThemesModel::ImageRole ); - QPixmap image = image_v.canConvert< QPixmap >() ? qvariant_cast< QPixmap >( image_v ) : QPixmap(); - - // The delegate paints three "columns", each of which takes 1/3 - // of the space: label, description and screenshot. - QRect labelRect( option.rect ); - labelRect.setWidth( labelRect.width() / 3 ); - - QStyleOptionButton rbOption; - rbOption.state |= QStyle::State_Enabled | selected; - rbOption.rect = labelRect; - rbOption.text = label; - option.widget->style()->drawControl( QStyle::CE_RadioButton, &rbOption, painter, option.widget ); - - labelRect.moveLeft( labelRect.width() ); - option.widget->style()->drawItemText( - painter, labelRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextWordWrap, option.palette, false, description ); - - labelRect.moveLeft( 2 * labelRect.width() ); - option.widget->style()->drawItemPixmap( painter, labelRect, Qt::AlignHCenter | Qt::AlignVCenter, image ); -} - - -PlasmaLnfPage::PlasmaLnfPage( Config* config, QWidget* parent ) - : QWidget( parent ) - , ui( new Ui::PlasmaLnfPage ) - , m_config( config ) -{ - ui->setupUi( this ); - CALAMARES_RETRANSLATE( { - ui->retranslateUi( this ); - if ( Calamares::Settings::instance()->isSetupMode() ) - { - ui->generalExplanation->setText( tr( "Please choose a look-and-feel for the KDE Plasma Desktop. " - "You can also skip this step and configure the look-and-feel " - "once the system is set up. Clicking on a look-and-feel " - "selection will give you a live preview of that look-and-feel." ) ); - } - else - { - ui->generalExplanation->setText( tr( "Please choose a look-and-feel for the KDE Plasma Desktop. " - "You can also skip this step and configure the look-and-feel " - "once the system is installed. Clicking on a look-and-feel " - "selection will give you a live preview of that look-and-feel." ) ); - } - } ); - - auto* view = new QListView( this ); - view->setModel( m_config->themeModel() ); - view->setItemDelegate( new ThemeDelegate( view ) ); - view->setUniformItemSizes( true ); - view->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ); - ui->verticalLayout->addWidget( view ); - - connect( view->selectionModel(), - &QItemSelectionModel::selectionChanged, - [ this ]( const QItemSelection& selected, const QItemSelection& ) - { - auto i = selected.indexes(); - if ( !i.isEmpty() ) - { - auto row = i.first().row(); - auto* model = m_config->themeModel(); - auto id = model->data( model->index( row, 0 ), ThemesModel::KeyRole ).toString(); - if ( !id.isEmpty() ) - { - m_config->setTheme( id ); - } - } - } ); -} diff --git a/src/modules/plasmalnf/PlasmaLnfPage.h b/src/modules/plasmalnf/PlasmaLnfPage.h deleted file mode 100644 index 24813239a7..0000000000 --- a/src/modules/plasmalnf/PlasmaLnfPage.h +++ /dev/null @@ -1,39 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2017-2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef PLASMALNFPAGE_H -#define PLASMALNFPAGE_H - -#include - -namespace Ui -{ -class PlasmaLnfPage; -} // namespace Ui - -class Config; - -/** @brief Page for selecting a Plasma Look-and-Feel theme. - * - * You must call setEnabledThemes -- either overload -- once - * to get the selection widgets. Note that calling that with - * an empty list will result in zero (0) selectable themes. - */ -class PlasmaLnfPage : public QWidget -{ - Q_OBJECT -public: - explicit PlasmaLnfPage( Config* config, QWidget* parent = nullptr ); - -private: - Ui::PlasmaLnfPage* ui; - Config* m_config; -}; - -#endif //PLASMALNFPAGE_H diff --git a/src/modules/plasmalnf/PlasmaLnfViewStep.cpp b/src/modules/plasmalnf/PlasmaLnfViewStep.cpp deleted file mode 100644 index 4f86758eea..0000000000 --- a/src/modules/plasmalnf/PlasmaLnfViewStep.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2017-2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ -#include "PlasmaLnfViewStep.h" - -#include "Config.h" -#include "PlasmaLnfPage.h" -#include "ThemeInfo.h" - -#include "utils/Logger.h" -#include "utils/Variant.h" - -#include - -CALAMARES_PLUGIN_FACTORY_DEFINITION( PlasmaLnfViewStepFactory, registerPlugin< PlasmaLnfViewStep >(); ) - -PlasmaLnfViewStep::PlasmaLnfViewStep( QObject* parent ) - : Calamares::ViewStep( parent ) - , m_config( new Config( this ) ) - , m_widget( new PlasmaLnfPage( m_config ) ) -{ - emit nextStatusChanged( false ); -} - - -PlasmaLnfViewStep::~PlasmaLnfViewStep() -{ - if ( m_widget && m_widget->parent() == nullptr ) - { - m_widget->deleteLater(); - } -} - - -QString -PlasmaLnfViewStep::prettyName() const -{ - return tr( "Look-and-Feel", "@label" ); -} - - -QWidget* -PlasmaLnfViewStep::widget() -{ - return m_widget; -} - - -bool -PlasmaLnfViewStep::isNextEnabled() const -{ - return true; -} - - -bool -PlasmaLnfViewStep::isBackEnabled() const -{ - return true; -} - - -bool -PlasmaLnfViewStep::isAtBeginning() const -{ - return true; -} - - -bool -PlasmaLnfViewStep::isAtEnd() const -{ - return true; -} - - -void -PlasmaLnfViewStep::onLeave() -{ -} - - -Calamares::JobList -PlasmaLnfViewStep::jobs() const -{ - return m_config->createJobs(); -} - - -void -PlasmaLnfViewStep::setConfigurationMap( const QVariantMap& configurationMap ) -{ - m_config->setConfigurationMap( configurationMap ); -} diff --git a/src/modules/plasmalnf/PlasmaLnfViewStep.h b/src/modules/plasmalnf/PlasmaLnfViewStep.h deleted file mode 100644 index 48f03cdad1..0000000000 --- a/src/modules/plasmalnf/PlasmaLnfViewStep.h +++ /dev/null @@ -1,51 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2017-2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef PLASMALNFVIEWSTEP_H -#define PLASMALNFVIEWSTEP_H - -#include "DllMacro.h" -#include "utils/PluginFactory.h" -#include "viewpages/ViewStep.h" - -class Config; -class PlasmaLnfPage; - -class PLUGINDLLEXPORT PlasmaLnfViewStep : public Calamares::ViewStep -{ - Q_OBJECT - -public: - explicit PlasmaLnfViewStep( QObject* parent = nullptr ); - ~PlasmaLnfViewStep() override; - - QString prettyName() const override; - - QWidget* widget() override; - - bool isNextEnabled() const override; - bool isBackEnabled() const override; - - bool isAtBeginning() const override; - bool isAtEnd() const override; - - void onLeave() override; - - Calamares::JobList jobs() const override; - - void setConfigurationMap( const QVariantMap& configurationMap ) override; - -private: - Config* m_config; - PlasmaLnfPage* m_widget; -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( PlasmaLnfViewStepFactory ) - -#endif // PLASMALNFVIEWSTEP_H diff --git a/src/modules/plasmalnf/ThemeInfo.cpp b/src/modules/plasmalnf/ThemeInfo.cpp deleted file mode 100644 index 96a9600401..0000000000 --- a/src/modules/plasmalnf/ThemeInfo.cpp +++ /dev/null @@ -1,316 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ -#include "ThemeInfo.h" - -#include "Branding.h" -#include "utils/Gui.h" -#include "utils/Logger.h" - -#include -#include - -#include -#include -#include - -/** @brief describes a single plasma LnF theme. - * - * A theme description has an id, which is really the name of the desktop - * file (e.g. org.kde.breeze.desktop), a name which is human-readable and - * translated, and an optional image Page, which points to a local screenshot - * of that theme. - */ -struct ThemeInfo -{ - QString id; - QString name; - QString description; - QString imagePath; - mutable QPixmap pixmap; - bool show = true; - bool selected = false; - - ThemeInfo() {} - - explicit ThemeInfo( const QString& _id ) - : id( _id ) - { - } - - explicit ThemeInfo( const QString& _id, const QString& image ) - : id( _id ) - , imagePath( image ) - { - } - - explicit ThemeInfo( const KPluginMetaData& ); - - bool isValid() const { return !id.isEmpty(); } - - /// @brief Fill in the pixmap member based on imagePath - QPixmap loadImage() const; -}; - -class ThemeInfoList : public QList< ThemeInfo > -{ -public: - std::pair< int, const ThemeInfo* > indexById( const QString& id ) const - { - int index = 0; - for ( const ThemeInfo& i : *this ) - { - if ( i.id == id ) - { - return { index, &i }; - } - } - return { -1, nullptr }; - } - - std::pair< int, ThemeInfo* > indexById( const QString& id ) - { - // Call the const version and then munge the types - auto [ i, p ] = const_cast< const ThemeInfoList* >( this )->indexById( id ); - return { i, const_cast< ThemeInfo* >( p ) }; - } - - /** @brief Looks for a given @p id in the list of themes, returns nullptr if not found. */ - ThemeInfo* findById( const QString& id ) - { - auto [ i, p ] = indexById( id ); - return p; - } - - /** @brief Looks for a given @p id in the list of themes, returns nullptr if not found. */ - const ThemeInfo* findById( const QString& id ) const - { - auto [ i, p ] = indexById( id ); - return p; - } - - /** @brief Checks if a given @p id is in the list of themes. */ - bool contains( const QString& id ) const { return findById( id ) != nullptr; } -}; - -ThemesModel::ThemesModel( QObject* parent ) - : QAbstractListModel( parent ) - , m_themes( new ThemeInfoList ) -{ - auto packages = KPackage::PackageLoader::self()->listPackages( "Plasma/LookAndFeel" ); - m_themes->reserve( packages.length() ); - - for ( const auto& p : packages ) - { - m_themes->append( ThemeInfo { p } ); - } -} - -int -ThemesModel::rowCount( const QModelIndex& ) const -{ - return m_themes->count(); -} - -QVariant -ThemesModel::data( const QModelIndex& index, int role ) const -{ - if ( !index.isValid() ) - { - return QVariant(); - } - if ( index.row() < 0 || index.row() >= m_themes->count() ) - { - return QVariant(); - } - - const auto& item = m_themes->at( index.row() ); - switch ( role ) - { - case LabelRole: - return item.name; - case KeyRole: - return item.id; - case ShownRole: - return item.show; - case SelectedRole: - return item.selected; - case DescriptionRole: - return item.description; - case ImageRole: - return item.loadImage(); - default: - return QVariant(); - } - __builtin_unreachable(); -} - -QHash< int, QByteArray > -ThemesModel::roleNames() const -{ - return { { LabelRole, "label" }, - { KeyRole, "key" }, - { SelectedRole, "selected" }, - { ShownRole, "show" }, - { ImageRole, "image" } }; -} - -void -ThemesModel::setThemeImage( const QString& id, const QString& imagePath ) -{ - auto [ i, theme ] = m_themes->indexById( id ); - if ( theme ) - { - theme->imagePath = imagePath; - emit dataChanged( index( i, 0 ), index( i, 0 ), { ImageRole } ); - } -} - -void -ThemesModel::setThemeImage( const QMap< QString, QString >& images ) -{ - if ( m_themes->isEmpty() ) - { - return; - } - - // Don't emit signals from each call, aggregate to one call (below this block) - { - QSignalBlocker b( this ); - for ( auto k = images.constKeyValueBegin(); k != images.constKeyValueEnd(); ++k ) - { - setThemeImage( ( *k ).first, ( *k ).second ); - } - } - emit dataChanged( index( 0, 0 ), index( m_themes->count() - 1 ), { ImageRole } ); -} - -void -ThemesModel::showTheme( const QString& id, bool show ) -{ - auto [ i, theme ] = m_themes->indexById( id ); - if ( theme ) - { - theme->show = show; - emit dataChanged( index( i, 0 ), index( i, 0 ), { ShownRole } ); - } -} - -void -ThemesModel::showOnlyThemes( const QMap< QString, QString >& onlyThese ) -{ - if ( m_themes->isEmpty() ) - { - return; - } - - // No signal blocker block needed here because we're not calling showTheme() - // QSignalBlocker b( this ); - for ( auto& t : *m_themes ) - { - t.show = onlyThese.contains( t.id ); - } - emit dataChanged( index( 0, 0 ), index( m_themes->count() - 1 ), { ShownRole } ); -} - -QSize -ThemesModel::imageSize() -{ - return { qMax( 12 * Calamares::defaultFontHeight(), 120 ), qMax( 8 * Calamares::defaultFontHeight(), 80 ) }; -} - -void -ThemesModel::select( const QString& themeId ) -{ - int i = 0; - for ( auto& t : *m_themes ) - { - if ( t.selected && t.id != themeId ) - { - t.selected = false; - emit dataChanged( index( i, 0 ), index( i, 0 ), { SelectedRole } ); - } - if ( !t.selected && t.id == themeId ) - { - t.selected = true; - emit dataChanged( index( i, 0 ), index( i, 0 ), { SelectedRole } ); - } - ++i; - } -} - -/** - * Massage the given @p path to the most-likely - * path that actually contains a screenshot. For - * empty image paths, returns the QRC path for an - * empty screenshot. Returns blank if the path - * doesn't exist anywhere in the search paths. - */ -static QString -munge_imagepath( const QString& path ) -{ - if ( path.isEmpty() ) - { - return ":/view-preview.png"; - } - - if ( path.startsWith( '/' ) ) - { - return path; - } - - if ( QFileInfo::exists( path ) ) - { - return path; - } - - QFileInfo fi( QDir( Calamares::Branding::instance()->componentDirectory() ), path ); - if ( fi.exists() ) - { - return fi.absoluteFilePath(); - } - - return QString(); -} - -ThemeInfo::ThemeInfo( const KPluginMetaData& data ) - : id( data.pluginId() ) - , name( data.name() ) - , description( data.description() ) -{ -} - -QPixmap -ThemeInfo::loadImage() const -{ - if ( pixmap.isNull() ) - { - - const QSize image_size( ThemesModel::imageSize() ); - - const QString path = munge_imagepath( imagePath ); - cDebug() << "Loading initial image for" << id << imagePath << "->" << path; - QPixmap image( path ); - if ( image.isNull() ) - { - // Not found or not specified, so convert the name into some (horrible, likely) - // color instead. - image = QPixmap( image_size ); - auto hash_color = qHash( imagePath.isEmpty() ? id : imagePath ); - cDebug() << Logger::SubEntry << "Theme image" << imagePath << "not found, hash" << hash_color; - image.fill( QColor( QRgb( hash_color ) ) ); - } - else - { - cDebug() << Logger::SubEntry << "Theme image" << image.size(); - } - - pixmap = image.scaled( image_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); - } - return pixmap; -} diff --git a/src/modules/plasmalnf/ThemeInfo.h b/src/modules/plasmalnf/ThemeInfo.h deleted file mode 100644 index c859bcd2d5..0000000000 --- a/src/modules/plasmalnf/ThemeInfo.h +++ /dev/null @@ -1,75 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2017 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef PLASMALNF_THEMEINFO_H -#define PLASMALNF_THEMEINFO_H - -#include -#include -#include - -class ThemeInfoList; - -class ThemesModel : public QAbstractListModel -{ - Q_OBJECT - -public: - enum - { - LabelRole = Qt::DisplayRole, - KeyRole = Qt::UserRole, - ShownRole, // Should theme be displayed - SelectedRole, // Is theme selected - DescriptionRole, - ImageRole - }; - - explicit ThemesModel( QObject* parent ); - - int rowCount( const QModelIndex& = QModelIndex() ) const override; - QVariant data( const QModelIndex& index, int role ) const override; - - QHash< int, QByteArray > roleNames() const override; - - /// @brief Set the screenshot to go with the given @p id - void setThemeImage( const QString& id, const QString& imagePath ); - - /// @brief Call setThemeImage( key, value ) for all keys in @p images - void setThemeImage( const QMap< QString, QString >& images ); - - /// @brief Set whether to show the given theme @p id (or not) - void showTheme( const QString& id, bool show = true ); - - /// @brief Shows the keys in the @p onlyThese map, and hides the rest - void showOnlyThemes( const QMap< QString, QString >& onlyThese ); - - /** @brief Mark the @p themeId as current / selected - * - * One theme can be selected at a time; this will emit data - * changed signals for any (one) theme already selected, and - * the newly-selected theme. If @p themeId does not name any - * theme, none are selected. - */ - void select( const QString& themeId ); - - /** @brief The size of theme Images - * - * The size is dependent on the font size used by Calamares, - * and is constant within one run of Calamares, but may change - * if the font settings do between runs. - */ - static QSize imageSize(); - -private: - ThemeInfoList* m_themes; -}; - - -#endif diff --git a/src/modules/plasmalnf/page_plasmalnf.qrc b/src/modules/plasmalnf/page_plasmalnf.qrc deleted file mode 100644 index c63ecc03b9..0000000000 --- a/src/modules/plasmalnf/page_plasmalnf.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - view-preview.png - - diff --git a/src/modules/plasmalnf/page_plasmalnf.ui b/src/modules/plasmalnf/page_plasmalnf.ui deleted file mode 100644 index c47bc6c934..0000000000 --- a/src/modules/plasmalnf/page_plasmalnf.ui +++ /dev/null @@ -1,37 +0,0 @@ - - - -SPDX-FileCopyrightText: 2017 Adriaan de Groot <groot@kde.org> -SPDX-License-Identifier: GPL-3.0-or-later - - PlasmaLnfPage - - - - 0 - 0 - 799 - 400 - - - - Form - - - - - - Placeholder - - - true - - - - - - - - - - diff --git a/src/modules/plasmalnf/plasmalnf.conf b/src/modules/plasmalnf/plasmalnf.conf deleted file mode 100644 index 105f247efd..0000000000 --- a/src/modules/plasmalnf/plasmalnf.conf +++ /dev/null @@ -1,83 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# The Plasma Look-and-Feel module allows selecting a Plasma -# Look-and-Feel in the live- or host-system and switches the -# host Plasma session immediately to the chosen LnF; it -# can also write a LnF configuration to the target user / on -# the target system. -# -# This module should be used once in a view section (to get -# the UI) and once in the exec section (to apply the selection -# to the target user). It should come **after** the user module -# in exec, so that the target user has been created alrady. ---- -# Full path to the Plasma look-and-feel tool (CLI program -# for querying and applying Plasma themes). If this is not -# set, no LNF setting will happen. -lnftool: "/usr/bin/lookandfeeltool" - -# For systems where the user Calamares runs as (usually root, -# via either sudo or pkexec) has a clean environment, set this -# to the originating username; the lnftool will be run through -# "sudo -H -u " instead of directly. -# -# liveuser: "live" - -# If *showAll* is true, then all installed themes are shown in the -# UI for selection, even if they are not listed in *themes* (below). -# This allows selection of all themes even while not all of them are -# listed in *themes* -- which is useful to show screenshots for those -# you do have a screenshot for. If *themes* is empty or missing, -# the value of *showAll* is treated as `true`. -showAll: false - -# You can limit the list of Plasma look-and-feel themes by listing ids -# here. If this key is not present, all of the installed themes are listed. -# If the key is present, only installed themes that are **also** included -# in the list are shown (could be none!). See the *showAll* key, above, -# to change that. -# -# Themes may be listed by id, (e.g. fluffy-bunny, below) or as a theme -# and an image (e.g. breeze) which will be used to show a screenshot. -# Themes with no image set at all get a "missing screenshot" image; if the -# image file is not found, they get a color swatch based on the image name. -# -# The image may be an absolute path. If it is a relative path, though, -# it is searched in the current directory and in the branding directory -# (i.e. relative to the directory where your branding.desc lives). -# -# Valid forms of entries in the *themes* key: -# - A single string (unquoted), which is the theme id -# - A pair of *theme* and *image* keys, e.g. -# ``` -# - theme: fluffy-bunny.desktop -# image: "fluffy-screenshot.png" -# ``` -# -# The image screenshot is resized to 12x8 the current font size, with -# a minimum of 120x80 pixels. This allows the screenshot to scale up -# on HiDPI displays where the fonts are larger (in pixels). -themes: - - org.kde.fuzzy-pig.desktop - - theme: org.kde.breeze.desktop - image: "breeze.png" - - theme: org.kde.breezedark.desktop - image: "breeze-dark.png" - - org.kde.fluffy-bunny.desktop - -# You can pre-select one of the themes; it is not applied -# immediately, but its radio-button is switched on to indicate -# that that is the theme (that is most likely) currently in use. -# Do this only on Live images where you are reasonably sure -# that the user is not going to change the theme out from under -# themselves before running the installer. -# -# If this key is present, its value should be the id of the theme -# which should be pre-selected. If absent, empty, or the pre-selected -# theme is not found on the live system, no theme will be pre-selected. -# -# As a special setting, use "*", to try to find the currently- -# selected theme by reading the Plasma configuration. This requires -# KF5::Config at build- and run-time. -preselect: "*" diff --git a/src/modules/plasmalnf/view-preview.png b/src/modules/plasmalnf/view-preview.png deleted file mode 100644 index 8e5f07ba9018e2708d9825b2446ea3ae5cc98d91..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 560 zcmeAS@N?(olHy`uVBq!ia0vp^6+j%o!3HER&ED7vq&N#aB8wRq_>O=u<5X=vX$A(y zN1iT@Ar*7p-tt|w*g>N8;bmXvV@=ituaqXSN*pXyTX(QAx`X+k>=iyHwUjw;9H&2I znl#atWBbmRe@gO-w@y0s+owgSi=TgfsF)Yf3N&y)q3(v>18bMSEBu!K(>7P$eE#Kh z8RPxby>a|T?`!PjQ|@j2vn7_H?WqrY{k77$J%(Ag!zPKeExcqh_5JT@+S2ojW$%>E z-J}yNz_MzUS7@jv2UBX~vURU>rkh(mXEHmc(U+|1sdWDHlgfFMR03s=8y&l$mtS&@ z_0G1nX`62z{ZV4|_w%Vb^>eH}#phUM+7_1WzI*gX-TrWiHZiSDr+3Dd%vyG8lh37> zTXp6hTKhUGH8N_=8NTOC-)iGiBTq>z-nCA3?yg-rr)SUiJpMRv^2wAlMju53MZW%D zojI#+W5gHV%Q1WHzZkx_Fekcs|DxPzQP+hko*^Pfqu*_cKcp;MV and others -SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/src/modules/plasmalnf/view-preview.svg b/src/modules/plasmalnf/view-preview.svg deleted file mode 100644 index 90e5beec52..0000000000 --- a/src/modules/plasmalnf/view-preview.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - diff --git a/src/modules/plasmalnf/view-preview.svg.license b/src/modules/plasmalnf/view-preview.svg.license deleted file mode 100644 index ef0e9d7cdc..0000000000 --- a/src/modules/plasmalnf/view-preview.svg.license +++ /dev/null @@ -1,2 +0,0 @@ -SPDX-FileCopyrightText: 2014 Uri Herrera and others -SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/src/modules/plymouthcfg/main.py b/src/modules/plymouthcfg/main.py deleted file mode 100644 index 5e66fce67b..0000000000 --- a/src/modules/plymouthcfg/main.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2016 Artoo -# SPDX-FileCopyrightText: 2017 Alf Gaida -# SPDX-FileCopyrightText: 2018 Gabriel Craciunescu -# SPDX-FileCopyrightText: 2019 Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later -# -# Calamares is Free Software: see the License-Identifier above. -# - -import libcalamares - -from libcalamares.utils import debug, target_env_call - -import gettext -_ = gettext.translation("calamares-python", - localedir=libcalamares.utils.gettext_path(), - languages=libcalamares.utils.gettext_languages(), - fallback=True).gettext - - -def pretty_name(): - return _("Configure Plymouth theme") - - -def detect_plymouth(): - """ - Checks existence (runnability) of plymouth in the target system. - - @return True if plymouth exists in the target, False otherwise - """ - # Used to only check existence of path /usr/bin/plymouth in target - return target_env_call(["sh", "-c", "which plymouth"]) == 0 - - -class PlymouthController: - - def __init__(self): - self.__root = libcalamares.globalstorage.value('rootMountPoint') - - @property - def root(self): - return self.__root - - def setTheme(self): - plymouth_theme = libcalamares.job.configuration["plymouth_theme"] - target_env_call(["sed", "-e", 's|^.*Theme=.*|Theme=' + - plymouth_theme + '|', "-i", - "/etc/plymouth/plymouthd.conf"]) - - def run(self): - if detect_plymouth(): - if (("plymouth_theme" in libcalamares.job.configuration) and - (libcalamares.job.configuration["plymouth_theme"] is not None)): - self.setTheme() - return None - - -def run(): - pc = PlymouthController() - return pc.run() diff --git a/src/modules/plymouthcfg/module.desc b/src/modules/plymouthcfg/module.desc deleted file mode 100644 index 660aa71b2f..0000000000 --- a/src/modules/plymouthcfg/module.desc +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -type: "job" -name: "plymouthcfg" -interface: "python" -script: "main.py" diff --git a/src/modules/plymouthcfg/plymouthcfg.conf b/src/modules/plymouthcfg/plymouthcfg.conf deleted file mode 100644 index ebe51d1ed8..0000000000 --- a/src/modules/plymouthcfg/plymouthcfg.conf +++ /dev/null @@ -1,31 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Plymouth Configuration Module -# -# This module can be used to setup the default plymouth theme to -# be used with your distribution -# -# You should only use this module if the plymouth package is installed -# on the build configurations of your distribution & the plymouth -# theme you want to configure is installed as well. If the unpacked -# filesystem configures a plymouth theme already, there is no need -# to change it here. ---- - - -# Leave this commented if you want to use the default theme -# shipped with your distribution configurations. Make sure that -# the theme exists in the themes directory of plymouth path. -# Debian / Ubuntu comes with themes "joy", "script", "softwaves", -# possibly others. Look in /usr/share/plymouth/themes for more. -# -# Specifying a non-existent theme will leave the plymouth -# configuration set to that theme. It is up to plymouth to -# deal with that. - -plymouth_theme: spinfinity - - - - diff --git a/src/modules/plymouthcfg/plymouthcfg.schema.yaml b/src/modules/plymouthcfg/plymouthcfg.schema.yaml deleted file mode 100644 index 27925ec026..0000000000 --- a/src/modules/plymouthcfg/plymouthcfg.schema.yaml +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later ---- -$schema: https://json-schema.org/schema# -$id: https://calamares.io/schemas/plymouthcfg -additionalProperties: false -type: object -properties: - plymouth_theme: { type: string } diff --git a/src/modules/preservefiles/CMakeLists.txt b/src/modules/preservefiles/CMakeLists.txt deleted file mode 100644 index b11b1310ce..0000000000 --- a/src/modules/preservefiles/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# -calamares_add_plugin(preservefiles - TYPE job - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - Item.cpp - PreserveFiles.cpp - # REQUIRES mount # To set the rootMountPoint - SHARED_LIB - EMERGENCY -) - -calamares_add_test(preservefilestest SOURCES Item.cpp Tests.cpp) diff --git a/src/modules/preservefiles/Item.cpp b/src/modules/preservefiles/Item.cpp deleted file mode 100644 index 7e8c28e226..0000000000 --- a/src/modules/preservefiles/Item.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2018, 2021 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#include "Item.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "compat/Variant.h" -#include "utils/Logger.h" -#include "utils/System.h" -#include "utils/Units.h" -#include "utils/Variant.h" - -#include - -using namespace Calamares::Units; - -static bool -copy_file( const QString& source, const QString& dest ) -{ - QFile sourcef( source ); - if ( !sourcef.open( QFile::ReadOnly ) ) - { - cWarning() << "Could not read" << source; - return false; - } - - QFile destf( dest ); - if ( !destf.open( QFile::WriteOnly ) ) - { - sourcef.close(); - cWarning() << "Could not open" << destf.fileName() << "for writing; could not copy" << source; - return false; - } - - QByteArray b; - do - { - b = sourcef.read( 1_MiB ); - destf.write( b ); - } while ( b.size() > 0 ); - - sourcef.close(); - destf.close(); - - return true; -} - -Item -Item::fromVariant( const QVariant& v, const Calamares::Permissions& defaultPermissions ) -{ - if ( Calamares::typeOf( v ) == Calamares::StringVariantType ) - { - QString filename = v.toString(); - if ( !filename.isEmpty() ) - { - return { filename, filename, defaultPermissions, ItemType::Path, false }; - } - else - { - cWarning() << "Empty filename for preservefiles, item" << v; - return {}; - } - } - else if ( Calamares::typeOf( v ) == Calamares::MapVariantType ) - { - const auto map = v.toMap(); - - Calamares::Permissions perm( defaultPermissions ); - ItemType t = ItemType::None; - bool optional = Calamares::getBool( map, "optional", false ); - - { - QString perm_string = map[ "perm" ].toString(); - if ( !perm_string.isEmpty() ) - { - perm = Calamares::Permissions( perm_string ); - } - } - - { - QString from = map[ "from" ].toString(); - t = ( from == "log" ) ? ItemType::Log : ( from == "config" ) ? ItemType::Config : ItemType::None; - - if ( t == ItemType::None && !map[ "src" ].toString().isEmpty() ) - { - t = ItemType::Path; - } - } - - QString dest = map[ "dest" ].toString(); - if ( dest.isEmpty() ) - { - cWarning() << "Empty dest for preservefiles, item" << v; - return {}; - } - - switch ( t ) - { - case ItemType::Config: - return { QString(), dest, perm, t, optional }; - case ItemType::Log: - return { QString(), dest, perm, t, optional }; - case ItemType::Path: - return { map[ "src" ].toString(), dest, perm, t, optional }; - case ItemType::None: - cWarning() << "Invalid type for preservefiles, item" << v; - return {}; - } - } - cWarning() << "Invalid type for preservefiles, item" << v; - return {}; -} - -bool -Item::exec( const std::function< QString( QString ) >& replacements ) const -{ - QString expanded_dest = replacements( dest ); - QString full_dest = Calamares::System::instance()->targetPath( expanded_dest ); - - bool success = false; - switch ( m_type ) - { - case ItemType::None: - cWarning() << "Invalid item for preservefiles skipped."; - return false; - case ItemType::Config: - if ( !( success = Calamares::JobQueue::instance()->globalStorage()->saveJson( full_dest ) ) ) - { - cWarning() << "Could not write a JSON dump of global storage to" << full_dest; - } - break; - case ItemType::Log: - if ( !( success = copy_file( Logger::logFile(), full_dest ) ) ) - { - cWarning() << "Could not preserve log file to" << full_dest; - } - break; - case ItemType::Path: - if ( !( success = copy_file( source, full_dest ) ) ) - { - cWarning() << "Could not preserve" << source << "to" << full_dest; - } - break; - } - if ( !success ) - { - Calamares::System::instance()->removeTargetFile( expanded_dest ); - return false; - } - else - { - return perm.apply( full_dest ); - } -} diff --git a/src/modules/preservefiles/Item.h b/src/modules/preservefiles/Item.h deleted file mode 100644 index 8707d8db20..0000000000 --- a/src/modules/preservefiles/Item.h +++ /dev/null @@ -1,74 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2018, 2021 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ -#ifndef PRESERVEFILES_ITEM_H -#define PRESERVEFILES_ITEM_H - -#include "utils/Permissions.h" - -#include -#include - -#include - -enum class ItemType -{ - None, - Path, - Log, - Config -}; - -/** @brief Represents one item to copy - * - * All item types need a destination (to place the data), this is - * intepreted within the target system. All items need a permission, - * which is applied to the data once written. - * - * The source may be a path, but not all types need a source. - */ -class Item -{ - QString source; - QString dest; - Calamares::Permissions perm; - ItemType m_type = ItemType::None; - bool m_optional = false; - -public: - Item( const QString& src, const QString& d, Calamares::Permissions p, ItemType t, bool optional ) - : source( src ) - , dest( d ) - , perm( std::move( p ) ) - , m_type( t ) - , m_optional( optional ) - { - } - - Item() - : m_type( ItemType::None ) - { - } - - operator bool() const { return m_type != ItemType::None; } - ItemType type() const { return m_type; } - bool isOptional() const { return m_optional; } - - bool exec( const std::function< QString( QString ) >& replacements ) const; - - /** @brief Create an Item -- or one of its subclasses -- from @p v - * - * Depending on the structure and contents of @p v, a pointer - * to an Item is returned. If @p v cannot be interpreted meaningfully, - * then a nullptr is returned. - * - * When the entry contains a *perm* key, use that permission, otherwise - * apply @p defaultPermissions to the item. - */ - static Item fromVariant( const QVariant& v, const Calamares::Permissions& defaultPermissions ); -}; - -#endif diff --git a/src/modules/preservefiles/PreserveFiles.cpp b/src/modules/preservefiles/PreserveFiles.cpp deleted file mode 100644 index 743b51fc40..0000000000 --- a/src/modules/preservefiles/PreserveFiles.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#include "PreserveFiles.h" - -#include "Item.h" - -#include "CalamaresVersion.h" -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "compat/Variant.h" -#include "utils/CommandList.h" -#include "utils/Logger.h" -#include "utils/StringExpander.h" -#include "utils/System.h" -#include "utils/Units.h" - -#include - -using namespace Calamares::Units; - -QString -atReplacements( QString s ) -{ - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - QString root( "/" ); - QString user; - - if ( gs && gs->contains( "rootMountPoint" ) ) - { - root = gs->value( "rootMountPoint" ).toString(); - } - if ( gs && gs->contains( "username" ) ) - { - user = gs->value( "username" ).toString(); - } - - Calamares::String::DictionaryExpander d; - return d.add( QStringLiteral( "ROOT" ), root ).add( QStringLiteral( "USER" ), user ).expand( s ); -} - -PreserveFiles::PreserveFiles( QObject* parent ) - : Calamares::CppJob( parent ) -{ -} - -PreserveFiles::~PreserveFiles() {} - -QString -PreserveFiles::prettyName() const -{ - return tr( "Saving files for later…", "@status" ); -} - -Calamares::JobResult -PreserveFiles::exec() -{ - if ( m_items.empty() ) - { - return Calamares::JobResult::error( tr( "No files configured to save for later." ) ); - } - - int count = 0; - for ( const auto& it : qAsConst( m_items ) ) - { - if ( !it ) - { - // Invalid entries are nullptr, ignore them but count as a success - // because they shouldn't block the installation. There are - // warnings in the log showing what the configuration problem is. - ++count; - continue; - } - // Try to preserve the file. If it's marked as optional, count it - // as a success regardless. - if ( it.exec( atReplacements ) || it.isOptional() ) - { - ++count; - } - } - - return count == m_items.size() - ? Calamares::JobResult::ok() - : Calamares::JobResult::error( tr( "Not all of the configured files could be preserved." ) ); -} - -void -PreserveFiles::setConfigurationMap( const QVariantMap& configurationMap ) -{ - auto files = configurationMap[ "files" ]; - if ( !files.isValid() ) - { - cDebug() << "No 'files' key for preservefiles."; - return; - } - - if ( Calamares::typeOf( files ) != Calamares::ListVariantType ) - { - cDebug() << "Configuration key 'files' is not a list for preservefiles."; - return; - } - - QString defaultPermissions = configurationMap[ "perm" ].toString(); - if ( defaultPermissions.isEmpty() ) - { - defaultPermissions = QStringLiteral( "root:root:0400" ); - } - Calamares::Permissions perm( defaultPermissions ); - - for ( const auto& li : files.toList() ) - { - m_items.push_back( Item::fromVariant( li, perm ) ); - } -} - -CALAMARES_PLUGIN_FACTORY_DEFINITION( PreserveFilesFactory, registerPlugin< PreserveFiles >(); ) diff --git a/src/modules/preservefiles/PreserveFiles.h b/src/modules/preservefiles/PreserveFiles.h deleted file mode 100644 index dfd2804e3f..0000000000 --- a/src/modules/preservefiles/PreserveFiles.h +++ /dev/null @@ -1,39 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#ifndef PRESERVEFILES_H -#define PRESERVEFILES_H - -#include "CppJob.h" -#include "DllMacro.h" -#include "utils/PluginFactory.h" - -class Item; - -class PLUGINDLLEXPORT PreserveFiles : public Calamares::CppJob -{ - Q_OBJECT - - using ItemList = QList< Item >; - -public: - explicit PreserveFiles( QObject* parent = nullptr ); - ~PreserveFiles() override; - - QString prettyName() const override; - - Calamares::JobResult exec() override; - - void setConfigurationMap( const QVariantMap& configurationMap ) override; - -private: - ItemList m_items; -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( PreserveFilesFactory ) - -#endif // PRESERVEFILES_H diff --git a/src/modules/preservefiles/Tests.cpp b/src/modules/preservefiles/Tests.cpp deleted file mode 100644 index 645843b87f..0000000000 --- a/src/modules/preservefiles/Tests.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2021 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "Item.h" - -#include "Settings.h" -#include "utils/Logger.h" -#include "utils/NamedEnum.h" -#include "utils/System.h" -#include "utils/Yaml.h" - -#include - -class PreserveFilesTests : public QObject -{ - Q_OBJECT -public: - PreserveFilesTests(); - ~PreserveFilesTests() override {} - -private Q_SLOTS: - void initTestCase(); - - void testItems_data(); - void testItems(); -}; - -PreserveFilesTests::PreserveFilesTests() {} - -void -PreserveFilesTests::initTestCase() -{ - Logger::setupLogLevel( Logger::LOGDEBUG ); - cDebug() << "PreserveFiles test started."; - - // Ensure we have a system object, expect it to be a "bogus" one - Calamares::System* system = Calamares::System::instance(); - QVERIFY( system ); - cDebug() << Logger::SubEntry << "System @" << Logger::Pointer( system ); - - const auto* settings = Calamares::Settings::instance(); - if ( !settings ) - { - (void)new Calamares::Settings( true ); - } -} - -void -PreserveFilesTests::testItems_data() -{ - QTest::addColumn< QString >( "filename" ); - QTest::addColumn< bool >( "ok" ); - QTest::addColumn< int >( "type_i" ); - - QTest::newRow( "log " ) << QString( "1a-log.conf" ) << true << smash( ItemType::Log ); - QTest::newRow( "config " ) << QString( "1b-config.conf" ) << true << smash( ItemType::Config ); - QTest::newRow( "src " ) << QString( "1c-src.conf" ) << true << smash( ItemType::Path ); - QTest::newRow( "filename" ) << QString( "1d-filename.conf" ) << true << smash( ItemType::Path ); - QTest::newRow( "empty " ) << QString( "1e-empty.conf" ) << false << smash( ItemType::None ); - QTest::newRow( "bad " ) << QString( "1f-bad.conf" ) << false << smash( ItemType::None ); -} - -void -PreserveFilesTests::testItems() -{ - QFETCH( QString, filename ); - QFETCH( bool, ok ); - QFETCH( int, type_i ); - - QFileInfo fi( QString( "%1/tests/%2" ).arg( BUILD_AS_TEST, filename ) ); - QVERIFY( fi.exists() ); - - bool config_file_ok = false; - const auto map = Calamares::YAML::load( fi, &config_file_ok ); - QVERIFY( config_file_ok ); - - Calamares::Permissions perm( QStringLiteral( "adridg:adridg:0750" ) ); - auto i = Item::fromVariant( map[ "item" ], perm ); - QCOMPARE( bool( i ), ok ); - QCOMPARE( smash( i.type() ), type_i ); -} - -QTEST_GUILESS_MAIN( PreserveFilesTests ) - -#include "utils/moc-warnings.h" - -#include "Tests.moc" diff --git a/src/modules/preservefiles/preservefiles.conf b/src/modules/preservefiles/preservefiles.conf deleted file mode 100644 index 75584f566d..0000000000 --- a/src/modules/preservefiles/preservefiles.conf +++ /dev/null @@ -1,70 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Configuration for the preserve-files job -# -# The *files* key contains a list of files to preserve. Each element of -# the list should have one of these forms: -# -# - an absolute path (probably within the host system). This will be preserved -# as the same path within the target system (chroot). If, globally, -# *dontChroot* is true, then these items will be ignored (since the -# destination is the same as the source). -# - a map with a *dest* key. The *dest* value is a path interpreted in the -# target system (if the global *dontChroot* is true, then the host is the -# target as well). Relative paths are not recommended. There are two -# ways to select the source data for the file: -# - *from*, which must have one of the values, below; it is used to -# preserve files whose pathname is known to Calamares internally. -# - *src*, to refer to a path interpreted in the host system. Relative -# paths are not recommended, and are interpreted relative to where -# Calamares is being run. -# Exactly one of the two source keys (either *from* or *src*) must be set. -# -# Special values for the key *from* are: -# - *log*, for the complete log file (up to the moment the preservefiles -# module is run), -# - *config*, for a JSON dump of the contents of global storage. -# Note that this may contain sensitive information, and should be -# given restrictive permissions. -# -# A map with a *dest* key can have these additional fields: -# - *perm*, is a colon-separated tuple of :: -# where is in octal (e.g. 4777 for wide-open, 0400 for read-only -# by owner). If set, the file's ownership and permissions are set to -# those values within the target system; if not set, no permissions -# are changed. -# - *optional*, is a boolean; if this is set to `true` then failure to -# preserve the file will **not** be counted as a failure of the -# module, and installation will proceed. Set this for files that might -# not exist in the host system (e.g. nvidia configuration files that -# are created in some boot scenarios and not in others). -# -# The target path (*dest*) is modified by expanding variables in `${}`: -# - `ROOT` is replaced by the path to the target root (may be /). -# There is never any reason to use this, since the *dest* is already -# interpreted in the target system. -# - `USER` is replaced by the username entered by on the user -# page (may be empty, for instance if no user page is enabled) -# -# -# -files: - - from: log - dest: /var/log/Calamares.log - perm: root:wheel:600 - - from: log - dest: /home/${USER}/installation.log - optional: true - - from: config - dest: /var/log/Calamares-install.json - perm: root:wheel:600 -# - src: /var/log/nvidia.conf -# dest: /var/log/Calamares-nvidia.conf -# optional: true - -# The *perm* key contains a default value to apply to all files listed -# above that do not have a *perm* key of their own. If not set, -# root:root:0400 (highly restrictive) is used. -# -# perm: "root:root:0400" diff --git a/src/modules/preservefiles/preservefiles.schema.yaml b/src/modules/preservefiles/preservefiles.schema.yaml deleted file mode 100644 index 65067ea972..0000000000 --- a/src/modules/preservefiles/preservefiles.schema.yaml +++ /dev/null @@ -1,37 +0,0 @@ -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later ---- -$schema: https://json-schema.org/schema# -$id: https://calamares.io/schemas/preservefiles -additionalProperties: false -type: object -properties: - # TODO: it's a particularly-formatted string - perm: { type: string } - files: - type: array - items: - # There are three entries here because: string, or an entry with - # a src (but no from) or an entry with from (but no src). - anyOf: - - type: string - - type: object - properties: - dest: { type: string } - src: { type: string } - # TODO: it's a particularly-formatted string - perm: { type: string } - optional: { type: boolean } - required: [ dest ] - additionalProperties: false - - type: object - properties: - dest: { type: string } - from: { type: string, enum: [config, log] } - # TODO: it's a particularly-formatted string - perm: { type: string } - optional: { type: boolean } - required: [ dest ] - additionalProperties: false - -required: [ files ] diff --git a/src/modules/preservefiles/tests/1a-log.conf b/src/modules/preservefiles/tests/1a-log.conf deleted file mode 100644 index d589d4dfbd..0000000000 --- a/src/modules/preservefiles/tests/1a-log.conf +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -item: - from: log - dest: /var/log/Calamares.log - perm: root:wheel:601 diff --git a/src/modules/preservefiles/tests/1b-config.conf b/src/modules/preservefiles/tests/1b-config.conf deleted file mode 100644 index 409dc89d9e..0000000000 --- a/src/modules/preservefiles/tests/1b-config.conf +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -item: - from: config - dest: /var/log/Calamares-install.json - perm: root:wheel:600 diff --git a/src/modules/preservefiles/tests/1c-src.conf b/src/modules/preservefiles/tests/1c-src.conf deleted file mode 100644 index 130ddd06fe..0000000000 --- a/src/modules/preservefiles/tests/1c-src.conf +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -item: - src: /root/.cache/calamares/session.log - dest: /var/log/Calamares.log - perm: root:wheel:600 diff --git a/src/modules/preservefiles/tests/1d-filename.conf b/src/modules/preservefiles/tests/1d-filename.conf deleted file mode 100644 index 130ddd06fe..0000000000 --- a/src/modules/preservefiles/tests/1d-filename.conf +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -item: - src: /root/.cache/calamares/session.log - dest: /var/log/Calamares.log - perm: root:wheel:600 diff --git a/src/modules/preservefiles/tests/1e-empty.conf b/src/modules/preservefiles/tests/1e-empty.conf deleted file mode 100644 index 183d4e456e..0000000000 --- a/src/modules/preservefiles/tests/1e-empty.conf +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -item: [] diff --git a/src/modules/preservefiles/tests/1f-bad.conf b/src/modules/preservefiles/tests/1f-bad.conf deleted file mode 100644 index b2c0089550..0000000000 --- a/src/modules/preservefiles/tests/1f-bad.conf +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -item: - bop: 1 diff --git a/src/modules/rawfs/main.py b/src/modules/rawfs/main.py deleted file mode 100644 index a72ffe19d2..0000000000 --- a/src/modules/rawfs/main.py +++ /dev/null @@ -1,182 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2019 Collabora Ltd -# SPDX-License-Identifier: GPL-3.0-or-later -# -# Calamares is Free Software: see the License-Identifier above. -# - -import libcalamares -import os -import stat -import subprocess -from time import gmtime, strftime, sleep -from math import gcd - -import gettext -_ = gettext.translation("calamares-python", - localedir=libcalamares.utils.gettext_path(), - languages=libcalamares.utils.gettext_languages(), - fallback=True).gettext - -def pretty_name(): - return _("Installing data.") - -def lcm(a, b): - """ - Computes the Least Common Multiple of 2 numbers - """ - return a * b / gcd(a, b) - -def get_device_size(device): - """ - Returns a filesystem's total size and block size in bytes. - For block devices, block size is the device's block size. - For other files (fs images), block size is 1 byte. - - @param device: str - Absolute path to the device or filesystem image. - @return: tuple(int, int) - The filesystem's size and its block size. - """ - mode = os.stat(device).st_mode - if stat.S_ISBLK(mode): - basedevice = "" - partition = os.path.basename(device) - tmp = partition - while len(tmp) > 0: - tmp = tmp[:-1] - if os.path.exists("/sys/block/" + tmp): - basedevice = tmp - break - # Get device block size - file = open("/sys/block/" + basedevice + "/queue/hw_sector_size") - blocksize = int(file.readline()) - file.close() - # Get partition size - file = open("/sys/block/" + basedevice + "/" + partition + "/size") - size = int(file.readline()) * blocksize - file.close() - else: - size = os.path.getsize(device) - blocksize = 1 - - return size, blocksize - -class RawFSLowSpaceError(Exception): - pass - -class RawFSItem: - __slots__ = ['source', 'destination', 'filesystem', 'resize'] - - def copy(self, current=0, total=1): - """ - Copies a raw filesystem on a disk partition, and grow it to the full destination - partition's size if required. - - @param current: int - The index of the current item in the filesystems list - (used for progress reporting) - @param total: int - The number of items in the filesystems list - (used for progress reporting) - """ - count = 0 - - libcalamares.utils.debug("Copying {} to {}".format(self.source, self.destination)) - if libcalamares.job.configuration.get("bogus", False): - return - - srcsize, srcblksize = get_device_size(self.source) - destsize, destblksize = get_device_size(self.destination) - - if destsize < srcsize: - raise RawFSLowSpaceError - return - - # Compute transfer block size (100x the LCM of the block sizes seems a good fit) - blksize = int(100 * lcm(srcblksize, destblksize)) - - # Execute copy - src = open(self.source, "rb") - dest = open(self.destination, "wb") - buffer = src.read(blksize) - while len(buffer) > 0: - dest.write(buffer) - count += len(buffer) - # Compute job progress - progress = ((count / srcsize) + (current)) / total - libcalamares.job.setprogress(progress) - # Read next data block - buffer = src.read(blksize) - src.close() - dest.close() - - if self.resize: - if "ext" in self.filesystem: - libcalamares.utils.debug("Resizing filesystem on {}".format(self.destination)) - subprocess.run(["e2fsck", "-f", "-y", self.destination]) - subprocess.run(["resize2fs", self.destination]) - - def __init__(self, config, device, fs): - libcalamares.utils.debug("Adding an entry for raw copy of {} to {}".format( - config["source"], device)) - self.source = os.path.realpath(config["source"]) - # If source is a mount point, look for the actual device mounted on it - if os.path.ismount(self.source): - procmounts = open("/proc/mounts", "r") - for line in procmounts: - if self.source in line.split(): - self.source = line.split()[0] - break - - self.destination = device - self.filesystem = fs - try: - self.resize = bool(config["resize"]) - except KeyError: - self.resize = False - -def update_global_storage(item, gs): - for partition in gs: - if partition["device"] == item.destination: - ret = subprocess.run(["blkid", "-s", "UUID", "-o", "value", item.destination], - stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True) - if ret.returncode == 0: - libcalamares.utils.debug("Setting {} UUID to {}".format(item.destination, - ret.stdout.rstrip())) - gs[gs.index(partition)]["uuid"] = ret.stdout.rstrip() - gs[gs.index(partition)]["source"] = item.source - - libcalamares.globalstorage.remove("partitions") - libcalamares.globalstorage.insert("partitions", gs) - -def run(): - """Raw filesystem copy module""" - filesystems = list() - partitions = libcalamares.globalstorage.value("partitions") - - if not partitions: - libcalamares.utils.warning("partitions is empty, {!s}".format(partitions)) - return (_("Configuration Error"), - _("No partitions are defined for
    {!s}
    to use." ).format("rawfs")) - - libcalamares.utils.debug("Copying {!s} raw partitions.".format(len(partitions))) - for partition in partitions: - if partition["mountPoint"]: - for src in libcalamares.job.configuration["targets"]: - if src["mountPoint"] == partition["mountPoint"]: - filesystems.append(RawFSItem(src, partition["device"], partition["fs"])) - - for item in filesystems: - try: - item.copy(filesystems.index(item), len(filesystems)) - except RawFSLowSpaceError: - return ("Not enough free space", - "{} partition is too small to copy {} on it".format(item.destination, item.source)) - update_global_storage(item, partitions) - - return None diff --git a/src/modules/rawfs/module.desc b/src/modules/rawfs/module.desc deleted file mode 100644 index 0c4f21f925..0000000000 --- a/src/modules/rawfs/module.desc +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# Module metadata file for block-copy jobmodule -# Syntax is YAML 1.2 ---- -type: "job" -name: "rawfs" -interface: "python" -script: "main.py" diff --git a/src/modules/rawfs/rawfs.conf b/src/modules/rawfs/rawfs.conf deleted file mode 100644 index bbc36906bb..0000000000 --- a/src/modules/rawfs/rawfs.conf +++ /dev/null @@ -1,32 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Configuration for the rawfs module: raw filesystem copy to a block device - ---- - -# To apply a custom partition layout, it has to be defined as a list of targets. -# -# For each target, the following attributes must be defined: -# * mountPoint: The mount point of the destination device on the installed system -# The corresponding block device will automatically be identified and used as the -# destination for the operation -# * source: The source filesystem; it can be the mount point of a locally (on the -# live system) mounted filesystem, a path to a disk image, or a block device -# * resize (optional): Expand the destination filesystem to fill the whole -# partition at the end of the operation; this works only with ext filesystems -# for now - -targets: - - mountPoint: / - source: / - - mountPoint: /home - source: /images/home.img - resize: true - - mountPoint: /data - source: /dev/mmcblk0p3 - -# To support testing, set the *bogus* key to true. No actual work is done, but the -# module's logic is exercised. - -# bogus: false diff --git a/src/modules/rawfs/tests/1.global b/src/modules/rawfs/tests/1.global deleted file mode 100644 index 089557d992..0000000000 --- a/src/modules/rawfs/tests/1.global +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -rootMountPoint: /tmp/unpackfs-test-run-rootdir3/ -partitions: - - mountPoint: / - device: /dev/sda1 - fs: ext4 - - mountPoint: /home - device: /dev/sda2 - fs: ext4 diff --git a/src/modules/rawfs/tests/1.job b/src/modules/rawfs/tests/1.job deleted file mode 100644 index c87a4a70c3..0000000000 --- a/src/modules/rawfs/tests/1.job +++ /dev/null @@ -1,17 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Testing configuration for rawfs -# ---- - -targets: - - mountPoint: / - source: / - - mountPoint: /home - source: /images/home.img - resize: true - - mountPoint: /data - source: /dev/mmcblk0p3 - -bogus: true diff --git a/src/modules/rawfs/tests/CMakeTests.txt b/src/modules/rawfs/tests/CMakeTests.txt deleted file mode 100644 index ed4c374853..0000000000 --- a/src/modules/rawfs/tests/CMakeTests.txt +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# -# Special cases for rawfs tests -# -# - On FreeBSD, /proc/mounts doesn't exist (/proc is only about processes, -# and is rarely used). Expect the test to fail. - -if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - set_tests_properties(load-rawfs-1 PROPERTIES WILL_FAIL TRUE) -endif() diff --git a/src/modules/removeuser/CMakeLists.txt b/src/modules/removeuser/CMakeLists.txt deleted file mode 100644 index eaaf20157a..0000000000 --- a/src/modules/removeuser/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# -calamares_add_plugin(removeuser - TYPE job - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - RemoveUserJob.cpp - SHARED_LIB -) diff --git a/src/modules/removeuser/RemoveUserJob.cpp b/src/modules/removeuser/RemoveUserJob.cpp deleted file mode 100644 index 2eba510ffb..0000000000 --- a/src/modules/removeuser/RemoveUserJob.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017 Alf Gaida - * SPDX-FileCopyrightText: 2019-2020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "RemoveUserJob.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "utils/Logger.h" -#include "utils/System.h" -#include "utils/Variant.h" - -#include - -RemoveUserJob::RemoveUserJob( QObject* parent ) - : Calamares::CppJob( parent ) -{ -} - -RemoveUserJob::~RemoveUserJob() {} - -QString -RemoveUserJob::prettyName() const -{ - return tr( "Removing live user from the target system…", "@status" ); -} - -Calamares::JobResult -RemoveUserJob::exec() -{ - if ( m_username.isEmpty() ) - { - cWarning() << "Ignoring an empty username."; - return Calamares::JobResult::ok(); - } - - auto* s = Calamares::System::instance(); - auto r = s->targetEnvCommand( { QStringLiteral( "userdel" ), - QStringLiteral( "-f" ), // force - QStringLiteral( "-r" ), // remove home-dir and mail - m_username } ); - if ( r.getExitCode() != 0 ) - { - cWarning() << "Cannot remove user" << m_username << "userdel terminated with exit code" << r.getExitCode(); - } - return Calamares::JobResult::ok(); -} - -void -RemoveUserJob::setConfigurationMap( const QVariantMap& map ) -{ - m_username = Calamares::getString( map, "username" ); -} - -CALAMARES_PLUGIN_FACTORY_DEFINITION( RemoveUserJobFactory, registerPlugin< RemoveUserJob >(); ) diff --git a/src/modules/removeuser/RemoveUserJob.h b/src/modules/removeuser/RemoveUserJob.h deleted file mode 100644 index c8a4df15d6..0000000000 --- a/src/modules/removeuser/RemoveUserJob.h +++ /dev/null @@ -1,40 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef REMOVEUSERJOB_H -#define REMOVEUSERJOB_H - -#include "CppJob.h" -#include "DllMacro.h" -#include "utils/PluginFactory.h" - -#include -#include - -class PLUGINDLLEXPORT RemoveUserJob : public Calamares::CppJob -{ - Q_OBJECT - -public: - explicit RemoveUserJob( QObject* parent = nullptr ); - ~RemoveUserJob() override; - - QString prettyName() const override; - - Calamares::JobResult exec() override; - - void setConfigurationMap( const QVariantMap& configurationMap ) override; - -private: - QString m_username; -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( RemoveUserJobFactory ) - -#endif // REMOVEUSERJOB_H diff --git a/src/modules/removeuser/removeuser.conf b/src/modules/removeuser/removeuser.conf deleted file mode 100644 index cc086e7234..0000000000 --- a/src/modules/removeuser/removeuser.conf +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Removes a single user (with userdel) from the system. -# This is typically used in OEM setups or if the live user -# spills into the target system. -# -# The module never fails; if userdel fails, this is logged -# but the module still reports success and installation / setup -# continues as normal. ---- -# Username in the target system to be removed. -username: live diff --git a/src/modules/removeuser/removeuser.schema.yaml b/src/modules/removeuser/removeuser.schema.yaml deleted file mode 100644 index c282717164..0000000000 --- a/src/modules/removeuser/removeuser.schema.yaml +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later ---- -$schema: https://json-schema.org/schema# -$id: https://calamares.io/schemas/removeuser -additionalProperties: false -type: object -properties: - username: { type: string } -required: [ username ] diff --git a/src/modules/services-openrc/main.py b/src/modules/services-openrc/main.py deleted file mode 100644 index cb1ae80202..0000000000 --- a/src/modules/services-openrc/main.py +++ /dev/null @@ -1,131 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2016 Artoo -# SPDX-FileCopyrightText: 2017 Philip Müller -# SPDX-FileCopyrightText: 2018 Artoo -# SPDX-FileCopyrightText: 2018-2019 Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later -# -# Calamares is Free Software: see the License-Identifier above. -# - -import libcalamares - -from libcalamares.utils import target_env_call, warning -from os.path import exists, join - - -import gettext -_ = gettext.translation("calamares-python", - localedir=libcalamares.utils.gettext_path(), - languages=libcalamares.utils.gettext_languages(), - fallback=True).gettext - - -def pretty_name(): - return _("Configure OpenRC services") - - -class OpenrcController: - """ - This is the openrc service controller. - All of its state comes from global storage and the job - configuration at initialization time. - """ - - def __init__(self): - self.root = libcalamares.globalstorage.value('rootMountPoint') - - # Translate the entries in the config to the actions passed to rc-config - self.services = dict() - self.services["add"] = libcalamares.job.configuration.get('services', []) - self.services["del"] = libcalamares.job.configuration.get('disable', []) - - self.initdDir = libcalamares.job.configuration['initdDir'] - self.runlevelsDir = libcalamares.job.configuration['runlevelsDir'] - - - def make_failure_description(self, state, name, runlevel): - """ - Returns a generic "could not " failure message, specialized - for the action @p state and the specific service @p name in @p runlevel. - """ - if state == "add": - description = _("Cannot add service {name!s} to run-level {level!s}.") - elif state == "del": - description = _("Cannot remove service {name!s} from run-level {level!s}.") - else: - description = _("Unknown service-action {arg!s} for service {name!s} in run-level {level!s}.") - - return description.format(arg=state, name=name, level=runlevel) - - - def update(self, state): - """ - Call rc-update for each service listed - in services for the given @p state. rc-update - is called with @p state as the command as well. - """ - - for svc in self.services.get(state, []): - if isinstance(svc, str): - name = svc - runlevel = "default" - mandatory = False - else: - name = svc["name"] - runlevel = svc.get("runlevel", "default") - mandatory = svc.get("mandatory", False) - - service_path = self.root + self.initdDir + "/" + name - runlevel_path = self.root + self.runlevelsDir + "/" + runlevel - - if exists(service_path): - if exists(runlevel_path): - ec = target_env_call(["rc-update", state, name, runlevel]) - if ec != 0: - warning("Cannot {} service {} to {}".format(state, name, runlevel)) - warning("rc-update returned error code {!s}".format(ec)) - if mandatory: - title = _("Cannot modify service") - diagnostic = _("rc-update {arg!s} call in chroot returned error code {num!s}.").format(arg=state, num=ec) - return (title, - self.make_failure_description(state, name, runlevel) + " " + diagnostic - ) - else: - warning("Target runlevel {} does not exist for {}.".format(runlevel, name)) - if mandatory: - title = _("Target runlevel does not exist") - diagnostic = _("The path for runlevel {level!s} is {path!s}, which does not exist.").format(level=runlevel, path=runlevel_path) - - return (title, - self.make_failure_description(state, name, runlevel) + " " + diagnostic - ) - else: - warning("Target service {} does not exist in {}.".format(name, self.initdDir)) - if mandatory: - title = _("Target service does not exist") - diagnostic = _("The path for service {name!s} is {path!s}, which does not exist.").format(name=name, path=service_path) - return (title, - self.make_failure_description(state, name, runlevel) + " " + diagnostic - ) - - - def run(self): - """Run the controller - """ - - for state in ("add", "del"): - r = self.update(state) - if r is not None: - return r - -def run(): - """ - Setup services - """ - - return OpenrcController().run() diff --git a/src/modules/services-openrc/module.desc b/src/modules/services-openrc/module.desc deleted file mode 100644 index c60872bc14..0000000000 --- a/src/modules/services-openrc/module.desc +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -type: "job" -name: "services-openrc" -interface: "python" -script: "main.py" diff --git a/src/modules/services-openrc/services-openrc.conf b/src/modules/services-openrc/services-openrc.conf deleted file mode 100644 index 6042b53050..0000000000 --- a/src/modules/services-openrc/services-openrc.conf +++ /dev/null @@ -1,49 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# openrc services module to modify service runlevels via rc-update in the chroot -# -# Services can be added (to any runlevel, or multiple runlevels) or deleted. -# Handle del with care and only use it if absolutely necessary. -# -# if a service is listed in the conf but is not present/detected on the target system, -# or a runlevel does not exist, it will be ignored and skipped; a warning is logged. -# ---- -# initdDir: holds the openrc service directory location -initdDir: /etc/init.d - -# runlevelsDir: holds the runlevels directory location -runlevelsDir: /etc/runlevels - -# services: a list of entries to **enable** -# disable: a list of entries to **disable** -# -# Each entry has three fields: -# - name: the service name -# - (optional) runlevel: can hold any runlevel present on the target -# system; if no runlevel is provided, "default" is assumed. -# - (optional) mandatory: if set to true, a failure to modify -# the service will result in installation failure, rather than just -# a warning. The default is false. -# -# an entry may also be a single string, which is interpreted -# as the name field (runlevel "default" is assumed then, and not-mandatory). -# -# # Example services and disable settings: -# # - add foo1 to default, but it must succeed -# # - add foo2 to nonetwork -# # - remove foo3 from default -# # - remove foo4 from default -# services: -# - name: foo1 -# mandatory: true -# - name: foo2 -# runlevel: nonetwork -# disable: -# - name: foo3 -# runlevel: default -# - foo4 -services: [] -disable: [] - diff --git a/src/modules/services-systemd/main.py b/src/modules/services-systemd/main.py deleted file mode 100644 index 19c5974d64..0000000000 --- a/src/modules/services-systemd/main.py +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2014 Philip Müller -# SPDX-FileCopyrightText: 2014 Teo Mrnjavac -# SPDX-FileCopyrightText: 2017 Alf Gaida -# SPDX-FileCopyrightText: 2018-2019 Adriaan de Groot -# SPDX-FileCopyrightText: 2022 shivanandvp -# SPDX-License-Identifier: GPL-3.0-or-later -# -# Calamares is Free Software: see the License-Identifier above. - -import libcalamares - - -import gettext -_ = gettext.translation("calamares-python", - localedir=libcalamares.utils.gettext_path(), - languages=libcalamares.utils.gettext_languages(), - fallback=True).gettext - - -def pretty_name(): - return _("Configure systemd units") - - -def systemctl(units): - """ - For each entry in @p units, run "systemctl ", - where each unit is a mapping of unit name, action, and a flag. - - Returns a failure message, or None if this was successful. - Units that are not mandatory have their failures suppressed - silently. - """ - - for unit in units: - if isinstance(unit, str): - name = unit - action = "enable" - mandatory = False - else: - if "name" not in unit: - libcalamares.utils.error("The key 'name' is missing from the mapping {_unit!s}. Continuing to the next unit.".format(_unit=str(unit))) - continue - name = unit["name"] - action = unit.get("action", "enable") - mandatory = unit.get("mandatory", False) - - exit_code = libcalamares.utils.target_env_call( - ['systemctl', action, name] - ) - - if exit_code != 0: - libcalamares.utils.warning( - "Cannot {} systemd unit {}".format(action, name) - ) - libcalamares.utils.warning( - "systemctl {} call in chroot returned error code {}".format(action, exit_code) - ) - if mandatory: - title = _("Cannot modify unit") - diagnostic = _("systemctl {_action!s} call in chroot returned error code {_exit_code!s}.").format(_action=action, _exit_code=exit_code) - description = _("Cannot {_action!s} systemd unit {_name!s}.").format(_action=action, _name=name) - return ( - title, - description + " " + diagnostic - ) - return None - - -def run(): - """ - Setup systemd units - """ - cfg = libcalamares.job.configuration - - return_value = systemctl( - cfg.get("units", []) - ) - if return_value is not None: - return return_value - - return None diff --git a/src/modules/services-systemd/module.desc b/src/modules/services-systemd/module.desc deleted file mode 100644 index e016c6dcb0..0000000000 --- a/src/modules/services-systemd/module.desc +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -type: "job" -name: "services-systemd" -interface: "python" -script: "main.py" diff --git a/src/modules/services-systemd/services-systemd.conf b/src/modules/services-systemd/services-systemd.conf deleted file mode 100644 index 330a94c651..0000000000 --- a/src/modules/services-systemd/services-systemd.conf +++ /dev/null @@ -1,54 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Systemd units manipulation. -# -# This module can perform actions using systemd units, -# (for example, enabling, disabling, or masking services, sockets, paths, etc.) ---- - -# There is one key for this module: *units*. Its value is a list of entries. -# Each entry has three keys: -# - *name* is the (string) name of the systemd unit that is being changed. -# Use quotes. You can use any valid systemd unit here (for example, -# "NetworkManager.service", "cups.socket", "lightdm", "gdm", etc.) -# - *action* is the (string) action that you want to perform over the unit -# (for example, "enable", "disable", "mask", "unmask", etc.). Please -# ensure that the action can actually run under chroot (otherwise it is -# pointless) -# - *mandatory* is a boolean option, which states whether the change -# must be done successfully. If systemd reports an error while changing -# a mandatory entry, the installation will fail. When mandatory is false, -# errors for that systemd unit are ignored. If mandatory -# is not specified, the default is false. -# -# The order of operations is the same as the order in which entries -# appear in the list - -# # This example enables NetworkManager.service (and fails if it can't), -# # disables cups.socket (and ignores failure). Then it enables the -# # graphical target (e.g. so that SDDM runs for login), and -# # finally masks pacman-init (an ArchLinux-only service). -# # -# units: -# - name: "NetworkManager.service" -# action: "enable" -# mandatory: true -# -# - name: "cups.socket" -# action: "disable" -# # The property "mandatory" is taken to be false by default here -# # because it is not specified -# -# - name: "graphical.target" -# action: "enable" -# # The property "mandatory" is taken to be false by default here -# # because it is not specified -# -# - name: "pacman-init.service" -# action: "mask" -# # The property "mandatory" is taken to be false by default here -# # because it is not specified - -# By default, no changes are made. -units: [] diff --git a/src/modules/services-systemd/services-systemd.schema.yaml b/src/modules/services-systemd/services-systemd.schema.yaml deleted file mode 100644 index 7e1fe052e4..0000000000 --- a/src/modules/services-systemd/services-systemd.schema.yaml +++ /dev/null @@ -1,21 +0,0 @@ -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later ---- -$schema: https://json-schema.org/schema# -$id: https://calamares.io/schemas/services-systemd -definitions: - unit: - $id: 'definitions/unit' - type: object - description: a map containing a unit name, an action, and whether it is mandatory - additionalProperties: false - properties: - name: { type: string } - action: { type: string, default: "enable" } - mandatory: { type: boolean, default: false } - required: [ name ] - -additionalProperties: false -type: object -properties: - units: { type: array, items: { $ref: 'definitions/unit' } } diff --git a/src/modules/summary/CMakeLists.txt b/src/modules/summary/CMakeLists.txt deleted file mode 100644 index 671cf569d6..0000000000 --- a/src/modules/summary/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# -include_directories(${PROJECT_BINARY_DIR}/src/libcalamaresui) -calamares_add_plugin(summary - TYPE viewmodule - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - Config.cpp - SummaryModel.cpp - SummaryPage.cpp - SummaryViewStep.cpp - UI - SHARED_LIB - NO_CONFIG -) diff --git a/src/modules/summary/Config.cpp b/src/modules/summary/Config.cpp deleted file mode 100644 index 387b03075f..0000000000 --- a/src/modules/summary/Config.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020, Camilo Higuita - * SPDX-FileCopyrightText: 2021 Anke Boersma - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "Config.h" - -#include "SummaryModel.h" - -#include "Branding.h" -#include "Settings.h" -#include "ViewManager.h" -#include "utils/Gui.h" -#include "utils/Logger.h" -#include "utils/Retranslator.h" -#include "viewpages/ExecutionViewStep.h" - -Config::Config( QObject* parent ) - : QObject( parent ) - , m_summary( new SummaryModel( this ) ) - -{ - CALAMARES_RETRANSLATE_SLOT( &Config::retranslate ); - retranslate(); -} - -void -Config::retranslate() -{ - m_title = tr( "Summary", "@label" ); - - if ( Calamares::Settings::instance()->isSetupMode() ) - { - m_message = tr( "This is an overview of what will happen once you start " - "the setup procedure." ); - } - else - { - m_message = tr( "This is an overview of what will happen once you start " - "the install procedure." ); - } - Q_EMIT titleChanged( m_title ); - Q_EMIT messageChanged( m_message ); -} - -Calamares::ViewStepList -Config::stepsForSummary( const Calamares::ViewStep* upToHere ) -{ - Calamares::ViewStepList steps; - for ( Calamares::ViewStep* step : Calamares::ViewManager::instance()->viewSteps() ) - { - // *Assume* that if there's an exec step in the sequence, - // we don't need a summary for steps before it. This works in - // practice if there's a summary step before each exec -- - // and in practice, there's only one of each. - if ( qobject_cast< Calamares::ExecutionViewStep* >( step ) ) - { - steps.clear(); - continue; - } - - // Having reached the parent view-step of the Config object, - // we know we're providing a summary of steps up until this - // view step, so we now have steps since the previous exec, up - // to this summary. - if ( upToHere == step ) - { - break; - } - - steps.append( step ); - } - return steps; -} - - -void -Config::collectSummaries( const Calamares::ViewStep* upToHere, Widgets withWidgets ) -{ - m_summary->setSummaryList( stepsForSummary( upToHere ), withWidgets == Widgets::Enabled ); -} - -void -Config::clearSummaries() -{ - m_summary->setSummaryList( {}, false ); -} diff --git a/src/modules/summary/Config.h b/src/modules/summary/Config.h deleted file mode 100644 index 25381b1263..0000000000 --- a/src/modules/summary/Config.h +++ /dev/null @@ -1,63 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2019-2020, Adriaan de Groot - * SPDX-FileCopyrightText: 2020, Camilo Higuita - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef SUMMARY_CONFIG_H -#define SUMMARY_CONFIG_H - -#include "SummaryModel.h" - -#include "viewpages/ViewStep.h" - -class Config : public QObject -{ - Q_OBJECT - - ///@brief Name of this summary (generally, "Summary") - Q_PROPERTY( QString title READ title NOTIFY titleChanged ) - ///@brief Description of what the summary means - Q_PROPERTY( QString message READ message NOTIFY messageChanged ) - - Q_PROPERTY( QAbstractListModel* summaryModel READ summaryModel CONSTANT FINAL ) - -public: - explicit Config( QObject* parent = nullptr ); - - ///@brief Include widgets in the model? - enum class Widgets - { - Disabled, - Enabled - }; - - static Calamares::ViewStepList stepsForSummary( const Calamares::ViewStep* upToHere ); - - ///@brief Called later, to load the model once all viewsteps are there - void collectSummaries( const Calamares::ViewStep* upToHere, Widgets withWidgets ); - ///@brief Clear the model of steps (to avoid dangling widgets) - void clearSummaries(); - - QAbstractListModel* summaryModel() const { return m_summary; } - - QString title() const { return m_title; } - QString message() const { return m_message; } - -private: - void retranslate(); - - SummaryModel* m_summary; - - QString m_title; - QString m_message; - -Q_SIGNALS: - void titleChanged( QString title ); - void messageChanged( QString message ); -}; -#endif diff --git a/src/modules/summary/SummaryModel.cpp b/src/modules/summary/SummaryModel.cpp deleted file mode 100644 index be8b062e00..0000000000 --- a/src/modules/summary/SummaryModel.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020, Camilo Higuita - * SPDX-FileCopyrightText: 2021 Anke Boersma - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "SummaryModel.h" - -#include - -SummaryModel::SummaryModel( QObject* parent ) - : QAbstractListModel( parent ) -{ -} - -QHash< int, QByteArray > -SummaryModel::roleNames() const -{ - // Not including WidgetRole here because that wouldn't make sense - // in a QML context which is where the roleNames are important. - return { { TitleRole, "title" }, { MessageRole, "message" } }; -} - -QVariant -SummaryModel::data( const QModelIndex& index, int role ) const -{ - if ( !index.isValid() ) - { - return QVariant(); - } - auto& item = m_summary.at( index.row() ); - switch ( role ) - { - case TitleRole: - return item.title; - case MessageRole: - return item.message; - case WidgetRole: - return item.widget ? QVariant::fromValue( item.widget ) : QVariant(); - default: - return QVariant(); - } -} - -int -SummaryModel::rowCount( const QModelIndex& ) const -{ - return m_summary.count(); -} - -void -SummaryModel::setSummaryList( const Calamares::ViewStepList& steps, bool withWidgets ) -{ - beginResetModel(); - m_summary.clear(); - - for ( Calamares::ViewStep* step : steps ) - { - QString text = step->prettyStatus(); - QWidget* widget = withWidgets ? step->createSummaryWidget() : nullptr; - - if ( text.isEmpty() && !widget ) - { - continue; - } - - m_summary << StepSummary { step->prettyName(), text, widget }; - } - endResetModel(); -} diff --git a/src/modules/summary/SummaryModel.h b/src/modules/summary/SummaryModel.h deleted file mode 100644 index 919b5d5852..0000000000 --- a/src/modules/summary/SummaryModel.h +++ /dev/null @@ -1,67 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2019-2020, Adriaan de Groot - * SPDX-FileCopyrightText: 2020, Camilo Higuita - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef SUMMARY_SUMMARYMODEL_H -#define SUMMARY_SUMMARYMODEL_H - -#include "viewpages/ViewStep.h" - -#include -#include - -class Config; - -/** @brief Data for one step - * - * A step generally has a text description, but **may** have a - * QWidget. There is no ownership of the QWidget, that is assumed - * to be handed off to some owning parent-widget. - */ -struct StepSummary -{ - QString title; - QString message; - QWidget* widget = nullptr; -}; - -class SummaryModel : public QAbstractListModel -{ - Q_OBJECT - friend class Config; - -public: - enum Roles : int - { - TitleRole = Qt::DisplayRole, // Name of the step - MessageRole = Qt::UserRole, // String saying what it will do - WidgetRole, // Pointer to widget - }; - - explicit SummaryModel( QObject* parent = nullptr ); - int rowCount( const QModelIndex& = QModelIndex() ) const override; - QVariant data( const QModelIndex& index, int role ) const override; - -protected: - QHash< int, QByteArray > roleNames() const override; - -private: - /** @brief Sets the model data from @p steps - * - * Replaces the list of summaries with summaries given by - * the jobs and ViewSteps objects in @p steps. If @p withWidgets - * is @c true, then also queries for widget summaries alongside - * the text summaries for each step. - */ - void setSummaryList( const Calamares::ViewStepList& steps, bool withWidgets = false ); - - QVector< StepSummary > m_summary; -}; - -#endif diff --git a/src/modules/summary/SummaryPage.cpp b/src/modules/summary/SummaryPage.cpp deleted file mode 100644 index 41881e479e..0000000000 --- a/src/modules/summary/SummaryPage.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017 2019, Adriaan de Groot - * SPDX-FileCopyrightText: 2019 Collabora Ltd - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "SummaryPage.h" - -#include "SummaryViewStep.h" - -#include "Branding.h" -#include "Settings.h" -#include "ViewManager.h" - -#include "utils/Gui.h" -#include "utils/Logger.h" -#include "utils/QtCompat.h" -#include "utils/Retranslator.h" -#include "viewpages/ExecutionViewStep.h" - -#include -#include -#include - -SummaryPage::SummaryPage( Config* config, QWidget* parent ) - : QWidget() - , m_contentWidget( nullptr ) - , m_scrollArea( new QScrollArea( this ) ) -{ - Q_UNUSED( parent ) - - this->setObjectName( "summaryStep" ); - - QVBoxLayout* layout = new QVBoxLayout( this ); - layout->setContentsMargins( 0, 0, 0, 0 ); - - QLabel* headerLabel = new QLabel( this ); - headerLabel->setObjectName( "summaryTitle" ); - headerLabel->setText( config->message() ); - connect( config, &Config::messageChanged, headerLabel, &QLabel::setText ); - layout->addWidget( headerLabel ); - layout->addWidget( m_scrollArea ); - m_scrollArea->setWidgetResizable( true ); - m_scrollArea->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); - // If Calamares will grow, then only show scrollbar when it's needed - // (e.g. when the screen is full). - m_scrollArea->setVerticalScrollBarPolicy( - Calamares::Branding::instance()->windowExpands() ? Qt::ScrollBarAsNeeded : Qt::ScrollBarAlwaysOn ); - m_scrollArea->setFrameStyle( QFrame::NoFrame ); - m_scrollArea->setContentsMargins( 0, 0, 0, 0 ); -} - -static QLabel* -createTitleLabel( const QString& text, const QFont& titleFont ) -{ - QLabel* label = new QLabel( text ); - label->setObjectName( "summaryItemTitle" ); - label->setFont( titleFont ); - label->setContentsMargins( 0, 0, 0, 0 ); - - return label; -} - -static QLabel* -createBodyLabel( const QString& text, const QPalette& bodyPalette ) -{ - QLabel* label = new QLabel; - label->setObjectName( "summaryItemBody" ); - label->setMargin( Calamares::defaultFontHeight() / 2 ); - label->setAutoFillBackground( true ); - label->setPalette( bodyPalette ); - label->setText( text ); - return label; -} - -static QWidget* -createStepWidget( const QString& description, QWidget* innerWidget, const QPalette& palette ) -{ - QWidget* w = new QWidget(); - QHBoxLayout* itemBodyLayout = new QHBoxLayout; - w->setLayout( itemBodyLayout ); - - // Indent the inner box by a bit - itemBodyLayout->addSpacing( Calamares::defaultFontHeight() * 2 ); - QVBoxLayout* itemBodyCoreLayout = new QVBoxLayout; - itemBodyLayout->addLayout( itemBodyCoreLayout ); - Calamares::unmarginLayout( itemBodyLayout ); - - itemBodyCoreLayout->addSpacing( Calamares::defaultFontHeight() / 2 ); - if ( innerWidget ) - { - itemBodyCoreLayout->addWidget( innerWidget ); - } - else - { - itemBodyCoreLayout->addWidget( createBodyLabel( description, palette ) ); - } - - return w; -} - -static void -ensureSize( QWidget* parent, QScrollArea* container, Calamares::ViewStep* viewstep ) -{ - auto summarySize = container->widget()->sizeHint(); - if ( summarySize.height() > container->size().height() ) - { - auto enlarge = 2 + summarySize.height() - container->size().height(); - auto widgetSize = parent->size(); - widgetSize.setHeight( widgetSize.height() + enlarge ); - - cDebug() << "Summary widget is larger than viewport, enlarge by" << enlarge << "to" << widgetSize; - - emit viewstep->ensureSize( widgetSize ); // Only expand height - } -} - -// Adds a widget for those ViewSteps that want a summary; -// see SummaryPage documentation and also ViewStep docs. -void -SummaryPage::buildWidgets( Config* config, SummaryViewStep* viewstep ) -{ - const int SECTION_SPACING = 12; - - delete m_contentWidget; // It might have been created previously - m_contentWidget = new QWidget; - m_layout = new QVBoxLayout( m_contentWidget ); - Calamares::unmarginLayout( m_layout ); - - QFont titleFont = font(); - titleFont.setWeight( QFont::Light ); - titleFont.setPointSize( Calamares::defaultFontSize() * 2 ); - - QPalette bodyPalette( palette() ); - bodyPalette.setColor( WindowBackground, palette().window().color().lighter( 108 ) ); - - const auto* model = config->summaryModel(); - const auto rowCount = model->rowCount(); - - for ( int row = 0; row < rowCount; row++ ) - { - const auto rowIndex = model->index( row ); - QString title = model->data( rowIndex, SummaryModel::TitleRole ).toString(); - QString text = model->data( rowIndex, SummaryModel::MessageRole ).toString(); - QWidget* widget = model->data( rowIndex, SummaryModel::WidgetRole ).value< QWidget* >(); - - if ( text.isEmpty() && !widget ) - { - continue; - } - - if ( row > 0 ) - { - m_layout->addSpacing( SECTION_SPACING ); - } - - m_layout->addWidget( createTitleLabel( title, titleFont ) ); - m_layout->addWidget( createStepWidget( text, widget, bodyPalette ) ); - } - m_layout->addStretch(); - - m_scrollArea->setWidget( m_contentWidget ); - ensureSize( this, m_scrollArea, viewstep ); -} - -void -SummaryPage::cleanup() -{ - delete m_contentWidget; - m_contentWidget = nullptr; -} diff --git a/src/modules/summary/SummaryPage.h b/src/modules/summary/SummaryPage.h deleted file mode 100644 index 9976020f7e..0000000000 --- a/src/modules/summary/SummaryPage.h +++ /dev/null @@ -1,61 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef SUMMARYPAGE_H -#define SUMMARYPAGE_H - -#include "viewpages/ViewStep.h" - -#include - -class Config; -class SummaryViewStep; - -class QLabel; -class QScrollArea; -class QVBoxLayout; - - -/** @brief Provide a summary view with to-be-done action descriptions. -* -* Those steps that occur since the previous execution step (e.g. that -* are queued for execution now; in the normal case where there is -* only one execution step, this means everything that the installer -* is going to do) are added to the summary view. Each view step -* can provide one of the following things to display in the summary -* view: -* -* - A string from ViewStep::prettyStatus(), which is formatted -* and added as a QLabel to the view. Return an empty string -* from prettyStatus() to avoid this. -* - A QWidget from ViewStep::createSummaryWidget(). This is for -* complicated displays not suitable for simple text representation. -* Return a nullptr to avoid this. -* -* If neither a (non-empty) string nor a widget is returned, the -* step is not named in the summary. -*/ -class SummaryPage : public QWidget -{ - Q_OBJECT -public: - explicit SummaryPage( Config* config, QWidget* parent = nullptr ); - - /// @brief Create contents showing all of the summary - void buildWidgets( Config* config, SummaryViewStep* viewstep ); - /// @brief Clean up the widgets - void cleanup(); - -private: - QVBoxLayout* m_layout = nullptr; - QWidget* m_contentWidget = nullptr; - QScrollArea* m_scrollArea = nullptr; -}; - -#endif // SUMMARYPAGE_H diff --git a/src/modules/summary/SummaryViewStep.cpp b/src/modules/summary/SummaryViewStep.cpp deleted file mode 100644 index 9d63d0d374..0000000000 --- a/src/modules/summary/SummaryViewStep.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "SummaryViewStep.h" - -#include "SummaryPage.h" - -CALAMARES_PLUGIN_FACTORY_DEFINITION( SummaryViewStepFactory, registerPlugin< SummaryViewStep >(); ) - -SummaryViewStep::SummaryViewStep( QObject* parent ) - : Calamares::ViewStep( parent ) - , m_config( new Config( this ) ) - , m_widget( new SummaryPage( m_config ) ) -{ - emit nextStatusChanged( true ); -} - - -SummaryViewStep::~SummaryViewStep() -{ - if ( m_widget && m_widget->parent() == nullptr ) - { - m_widget->deleteLater(); - } - delete m_config; -} - - -QString -SummaryViewStep::prettyName() const -{ - return m_config->title(); -} - - -QWidget* -SummaryViewStep::widget() -{ - return m_widget; -} - - -bool -SummaryViewStep::isNextEnabled() const -{ - return true; -} - - -bool -SummaryViewStep::isBackEnabled() const -{ - return true; -} - - -bool -SummaryViewStep::isAtBeginning() const -{ - return true; -} - - -bool -SummaryViewStep::isAtEnd() const -{ - return true; -} - - -Calamares::JobList -SummaryViewStep::jobs() const -{ - return {}; -} - - -void -SummaryViewStep::onActivate() -{ - m_config->collectSummaries( this, Config::Widgets::Enabled ); - m_widget->buildWidgets( m_config, this ); -} - - -void -SummaryViewStep::onLeave() -{ - m_config->clearSummaries(); - m_widget->cleanup(); -} diff --git a/src/modules/summary/SummaryViewStep.h b/src/modules/summary/SummaryViewStep.h deleted file mode 100644 index e2ee0566e9..0000000000 --- a/src/modules/summary/SummaryViewStep.h +++ /dev/null @@ -1,51 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef SUMMARYPAGEPLUGIN_H -#define SUMMARYPAGEPLUGIN_H - -#include "Config.h" - -#include "DllMacro.h" -#include "utils/PluginFactory.h" -#include "viewpages/ViewStep.h" - -class SummaryPage; - -class PLUGINDLLEXPORT SummaryViewStep : public Calamares::ViewStep -{ - Q_OBJECT - -public: - explicit SummaryViewStep( QObject* parent = nullptr ); - ~SummaryViewStep() override; - - QString prettyName() const override; - - QWidget* widget() 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; - -private: - Config* m_config = nullptr; - SummaryPage* m_widget = nullptr; -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( SummaryViewStepFactory ) - -#endif // SUMMARYPAGEPLUGIN_H diff --git a/src/modules/summaryq/CMakeLists.txt b/src/modules/summaryq/CMakeLists.txt deleted file mode 100644 index 75dd68aeaf..0000000000 --- a/src/modules/summaryq/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2021 Anke Boersma -# SPDX-License-Identifier: BSD-2-Clause -# -if(NOT WITH_QML) - calamares_skip_module( "summaryq (QML is not supported in this build)" ) - return() -endif() - -set(_summary ${CMAKE_CURRENT_SOURCE_DIR}/../summary) -include_directories(${_summary}) - -calamares_add_plugin(summaryq - TYPE viewmodule - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - SummaryQmlViewStep.cpp - ${_summary}/Config.cpp - ${_summary}/SummaryModel.cpp - UI - RESOURCES - summaryq${QT_VERSION_SUFFIX}.qrc - LINK_PRIVATE_LIBRARIES - calamaresui - SHARED_LIB - NO_CONFIG -) diff --git a/src/modules/summaryq/SummaryQmlViewStep.cpp b/src/modules/summaryq/SummaryQmlViewStep.cpp deleted file mode 100644 index a5acdfddda..0000000000 --- a/src/modules/summaryq/SummaryQmlViewStep.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015, Teo Mrnjavac - * SPDX-FileCopyrightText: 2020, Camilo Higuita - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "SummaryQmlViewStep.h" - -CALAMARES_PLUGIN_FACTORY_DEFINITION( SummaryQmlViewStepFactory, registerPlugin< SummaryQmlViewStep >(); ) - -SummaryQmlViewStep::SummaryQmlViewStep( QObject* parent ) - : Calamares::QmlViewStep( parent ) - , m_config( new Config( this ) ) -{ - emit nextStatusChanged( true ); -} - - -SummaryQmlViewStep::~SummaryQmlViewStep() {} - -QString -SummaryQmlViewStep::prettyName() const -{ - return m_config->title(); -} - - -bool -SummaryQmlViewStep::isNextEnabled() const -{ - return true; -} - - -bool -SummaryQmlViewStep::isBackEnabled() const -{ - return true; -} - - -bool -SummaryQmlViewStep::isAtBeginning() const -{ - return true; -} - - -bool -SummaryQmlViewStep::isAtEnd() const -{ - return true; -} - - -Calamares::JobList -SummaryQmlViewStep::jobs() const -{ - return {}; -} - - -void -SummaryQmlViewStep::onActivate() -{ - // Collect the steps before this one: those need to have their - // summary (text or widget) displayed. - m_config->collectSummaries( this, Config::Widgets::Disabled ); -} diff --git a/src/modules/summaryq/SummaryQmlViewStep.h b/src/modules/summaryq/SummaryQmlViewStep.h deleted file mode 100644 index 8668d0afef..0000000000 --- a/src/modules/summaryq/SummaryQmlViewStep.h +++ /dev/null @@ -1,49 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015, Teo Mrnjavac - * SPDX-FileCopyrightText: 2020, Camilo Higuita - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef SUMMARYQMLVIEWSTEP_H -#define SUMMARYQMLVIEWSTEP_H - -#include "Config.h" - -#include "DllMacro.h" -#include "utils/PluginFactory.h" -#include "viewpages/QmlViewStep.h" - -class PLUGINDLLEXPORT SummaryQmlViewStep : public Calamares::QmlViewStep -{ - Q_OBJECT - -public: - explicit SummaryQmlViewStep( QObject* parent = nullptr ); - virtual ~SummaryQmlViewStep() override; - - 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; - - QObject* getConfig() override { return m_config; } - -private: - Config* m_config; -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( SummaryQmlViewStepFactory ) - -#endif // SUMMARYQMLVIEWSTEP_H diff --git a/src/modules/summaryq/img/keyboard.svg b/src/modules/summaryq/img/keyboard.svg deleted file mode 100644 index 6227b788b4..0000000000 --- a/src/modules/summaryq/img/keyboard.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/summaryq/img/keyboard.svg.license b/src/modules/summaryq/img/keyboard.svg.license deleted file mode 100644 index e59dc6f9cc..0000000000 --- a/src/modules/summaryq/img/keyboard.svg.license +++ /dev/null @@ -1,2 +0,0 @@ -SPDX-FileCopyrightText: 2021 KDE Visual Design Group -SPDX-License-Identifier: GPL-3.0-or-later diff --git a/src/modules/summaryq/img/lokalize.svg b/src/modules/summaryq/img/lokalize.svg deleted file mode 100644 index 83a7c9dcf8..0000000000 --- a/src/modules/summaryq/img/lokalize.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/summaryq/img/lokalize.svg.license b/src/modules/summaryq/img/lokalize.svg.license deleted file mode 100644 index e59dc6f9cc..0000000000 --- a/src/modules/summaryq/img/lokalize.svg.license +++ /dev/null @@ -1,2 +0,0 @@ -SPDX-FileCopyrightText: 2021 KDE Visual Design Group -SPDX-License-Identifier: GPL-3.0-or-later diff --git a/src/modules/summaryq/summaryq-qt6.qml b/src/modules/summaryq/summaryq-qt6.qml deleted file mode 100644 index 22dac588ff..0000000000 --- a/src/modules/summaryq/summaryq-qt6.qml +++ /dev/null @@ -1,111 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2021 Anke Boersma - * 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 -import QtQuick.Controls -import QtQuick.Layouts -import org.kde.kirigami as Kirigami -import QtQuick.Window - -Kirigami.ScrollablePage { - width: 860 //parent.width - height: 640 //parent.height - - Kirigami.Theme.backgroundColor: "#EFF0F1" - Kirigami.Theme.textColor: "#1F1F1F" - - header: Kirigami.Heading { - Layout.fillWidth: true - height: 100 - horizontalAlignment: Qt.AlignHCenter - color: Kirigami.Theme.textColor - font.weight: Font.Medium - font.pointSize: 12 - text: config.message - - } - - RowLayout { - width: parent.width - - Component { - id: _delegate - - Rectangle { - id: rect - border.color: "#BDC3C7" - width: parent.width - 80 - implicitHeight: message.implicitHeight + title.implicitHeight + 20 - anchors.horizontalCenter: parent.horizontalCenter - - Item { - width: parent.width - 80 - implicitHeight: message.implicitHeight + title.implicitHeight + 20 - - Kirigami.FormLayout { - - GridLayout { - anchors { - //left: parent.left - top: parent.top - right: parent.right - } - rowSpacing: Kirigami.Units.largeSpacing - columnSpacing: Kirigami.Units.largeSpacing - columns: width > Kirigami.Units.gridUnit * 20 ? 4 : 2 - - Image { - id: image - Layout.maximumHeight: Kirigami.Units.iconSizes.huge - Layout.preferredWidth: height - Layout.alignment: Qt.AlignTop - fillMode: Image.PreserveAspectFit - source: index === 0 ? "img/lokalize.svg" - : ( index === 1 ? "img/keyboard.svg" - : ( index === 2 ? "qrc:/data/images/partition-manual.svg" - : "qrc:/data/images/partition-partition.svg" ) ) - } - ColumnLayout { - - Label { - id: title - Layout.fillWidth: true - wrapMode: Text.WordWrap - text: model.title - font.weight: Font.Medium - font.pointSize: 16 - } - Rectangle { - height: 2 - width: 200 - border.color: "#BDC3C7" - } - Label { - id: message - Layout.fillWidth: true - text: model.message - } - } - } - } - } - } - } - } - - ListView { - anchors.fill: parent - spacing: 20 - model: config.summaryModel - delegate: _delegate - } -} diff --git a/src/modules/summaryq/summaryq-qt6.qrc b/src/modules/summaryq/summaryq-qt6.qrc deleted file mode 100644 index c2cfc07cc9..0000000000 --- a/src/modules/summaryq/summaryq-qt6.qrc +++ /dev/null @@ -1,7 +0,0 @@ - - - summaryq-qt6.qml - img/keyboard.svg - img/lokalize.svg - - diff --git a/src/modules/summaryq/summaryq.qml b/src/modules/summaryq/summaryq.qml deleted file mode 100644 index 626a42c406..0000000000 --- a/src/modules/summaryq/summaryq.qml +++ /dev/null @@ -1,112 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2021 Anke Boersma - * 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.13 -import QtQuick.Layouts 1.3 -import org.kde.kirigami 2.7 as Kirigami -import QtGraphicalEffects 1.0 -import QtQuick.Window 2.3 - -Kirigami.ScrollablePage { - width: 860 //parent.width //860 - height: 640 //parent.height //640 - - Kirigami.Theme.backgroundColor: "#EFF0F1" - Kirigami.Theme.textColor: "#1F1F1F" - - header: Kirigami.Heading { - Layout.fillWidth: true - height: 100 - horizontalAlignment: Qt.AlignHCenter - color: Kirigami.Theme.textColor - font.weight: Font.Medium - font.pointSize: 12 - text: config.message - - } - - RowLayout { - width: parent.width - - Component { - id: _delegate - - Rectangle { - id: rect - border.color: "#BDC3C7" - width: parent.width - 80 - implicitHeight: message.implicitHeight + title.implicitHeight + 20 - anchors.horizontalCenter: parent.horizontalCenter - - Item { - width: parent.width - 80 - implicitHeight: message.implicitHeight + title.implicitHeight + 20 - - Kirigami.FormLayout { - - GridLayout { - anchors { - //left: parent.left - top: parent.top - right: parent.right - } - rowSpacing: Kirigami.Units.largeSpacing - columnSpacing: Kirigami.Units.largeSpacing - columns: width > Kirigami.Units.gridUnit * 20 ? 4 : 2 - - Image { - id: image - Layout.maximumHeight: Kirigami.Units.iconSizes.huge - Layout.preferredWidth: height - Layout.alignment: Qt.AlignTop - fillMode: Image.PreserveAspectFit - source: index === 0 ? "img/lokalize.svg" - : ( index === 1 ? "img/keyboard.svg" - : ( index === 2 ? "qrc:/data/images/partition-manual.svg" - : "qrc:/data/images/partition-partition.svg" ) ) - } - ColumnLayout { - - Label { - id: title - Layout.fillWidth: true - wrapMode: Text.WordWrap - text: model.title - font.weight: Font.Medium - font.pointSize: 16 - } - Rectangle { - height: 2 - width: 200 - border.color: "#BDC3C7" - } - Label { - id: message - Layout.fillWidth: true - text: model.message - } - } - } - } - } - } - } - } - - ListView { - anchors.fill: parent - spacing: 20 - model: config.summaryModel - delegate: _delegate - } -} diff --git a/src/modules/summaryq/summaryq.qrc b/src/modules/summaryq/summaryq.qrc deleted file mode 100644 index 62bfe78995..0000000000 --- a/src/modules/summaryq/summaryq.qrc +++ /dev/null @@ -1,7 +0,0 @@ - - - summaryq.qml - img/keyboard.svg - img/lokalize.svg - - diff --git a/src/modules/tracking/CMakeLists.txt b/src/modules/tracking/CMakeLists.txt deleted file mode 100644 index b54bd1430a..0000000000 --- a/src/modules/tracking/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# -calamares_add_plugin(tracking - TYPE viewmodule - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - Config.cpp - TrackingJobs.cpp - TrackingPage.cpp - TrackingViewStep.cpp - UI - page_trackingstep.ui - RESOURCES - page_trackingstep.qrc - SHARED_LIB - LINK_LIBRARIES - ${kfname}::CoreAddons -) - -calamares_add_test(trackingtest SOURCES Tests.cpp Config.cpp) diff --git a/src/modules/tracking/Config.cpp b/src/modules/tracking/Config.cpp deleted file mode 100644 index 58c4f63aec..0000000000 --- a/src/modules/tracking/Config.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "Config.h" - -#include "TrackingType.h" - -#include "utils/Logger.h" -#include "utils/Variant.h" - -#include - -const NamedEnumTable< TrackingType >& -trackingNames() -{ - // *INDENT-OFF* - // clang-format off - static const NamedEnumTable< TrackingType > names { - { QStringLiteral( "none" ), TrackingType::NoTracking }, - { QStringLiteral( "install" ), TrackingType::InstallTracking }, - { QStringLiteral( "machine" ), TrackingType::MachineTracking }, - { QStringLiteral( "user" ), TrackingType::UserTracking } - }; - // clang-format on - // *INDENT-ON* - - return names; -} - -TrackingStyleConfig::TrackingStyleConfig( QObject* parent ) - : QObject( parent ) -{ -} - -TrackingStyleConfig::~TrackingStyleConfig() {} - -void -TrackingStyleConfig::setTracking( bool enabled ) -{ - setTracking( enabled ? EnabledByUser : DisabledByUser ); -} - -void -TrackingStyleConfig::setTracking( TrackingStyleConfig::TrackingState state ) -{ - if ( m_state != TrackingState::DisabledByConfig ) - { - m_state = state; - } - emit trackingChanged(); -} - -void -TrackingStyleConfig::validate( QString& s, std::function< bool( const QString& ) >&& pred ) -{ - if ( !pred( s ) ) - { - if ( m_state != DisabledByConfig ) - { - cError() << "Configuration string" << s << "is not valid; disabling this tracking type."; - m_state = DisabledByConfig; - emit trackingChanged(); - } - s = QString(); - } -} - -void -TrackingStyleConfig::validateUrl( QString& urlString ) -{ - if ( !QUrl( urlString ).isValid() ) - { - if ( m_state != DisabledByConfig ) - { - cError() << "URL" << urlString << "is not valid; disabling tracking type" << objectName(); - m_state = DisabledByConfig; - emit trackingChanged(); - } - urlString = QString(); - } -} - -void -TrackingStyleConfig::setConfigurationMap( const QVariantMap& config ) -{ - m_state = Calamares::getBool( config, "enabled", false ) ? DisabledByUser : DisabledByConfig; - m_policy = Calamares::getString( config, "policy" ); - validateUrl( m_policy ); - emit policyChanged( m_policy ); - emit trackingChanged(); -} - -InstallTrackingConfig::InstallTrackingConfig( QObject* parent ) - : TrackingStyleConfig( parent ) -{ - setObjectName( "InstallTrackingConfig" ); -} - -InstallTrackingConfig::~InstallTrackingConfig() {} - -void -InstallTrackingConfig::setConfigurationMap( const QVariantMap& configurationMap ) -{ - TrackingStyleConfig::setConfigurationMap( configurationMap ); - - m_installTrackingUrl = Calamares::getString( configurationMap, "url" ); - validateUrl( m_installTrackingUrl ); -} - -MachineTrackingConfig::MachineTrackingConfig( QObject* parent ) - : TrackingStyleConfig( parent ) -{ - setObjectName( "MachineTrackingConfig" ); -} - -MachineTrackingConfig::~MachineTrackingConfig() {} - -/** @brief Is @p s a valid machine-tracking style. */ -static bool -isValidMachineTrackingStyle( const QString& s ) -{ - static QStringList knownStyles { "updatemanager" }; - return knownStyles.contains( s ); -} - -void -MachineTrackingConfig::setConfigurationMap( const QVariantMap& configurationMap ) -{ - TrackingStyleConfig::setConfigurationMap( configurationMap ); - - m_machineTrackingStyle = Calamares::getString( configurationMap, "style" ); - validate( m_machineTrackingStyle, isValidMachineTrackingStyle ); -} - -UserTrackingConfig::UserTrackingConfig( QObject* parent ) - : TrackingStyleConfig( parent ) -{ - setObjectName( "UserTrackingConfig" ); -} - -UserTrackingConfig::~UserTrackingConfig() {} - -static bool -isValidUserTrackingStyle( const QString& s ) -{ - static QStringList knownStyles { "kuserfeedback" }; - return knownStyles.contains( s ); -} - -void -UserTrackingConfig::setConfigurationMap( const QVariantMap& configurationMap ) -{ - TrackingStyleConfig::setConfigurationMap( configurationMap ); - - m_userTrackingStyle = Calamares::getString( configurationMap, "style" ); - validate( m_userTrackingStyle, isValidUserTrackingStyle ); - - m_userTrackingAreas = Calamares::getStringList( configurationMap, "areas" ); -} - -Config::Config( QObject* parent ) - : QObject( parent ) - , m_installTracking( new InstallTrackingConfig( this ) ) - , m_machineTracking( new MachineTrackingConfig( this ) ) - , m_userTracking( new UserTrackingConfig( this ) ) -{ -} - -static void -enableLevelsBelow( Config* config, TrackingType level ) -{ - switch ( level ) - { - case TrackingType::UserTracking: - config->userTracking()->setTracking( TrackingStyleConfig::TrackingState::EnabledByUser ); - [[fallthrough]]; - case TrackingType::MachineTracking: - config->machineTracking()->setTracking( TrackingStyleConfig::TrackingState::EnabledByUser ); - [[fallthrough]]; - case TrackingType::InstallTracking: - config->installTracking()->setTracking( TrackingStyleConfig::TrackingState::EnabledByUser ); - break; - case TrackingType::NoTracking: - config->noTracking( true ); - break; - } -} - -void -Config::setConfigurationMap( const QVariantMap& configurationMap ) -{ - m_generalPolicy = Calamares::getString( configurationMap, "policy" ); - - if ( !QUrl( m_generalPolicy ).isValid() ) - { - m_generalPolicy = QString(); - } - emit generalPolicyChanged( m_generalPolicy ); - - bool success = false; - auto subconfig = Calamares::getSubMap( configurationMap, "install", success ); - if ( success ) - { - m_installTracking->setConfigurationMap( subconfig ); - } - - subconfig = Calamares::getSubMap( configurationMap, "machine", success ); - if ( success ) - { - m_machineTracking->setConfigurationMap( subconfig ); - } - - subconfig = Calamares::getSubMap( configurationMap, "user", success ); - if ( success ) - { - m_userTracking->setConfigurationMap( subconfig ); - } - - auto level = trackingNames().find( Calamares::getString( configurationMap, "default" ), success ); - if ( !success ) - { - cWarning() << "Default tracking level unknown:" << Calamares::getString( configurationMap, "default" ); - level = TrackingType::NoTracking; - } - enableLevelsBelow( this, level ); -} - -QString -Config::generalPolicy() const -{ - return m_generalPolicy; -} - -void -Config::noTracking( bool switchOffAllTracking ) -{ - if ( !switchOffAllTracking ) - { - return; - } - m_installTracking->setTracking( TrackingStyleConfig::TrackingState::DisabledByUser ); - m_machineTracking->setTracking( TrackingStyleConfig::TrackingState::DisabledByUser ); - m_userTracking->setTracking( TrackingStyleConfig::TrackingState::DisabledByUser ); -} diff --git a/src/modules/tracking/Config.h b/src/modules/tracking/Config.h deleted file mode 100644 index c91d430f56..0000000000 --- a/src/modules/tracking/Config.h +++ /dev/null @@ -1,186 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef TRACKING_CONFIG_H -#define TRACKING_CONFIG_H - -#include -#include -#include - -/** @brief Base class for configuring a specific kind of tracking. - * - * All tracking types have a policy URL, which is used to explain what - * kind of tracking is involved, what data is sent, etc. The content - * of that URL is the responsibility of the distro. - * - * A tracking type is disabled by default: if it isn't specifically - * enabled (for configuration) in the config file, it will always be disabled. - * If it is enabled (for configuration) in the config file, it still - * defaults to disabled, but the user can choose to enable it. - */ -class TrackingStyleConfig : public QObject -{ - Q_OBJECT - - Q_PROPERTY( TrackingState trackingStatus READ tracking WRITE setTracking NOTIFY trackingChanged FINAL ) - Q_PROPERTY( bool isEnabled READ isEnabled NOTIFY trackingChanged FINAL ) - Q_PROPERTY( bool isConfigurable READ isConfigurable NOTIFY trackingChanged FINAL ) - Q_PROPERTY( QString policy READ policy NOTIFY policyChanged FINAL ) - -public: - TrackingStyleConfig( QObject* parent ); - ~TrackingStyleConfig() override; - - void setConfigurationMap( const QVariantMap& ); - - enum TrackingState - { - DisabledByConfig, - DisabledByUser, - EnabledByUser - }; - Q_ENUM( TrackingState ) - -public Q_SLOTS: - TrackingState tracking() const { return m_state; } - /// @brief Has the user specifically enabled this kind of tracking? - bool isEnabled() const { return m_state == EnabledByUser; } - /// @brief Is this tracking enabled for configuration? - bool isConfigurable() const { return m_state != DisabledByConfig; } - /** @brief Sets the tracking state - * - * Unless the tracking is enabled for configuration, it always - * remains disabled. - */ - void setTracking( TrackingState ); - /** @brief Sets the tracking state - * - * Use @c true for @c EnabledByUser, @c false for DisabledByUser, - * but keep in mind that if the tracking is not enabled for - * configuration, it will always remain disabled. - */ - void setTracking( bool ); - - /// @brief URL for the policy explaining this tracking - QString policy() const { return m_policy; } - -signals: - void trackingChanged(); - void policyChanged( QString ); - -protected: - /// @brief Validates the @p urlString, disables tracking if invalid - void validateUrl( QString& urlString ); - /// @brief Validates the @p string, disables tracking if invalid - void validate( QString& s, std::function< bool( const QString& s ) >&& pred ); - -private: - TrackingState m_state = DisabledByConfig; - QString m_policy; // URL -}; - -/** @brief Install tracking pings a URL at the end of installation - * - * Install tracking will do a single GET on the given URL at - * the end of installation. The information included in the GET - * request depends on the URL configuration, see also the tracking - * jobs. - */ -class InstallTrackingConfig : public TrackingStyleConfig -{ -public: - InstallTrackingConfig( QObject* parent ); - ~InstallTrackingConfig() override; - void setConfigurationMap( const QVariantMap& configurationMap ); - - QString installTrackingUrl() { return m_installTrackingUrl; } - -private: - QString m_installTrackingUrl; -}; - -/** @brief Machine tracking reports from the installed system - * - * When machine tracking is on, the installed system will report - * back ("call home") at some point. This can mean Debian pop-con, - * or updatemanager maching tracking, or something else. The kind - * of configuration depends on the style of tracking that is enabled. - */ -class MachineTrackingConfig : public TrackingStyleConfig -{ -public: - MachineTrackingConfig( QObject* parent ); - ~MachineTrackingConfig() override; - void setConfigurationMap( const QVariantMap& configurationMap ); - - QString machineTrackingStyle() { return m_machineTrackingStyle; } - -private: - QString m_machineTrackingStyle; -}; - -/** @brief User tracking reports user actions - * - * When user tracking is on, it is enabled for the user configured - * in Calamares -- not for users created afterwards in the target - * system, unless the target system defaults to tracking them. - * The kind of user tracking depends on the target system and - * environment; KDE user tracking is one example, which can be - * configured in a fine-grained way and defaults to off. - */ -class UserTrackingConfig : public TrackingStyleConfig -{ -public: - UserTrackingConfig( QObject* parent ); - ~UserTrackingConfig() override; - void setConfigurationMap( const QVariantMap& configurationMap ); - - QString userTrackingStyle() { return m_userTrackingStyle; } - QStringList userTrackingAreas() const { return m_userTrackingAreas; } - -private: - QString m_userTrackingStyle; - QStringList m_userTrackingAreas; // fine-grained areas -}; - -class Config : public QObject -{ - Q_OBJECT - Q_PROPERTY( QString generalPolicy READ generalPolicy NOTIFY generalPolicyChanged FINAL ) - Q_PROPERTY( TrackingStyleConfig* installTracking READ installTracking FINAL ) - Q_PROPERTY( TrackingStyleConfig* machineTracking READ machineTracking FINAL ) - Q_PROPERTY( TrackingStyleConfig* userTracking READ userTracking FINAL ) - -public: - Config( QObject* parent = nullptr ); - void setConfigurationMap( const QVariantMap& ); - -public Q_SLOTS: - QString generalPolicy() const; - - InstallTrackingConfig* installTracking() const { return m_installTracking; } - MachineTrackingConfig* machineTracking() const { return m_machineTracking; } - UserTrackingConfig* userTracking() const { return m_userTracking; } - - /// @brief Call with @c true to turn off all the trackings - void noTracking( bool ); - -signals: - void generalPolicyChanged( QString ); - -private: - QString m_generalPolicy; - - InstallTrackingConfig* m_installTracking; - MachineTrackingConfig* m_machineTracking; - UserTrackingConfig* m_userTracking; -}; - -#endif diff --git a/src/modules/tracking/Tests.cpp b/src/modules/tracking/Tests.cpp deleted file mode 100644 index c3fe90ad16..0000000000 --- a/src/modules/tracking/Tests.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -#include "Config.h" - -#include "utils/Logger.h" - -#include -#include - -class TrackingTests : public QObject -{ - Q_OBJECT -public: - TrackingTests(); - ~TrackingTests() override; - -private Q_SLOTS: - void initTestCase(); - void testEmptyConfig(); -}; - -TrackingTests::TrackingTests() - : QObject() -{ -} - -TrackingTests::~TrackingTests() {} - -void -TrackingTests::initTestCase() -{ - Logger::setupLogLevel( Logger::LOGDEBUG ); - cDebug() << "Tracking test started."; -} - -void -TrackingTests::testEmptyConfig() -{ - Logger::setupLogLevel( Logger::LOGDEBUG ); - - Config* c = new Config; - QVERIFY( c->generalPolicy().isEmpty() ); - QVERIFY( c->installTracking() ); // not-nullptr - - cDebug() << "Install" << Logger::Pointer( c->installTracking() ); - - delete c; // also deletes the owned tracking-configs -} - - -QTEST_GUILESS_MAIN( TrackingTests ) - -#include "utils/moc-warnings.h" - -#include "Tests.moc" diff --git a/src/modules/tracking/TrackingJobs.cpp b/src/modules/tracking/TrackingJobs.cpp deleted file mode 100644 index 53a97b702c..0000000000 --- a/src/modules/tracking/TrackingJobs.cpp +++ /dev/null @@ -1,301 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2017-2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "TrackingJobs.h" - -#include "Config.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "network/Manager.h" -#include "utils/Logger.h" -#include "utils/System.h" - -#include - -#include - -#include - -// Namespace keeps all the actual jobs anonymous, the -// public API is the addJob() functions below the namespace. -namespace -{ - -/** @brief Install-tracking job (gets a URL) - * - * The install-tracking job (there is only one kind) does a GET - * on a configured URL with some additional information about - * the machine (if configured into the URL). - * - * No persistent tracking is done. - */ -class TrackingInstallJob : public Calamares::Job -{ -public: - TrackingInstallJob( const QString& url ); - ~TrackingInstallJob() override; - - QString prettyName() const override; - QString prettyStatusMessage() const override; - Calamares::JobResult exec() override; - -private: - const QString m_url; -}; - -/** @brief Tracking machines, update-manager style - * - * The machine has a machine-id, and this is sed(1)'ed into the - * update-manager configuration, to report the machine-id back - * to distro servers. - */ -class TrackingMachineUpdateManagerJob : public Calamares::Job -{ -public: - ~TrackingMachineUpdateManagerJob() override; - - QString prettyName() const override; - QString prettyStatusMessage() const override; - Calamares::JobResult exec() override; -}; - -/** @brief Turn on KUserFeedback in target system - * - * This writes suitable files for turning on KUserFeedback for the - * normal user configured in Calamares. The feedback can be reconfigured - * by the user through Plasma's user-feedback dialog. - */ -class TrackingKUserFeedbackJob : public Calamares::Job -{ -public: - TrackingKUserFeedbackJob( const QString& username, const QStringList& areas ); - ~TrackingKUserFeedbackJob() override; - - QString prettyName() const override; - QString prettyStatusMessage() const override; - Calamares::JobResult exec() override; - -private: - QString m_username; - QStringList m_areas; -}; - -TrackingInstallJob::TrackingInstallJob( const QString& url ) - : m_url( url ) -{ -} - -TrackingInstallJob::~TrackingInstallJob() {} - -QString -TrackingInstallJob::prettyName() const -{ - return QCoreApplication::translate( "TrackingInstallJob", "Installation feedback" ); -} - -QString -TrackingInstallJob::prettyStatusMessage() const -{ - return QCoreApplication::translate( "TrackingInstallJob", "Sending installation feedback…", "@status" ); -} - -Calamares::JobResult -TrackingInstallJob::exec() -{ - using Calamares::Network::Manager; - using Calamares::Network::RequestOptions; - using Calamares::Network::RequestStatus; - - auto result - = Manager().synchronousPing( QUrl( m_url ), - RequestOptions( RequestOptions::FollowRedirect | RequestOptions::FakeUserAgent, - RequestOptions::milliseconds( 5000 ) ) ); - if ( result.status == RequestStatus::Timeout ) - { - cWarning() << "install-tracking request timed out."; - return Calamares::JobResult::error( - QCoreApplication::translate( "TrackingInstallJob", "Internal error in install-tracking." ), - QCoreApplication::translate( "TrackingInstallJob", "HTTP request timed out." ) ); - } - return Calamares::JobResult::ok(); -} - -TrackingMachineUpdateManagerJob::~TrackingMachineUpdateManagerJob() {} - -QString -TrackingMachineUpdateManagerJob::prettyName() const -{ - return QCoreApplication::translate( "TrackingMachineUpdateManagerJob", "Machine feedback" ); -} - -QString -TrackingMachineUpdateManagerJob::prettyStatusMessage() const -{ - return QCoreApplication::translate( "TrackingMachineUpdateManagerJob", "Configuring machine feedback…", "@status" ); -} - -Calamares::JobResult -TrackingMachineUpdateManagerJob::exec() -{ - static const auto script = QStringLiteral( - "sed -i '/^URI/s,${MACHINE_ID},'`cat /etc/machine-id`',' /etc/update-manager/meta-release || true" ); - - auto res = Calamares::System::instance()->runCommand( Calamares::System::RunLocation::RunInTarget, - QStringList { QStringLiteral( "/bin/sh" ) }, - QString(), // Working dir - script, // standard input - std::chrono::seconds( 1 ) ); - int r = res.first; - - if ( r == 0 ) - { - return Calamares::JobResult::ok(); - } - else if ( r > 0 ) - { - return Calamares::JobResult::error( - QCoreApplication::translate( "TrackingMachineUpdateManagerJob", - "Error in machine feedback configuration." ), - QCoreApplication::translate( "TrackingMachineUpdateManagerJob", - "Could not configure machine feedback correctly, script error %1." ) - .arg( r ) ); - } - else - { - return Calamares::JobResult::error( - QCoreApplication::translate( "TrackingMachineUpdateManagerJob", - "Error in machine feedback configuration." ), - QCoreApplication::translate( "TrackingMachineUpdateManagerJob", - "Could not configure machine feedback correctly, Calamares error %1." ) - .arg( r ) ); - } -} - -TrackingKUserFeedbackJob::TrackingKUserFeedbackJob( const QString& username, const QStringList& areas ) - : m_username( username ) - , m_areas( areas ) -{ -} - -TrackingKUserFeedbackJob::~TrackingKUserFeedbackJob() {} - -QString -TrackingKUserFeedbackJob::prettyName() const -{ - return QCoreApplication::translate( "TrackingKUserFeedbackJob", "KDE user feedback" ); -} - -QString -TrackingKUserFeedbackJob::prettyStatusMessage() const -{ - return QCoreApplication::translate( "TrackingKUserFeedbackJob", "Configuring KDE user feedback…", "@status" ); -} - -Calamares::JobResult -TrackingKUserFeedbackJob::exec() -{ - // This is the contents of a config file to turn on some kind - // of KUserFeedback tracking; the level (16) is chosen for minimal - // but not zero tracking. - static const char config[] = R"x([Global] -FeedbackLevel=16 -)x"; - - for ( const QString& area : m_areas ) - { - QString path = QStringLiteral( "/home/%1/.config/%2" ).arg( m_username, area ); - cDebug() << "Configuring KUserFeedback" << path; - - int r = Calamares::System::instance()->createTargetFile( path, config ); - if ( r > 0 ) - { - return Calamares::JobResult::error( - QCoreApplication::translate( "TrackingKUserFeedbackJob", "Error in KDE user feedback configuration." ), - QCoreApplication::translate( "TrackingKUserFeedbackJob", - "Could not configure KDE user feedback correctly, script error %1." ) - .arg( r ) ); - } - else if ( r < 0 ) - { - return Calamares::JobResult::error( - QCoreApplication::translate( "TrackingKUserFeedbackJob", "Error in KDE user feedback configuration." ), - QCoreApplication::translate( "TrackingKUserFeedbackJob", - "Could not configure KDE user feedback correctly, Calamares error %1." ) - .arg( r ) ); - } - } - - return Calamares::JobResult::ok(); -} - -} // namespace - -void -addJob( Calamares::JobList& list, InstallTrackingConfig* config ) -{ - if ( config->isEnabled() ) - { - const auto* s = Calamares::System::instance(); - QHash< QString, QString > map { std::initializer_list< std::pair< QString, QString > > { - { QStringLiteral( "CPU" ), s->getCpuDescription() }, - { QStringLiteral( "MEMORY" ), QString::number( s->getTotalMemoryB().first ) }, - { QStringLiteral( "DISK" ), QString::number( s->getTotalDiskB() ) } } }; - QString installUrl = KMacroExpander::expandMacros( config->installTrackingUrl(), map ); - - cDebug() << Logger::SubEntry << "install-tracking URL" << installUrl; - - list.append( Calamares::job_ptr( new TrackingInstallJob( installUrl ) ) ); - } -} - -void -addJob( Calamares::JobList& list, MachineTrackingConfig* config ) -{ - if ( config->isEnabled() ) - { - const auto style = config->machineTrackingStyle(); - if ( style == "updatemanager" ) - { - list.append( Calamares::job_ptr( new TrackingMachineUpdateManagerJob() ) ); - } - else - { - cWarning() << "Unsupported machine tracking style" << style; - } - } -} - - -void -addJob( Calamares::JobList& list, UserTrackingConfig* config ) -{ - if ( config->isEnabled() ) - { - const auto* gs = Calamares::JobQueue::instance()->globalStorage(); - static const auto key = QStringLiteral( "username" ); - QString username = ( gs && gs->contains( key ) ) ? gs->value( key ).toString() : QString(); - - if ( username.isEmpty() ) - { - cWarning() << "No username is set in GlobalStorage, skipping user-tracking."; - return; - } - - const auto style = config->userTrackingStyle(); - if ( style == "kuserfeedback" ) - { - list.append( Calamares::job_ptr( new TrackingKUserFeedbackJob( username, config->userTrackingAreas() ) ) ); - } - else - { - cWarning() << "Unsupported user tracking style" << style; - } - } -} diff --git a/src/modules/tracking/TrackingJobs.h b/src/modules/tracking/TrackingJobs.h deleted file mode 100644 index 4a6e90c316..0000000000 --- a/src/modules/tracking/TrackingJobs.h +++ /dev/null @@ -1,37 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2017-2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef TRACKING_TRACKINGJOBS_H -#define TRACKING_TRACKINGJOBS_H - -#include "Job.h" - -class InstallTrackingConfig; -class MachineTrackingConfig; -class UserTrackingConfig; - -/** @section Tracking Jobs - * - * The tracking jobs do the actual work of configuring tracking on the - * target machine. Tracking jobs may have *styles*, variations depending - * on the distro or environment of the target system. At the root of - * each family of tracking jobs (installation, machine, user) there is - * free function `addJob()` that takes the configuration - * information from the relevant Config sub-object and optionally - * adds the right job (subclass!) to the list of jobs. - * - * There are no job-classes defined here because you need to be using the - * `addJob()` interface instead. - */ - -void addJob( Calamares::JobList& list, InstallTrackingConfig* config ); -void addJob( Calamares::JobList& list, MachineTrackingConfig* config ); -void addJob( Calamares::JobList& list, UserTrackingConfig* config ); - -#endif diff --git a/src/modules/tracking/TrackingPage.cpp b/src/modules/tracking/TrackingPage.cpp deleted file mode 100644 index df4b52385c..0000000000 --- a/src/modules/tracking/TrackingPage.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2017-2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "TrackingPage.h" - -#include "Config.h" -#include "ui_page_trackingstep.h" - -#include "Branding.h" -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "ViewManager.h" -#include "utils/Gui.h" -#include "utils/Logger.h" -#include "utils/Retranslator.h" - -#include -#include - -TrackingPage::TrackingPage( Config* config, QWidget* parent ) - : QWidget( parent ) - , ui( new Ui::TrackingPage ) -{ - ui->setupUi( this ); - CALAMARES_RETRANSLATE_SLOT( &TrackingPage::retranslate ); - - ui->noneCheckBox->setChecked( true ); - ui->noneCheckBox->setEnabled( false ); - connect( ui->noneCheckBox, &QCheckBox::stateChanged, this, &TrackingPage::buttonNoneChecked ); - - // Each "panel" of configuration has the same kind of setup, - // where the xButton and xCheckBox is connected to the xTracking - // configuration object; that takes macro-trickery, unfortunately. -#define trackingSetup( x ) \ - do \ - { \ - connect( ui->x##CheckBox, &QCheckBox::stateChanged, this, &TrackingPage::buttonChecked ); \ - connect( ui->x##CheckBox, \ - &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 ); \ - } \ - } ); \ - } while ( false ) - - trackingSetup( install ); - trackingSetup( machine ); - trackingSetup( user ); - -#undef trackingSetup - - connect( config, - &Config::generalPolicyChanged, - [ this ]( const QString& url ) { this->ui->generalPolicyLabel->setVisible( !url.isEmpty() ); } ); - connect( ui->generalPolicyLabel, - &QLabel::linkActivated, - [ config ] - { - QString url( config->generalPolicy() ); - if ( !url.isEmpty() ) - { - QDesktopServices::openUrl( url ); - } - } ); - - retranslate(); -} - -void -TrackingPage::retranslate() -{ - QString product = Calamares::Branding::instance()->shortProductName(); - ui->retranslateUi( this ); - ui->generalExplanation->setText( - tr( "Tracking helps %1 to see how often it is installed, what hardware it is installed on and " - "which applications are used. To see what " - "will be sent, please click the help icon next to each area." ) - .arg( product ) ); - ui->installExplanation->setText( - tr( "By selecting this you will send information about your installation and hardware. This information " - "will only be sent once after the installation finishes." ) ); - ui->machineExplanation->setText( - tr( "By selecting this you will periodically send information about your machine installation, " - "hardware and applications, to %1." ) - .arg( product ) ); - ui->userExplanation->setText( - tr( "By selecting this you will regularly send information about your " - "user installation, hardware, applications and application usage patterns, to %1." ) - .arg( product ) ); -} - -bool -TrackingPage::anyOtherChecked() const -{ - return ui->installCheckBox->isChecked() || ui->machineCheckBox->isChecked() || ui->userCheckBox->isChecked(); -} - - -void -TrackingPage::buttonNoneChecked( int state ) -{ - if ( state ) - { - cDebug() << "Unchecking all other buttons because 'None' was checked"; - ui->installCheckBox->setChecked( false ); - ui->machineCheckBox->setChecked( false ); - ui->userCheckBox->setChecked( false ); - ui->noneCheckBox->setEnabled( false ); - } -} - -void -TrackingPage::buttonChecked( int state ) -{ - if ( state ) - { - // Can't have none checked, if another one is - ui->noneCheckBox->setEnabled( true ); - ui->noneCheckBox->setChecked( false ); - } - else - { - if ( !anyOtherChecked() ) - { - ui->noneCheckBox->setChecked( true ); - ui->noneCheckBox->setEnabled( false ); - } - } -} - -void -TrackingPage::trackerChanged( TrackingStyleConfig* config, QWidget* panel, QCheckBox* check ) -{ - panel->setVisible( config->isConfigurable() ); - check->setChecked( config->isEnabled() ); -} diff --git a/src/modules/tracking/TrackingPage.h b/src/modules/tracking/TrackingPage.h deleted file mode 100644 index d9c5a3ec17..0000000000 --- a/src/modules/tracking/TrackingPage.h +++ /dev/null @@ -1,69 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2017 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef TRACKINGPAGE_H -#define TRACKINGPAGE_H - -#include "TrackingType.h" - -#include -#include -#include - -namespace Ui -{ -class TrackingPage; -} // namespace Ui - -class Config; -class TrackingStyleConfig; - -class TrackingPage : public QWidget -{ - Q_OBJECT -public: - explicit TrackingPage( Config* config, QWidget* parent = nullptr ); - - /** @brief is any of the enable-tracking buttons checked? - * - * Returns true if any one or more of install, machine or user - * tracking is enabled. - */ - bool anyOtherChecked() const; - -public Q_SLOTS: - void retranslate(); - - /** @brief When the *no tracking* checkbox is changed - * - * @p state will be non-zero when the box is checked; this - * **unchecks** all the other boxes. - */ - void buttonNoneChecked( int state ); - - /** @brief Some other checkbox changed - * - * This may check the *none* button if all the others are - * now unchecked. - */ - void buttonChecked( int state ); - -private: - /** @brief Apply the tracking configuration to the UI - * - * If the config cannot be changed (disabled in config) then - * hide the UI parts on the @p panel; otherwise show it - * and set @p check state to whether the user has enabled it. - */ - void trackerChanged( TrackingStyleConfig* subconfig, QWidget* panel, QCheckBox* check ); - - Ui::TrackingPage* ui; -}; - -#endif //TRACKINGPAGE_H diff --git a/src/modules/tracking/TrackingType.h b/src/modules/tracking/TrackingType.h deleted file mode 100644 index 81af346887..0000000000 --- a/src/modules/tracking/TrackingType.h +++ /dev/null @@ -1,26 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2017 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef TRACKINGTYPE_H -#define TRACKINGTYPE_H - -#include "utils/NamedEnum.h" - -enum class TrackingType -{ - NoTracking, // Do not enable tracking at all - InstallTracking, // Track that *this* install has happened - MachineTracking, // Track the machine, ongoing - UserTracking // Track the user, ongoing -}; - -// Implemented in Config.cpp -const NamedEnumTable< TrackingType >& trackingNames(); - -#endif //TRACKINGTYPE_H diff --git a/src/modules/tracking/TrackingViewStep.cpp b/src/modules/tracking/TrackingViewStep.cpp deleted file mode 100644 index 37f2912c34..0000000000 --- a/src/modules/tracking/TrackingViewStep.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2017 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "TrackingViewStep.h" - -#include "Config.h" -#include "TrackingJobs.h" -#include "TrackingPage.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" - -#include "utils/Logger.h" -#include "utils/System.h" -#include "utils/Variant.h" - -#include -#include - -CALAMARES_PLUGIN_FACTORY_DEFINITION( TrackingViewStepFactory, registerPlugin< TrackingViewStep >(); ) - -TrackingViewStep::TrackingViewStep( QObject* parent ) - : Calamares::ViewStep( parent ) - , m_config( new Config( this ) ) - , m_widget( new TrackingPage( m_config ) ) -{ - emit nextStatusChanged( false ); -} - - -TrackingViewStep::~TrackingViewStep() -{ - if ( m_widget && m_widget->parent() == nullptr ) - { - m_widget->deleteLater(); - } -} - - -QString -TrackingViewStep::prettyName() const -{ - return tr( "Feedback", "@title" ); -} - - -QWidget* -TrackingViewStep::widget() -{ - return m_widget; -} - - -bool -TrackingViewStep::isNextEnabled() const -{ - return true; -} - - -bool -TrackingViewStep::isBackEnabled() const -{ - return true; -} - - -bool -TrackingViewStep::isAtBeginning() const -{ - return true; -} - - -bool -TrackingViewStep::isAtEnd() const -{ - return true; -} - - -void -TrackingViewStep::onLeave() -{ - cDebug() << "Install tracking:" << m_config->installTracking()->isEnabled(); - cDebug() << Logger::SubEntry << "Machine tracking:" << m_config->machineTracking()->isEnabled(); - cDebug() << Logger::SubEntry << " User tracking:" << m_config->userTracking()->isEnabled(); -} - - -Calamares::JobList -TrackingViewStep::jobs() const -{ - cDebug() << "Creating tracking jobs .."; - - Calamares::JobList l; - addJob( l, m_config->installTracking() ); - addJob( l, m_config->machineTracking() ); - addJob( l, m_config->userTracking() ); - cDebug() << Logger::SubEntry << l.count() << "jobs queued."; - return l; -} - - -void -TrackingViewStep::setConfigurationMap( const QVariantMap& configurationMap ) -{ - m_config->setConfigurationMap( configurationMap ); -} diff --git a/src/modules/tracking/TrackingViewStep.h b/src/modules/tracking/TrackingViewStep.h deleted file mode 100644 index 0601dde570..0000000000 --- a/src/modules/tracking/TrackingViewStep.h +++ /dev/null @@ -1,57 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2017 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef TRACKINGVIEWSTEP_H -#define TRACKINGVIEWSTEP_H - -#include "TrackingType.h" - -#include "DllMacro.h" -#include "utils/PluginFactory.h" -#include "viewpages/ViewStep.h" - -#include -#include -#include - -class Config; -class TrackingPage; - -class PLUGINDLLEXPORT TrackingViewStep : public Calamares::ViewStep -{ - Q_OBJECT - -public: - explicit TrackingViewStep( QObject* parent = nullptr ); - ~TrackingViewStep() override; - - QString prettyName() const override; - - QWidget* widget() override; - - bool isNextEnabled() const override; - bool isBackEnabled() const override; - - bool isAtBeginning() const override; - bool isAtEnd() const override; - - void onLeave() override; - - Calamares::JobList jobs() const override; - - void setConfigurationMap( const QVariantMap& configurationMap ) override; - -private: - Config* m_config; - TrackingPage* m_widget; -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( TrackingViewStepFactory ) - -#endif // TRACKINGVIEWSTEP_H diff --git a/src/modules/tracking/level-install.svg b/src/modules/tracking/level-install.svg deleted file mode 100644 index ffa62ce65f..0000000000 --- a/src/modules/tracking/level-install.svg +++ /dev/null @@ -1,194 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - ! - - - - - diff --git a/src/modules/tracking/level-install.svg.license b/src/modules/tracking/level-install.svg.license deleted file mode 100644 index ef0e9d7cdc..0000000000 --- a/src/modules/tracking/level-install.svg.license +++ /dev/null @@ -1,2 +0,0 @@ -SPDX-FileCopyrightText: 2014 Uri Herrera and others -SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/src/modules/tracking/level-machine.svg b/src/modules/tracking/level-machine.svg deleted file mode 100644 index f9df4d56e3..0000000000 --- a/src/modules/tracking/level-machine.svg +++ /dev/null @@ -1,271 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/tracking/level-machine.svg.license b/src/modules/tracking/level-machine.svg.license deleted file mode 100644 index ef0e9d7cdc..0000000000 --- a/src/modules/tracking/level-machine.svg.license +++ /dev/null @@ -1,2 +0,0 @@ -SPDX-FileCopyrightText: 2014 Uri Herrera and others -SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/src/modules/tracking/level-none.svg b/src/modules/tracking/level-none.svg deleted file mode 100644 index 9cf85ff410..0000000000 --- a/src/modules/tracking/level-none.svg +++ /dev/null @@ -1,212 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/tracking/level-none.svg.license b/src/modules/tracking/level-none.svg.license deleted file mode 100644 index ef0e9d7cdc..0000000000 --- a/src/modules/tracking/level-none.svg.license +++ /dev/null @@ -1,2 +0,0 @@ -SPDX-FileCopyrightText: 2014 Uri Herrera and others -SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/src/modules/tracking/level-user.svg b/src/modules/tracking/level-user.svg deleted file mode 100644 index 5d9f03ae88..0000000000 --- a/src/modules/tracking/level-user.svg +++ /dev/null @@ -1,224 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/modules/tracking/level-user.svg.license b/src/modules/tracking/level-user.svg.license deleted file mode 100644 index ef0e9d7cdc..0000000000 --- a/src/modules/tracking/level-user.svg.license +++ /dev/null @@ -1,2 +0,0 @@ -SPDX-FileCopyrightText: 2014 Uri Herrera and others -SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/src/modules/tracking/page_trackingstep.qrc b/src/modules/tracking/page_trackingstep.qrc deleted file mode 100644 index e0147a8a56..0000000000 --- a/src/modules/tracking/page_trackingstep.qrc +++ /dev/null @@ -1,9 +0,0 @@ - - - level-none.svg - level-install.svg - level-machine.svg - level-user.svg - ../../../data/images/information.svgz - - diff --git a/src/modules/tracking/page_trackingstep.ui b/src/modules/tracking/page_trackingstep.ui deleted file mode 100644 index 291a3a3056..0000000000 --- a/src/modules/tracking/page_trackingstep.ui +++ /dev/null @@ -1,310 +0,0 @@ - - - -SPDX-FileCopyrightText: 2017 Adriaan de Groot <groot@kde.org> -SPDX-License-Identifier: GPL-3.0-or-later - - TrackingPage - - - - 0 - 0 - 799 - 400 - - - - Form - - - - - - margin-bottom: 1ex; -margin-left: 2em; - - - Placeholder - - - true - - - - - - - - - - - - - - - - - - 64 - 64 - - - - - 64 - 64 - - - - - - - :/tracking/level-none.svg - - - - - - - - 0 - 0 - - - - <html><head/><body><p>Click here to send <span style=" font-weight:600;">no information at all</span> about your installation.</p></body></html> - - - true - - - - - - - - - - - - - - - - - - - - - 64 - 64 - - - - - 64 - 64 - - - - - - - :/tracking/level-install.svg - - - - - - - - 0 - 0 - - - - TextLabel - - - true - - - - - - - ... - - - - :/tracking/data/images/information.svgz:/tracking/data/images/information.svgz - - - - - - - - - - - - - - - - - - - - - 64 - 64 - - - - - 64 - 64 - - - - - - - :/tracking/level-machine.svg - - - - - - - - 0 - 0 - - - - TextLabel - - - true - - - - - - - ... - - - - :/tracking/data/images/information.svgz:/tracking/data/images/information.svgz - - - - - - - - - - - - - - - - - - - - - 64 - 64 - - - - - 64 - 64 - - - - - - - :/tracking/level-user.svg - - - - - - - - 0 - 0 - - - - TextLabel - - - true - - - - - - - ... - - - - :/tracking/data/images/information.svgz:/tracking/data/images/information.svgz - - - - - - - - - - <html><head/><body><p><a href="placeholder"><span style=" text-decoration: underline; color:#2980b9;">Click here for more information about user feedback</span></a></p></body></html> - - - Qt::RichText - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - false - - - Qt::TextBrowserInteraction - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - diff --git a/src/modules/tracking/tracking.conf b/src/modules/tracking/tracking.conf deleted file mode 100644 index 6f726226d8..0000000000 --- a/src/modules/tracking/tracking.conf +++ /dev/null @@ -1,105 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Settings for various kinds of tracking that Distributions can -# enable. Distributions looking at tracking should be aware of -# the privacy (and hence communications) impact of that tracking, -# and are advised to consult the Mozilla and KDE policies on -# privacy and user tracking. -# -# There are three areas of tracking (-configuration) supported -# by Calamares It is up to individual Distributions to create -# suitable backends / configuration scripts for each. The -# different areas are: -# -# install: This is "phone home" functionality at the end of the -# install process. When enabled, it contacts the given -# URL. The URL can contain the special token $MACHINE, -# which is replaced by the machine-id of the installed -# system (if available, blank otherwise). -# -# machine: This enables machine-level tracking on a (semi-) -# continuous basis. It is meant to keep track of installed -# systems and their continued use / updating. -# -# user: This area enables user-level tracking, along the lines -# of the KDE User Telemetry Policy. It enables specific -# collection of data at a user- and application-level, -# possibly including actions done in an application. -# For the KDE environment, this enables user tracking -# with the appropriate framework, and the KDE User Telemetry -# policy applies. -# -# Each area has a key *enabled*. If the area is enabled, it is shown to -# the user. This defaults to false, which means no tracking would be -# configured or enabled by Calamares. -# -# Each area has a key *policy*, which is a Url to be opened when -# the user clicks on the corresponding Help button for an explanation -# of the details of that particular kind of tracking. If no policy -# is set, that tracking style is disabled. The example policy links -# go to Calamares' generic user manual (which is a terrible idea -# for distro's: you have GDPR obligations under most of these tracking -# styles, so do your homework). -# -# Each area may have other configuration keys, depending on the -# area and how it needs to be configured. -# -# Globally, there are two other keys: -# -# policy: (optional) url about tracking settings for this distro. -# default: (optional) level to enable by default -# ---- -# This is the global policy; it is displayed as a link on the page. -# If blank or commented out, no link is displayed on the tracking -# page. You **must** provide policy links per-area as well. -policy: "https://github.com/calamares/calamares/wiki/Use-Guide#installation-tracking" - -# This is the default area to enable for tracking. If commented out, -# empty, or otherwise invalid, "none" is used, so no tracking by default. -# Setting an area here also checks the areas before it (install, machine, -# then user) by default -- subject to those areas being enabled at all. -# default: user - -# The install area has one specific configuration key: -# url: this URL (remember to include the protocol, and prefer https) -# is fetched (with a GET request, and the data discarded) at -# the end of the installation process. The following tokens -# are replaced in the url (possibly by blank strings, or by 0). -# - $CPU (cpu make and model) -# - $MEMORY (amount of main memory available) -# - $DISK (total amount of disk attached) -# Typically these are used as GET parameters, as in the example. -# -# Note that phone-home only works if the system has an internet -# connection; it is a good idea to require internet in the welcome -# module then. -install: - enabled: false - policy: "https://github.com/calamares/calamares/wiki/Use-Guide#installation-tracking" - url: "https://example.com/install.php?c=$CPU&m=$MEMORY" - -# The machine area has one specific configuration key: -# style: This string specifies what kind of tracking configuration -# needs to be done. See below for valid styles. -# -# Available styles: -# - *updatemanager* replaces the literal string "${MACHINE_ID}" with the contents of -# /etc/machine-id, in lines starting with "URI" in the file /etc/update-manager/meta-release -machine: - enabled: false - style: updatemanager - policy: "https://github.com/calamares/calamares/wiki/Use-Guide#machine-tracking" - -# The user area has one specific configuration key: -# style: This string specifies what kind of tracking configuration -# needs to be done. See below for valid styles. -# -# Available styles: -# - *kuserfeedback* sets up KUserFeedback tracking (applicable to the KDE -# Plasma Desktop) for each KUserFeedback area listed in *areas*. -user: - enabled: false - style: kuserfeedback - areas: [ PlasmaUserFeedback ] diff --git a/src/modules/umount/CMakeLists.txt b/src/modules/umount/CMakeLists.txt deleted file mode 100644 index 09e6a085d2..0000000000 --- a/src/modules/umount/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2021 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# -calamares_add_plugin(umount - TYPE job - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - UmountJob.cpp - SHARED_LIB - EMERGENCY -) - -calamares_add_test(umounttest SOURCES Tests.cpp) diff --git a/src/modules/umount/Tests.cpp b/src/modules/umount/Tests.cpp deleted file mode 100644 index a0ae8bc348..0000000000 --- a/src/modules/umount/Tests.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2021 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "UmountJob.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "utils/Logger.h" -#include "utils/System.h" - -#include -#include -#include - -// Internals of UmountJob.cpp - -// Actual tests -class UmountTests : public QObject -{ - Q_OBJECT -public: - UmountTests() {} - ~UmountTests() override {} - -private Q_SLOTS: - void initTestCase(); - void testTrue(); -}; - -void -UmountTests::initTestCase() -{ - Logger::setupLogLevel( Logger::LOGDEBUG ); -} - -void -UmountTests::testTrue() -{ - QVERIFY( true ); -} - -QTEST_GUILESS_MAIN( UmountTests ) - -#include "utils/moc-warnings.h" - -#include "Tests.moc" diff --git a/src/modules/umount/UmountJob.cpp b/src/modules/umount/UmountJob.cpp deleted file mode 100644 index 83cf2f10e6..0000000000 --- a/src/modules/umount/UmountJob.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* === This file is part of Calamares - === - * - * Tags from the Python version of this module: - * SPDX-FileCopyrightText: 2014 Aurélien Gâteau - * SPDX-FileCopyrightText: 2016 Anke Boersma - * SPDX-FileCopyrightText: 2018 Adriaan de Groot - * Tags for the C++ version of this module: - * SPDX-FileCopyrightText: 2021 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "UmountJob.h" - -#include "partition/Mount.h" -#include "utils/Logger.h" -#include "utils/System.h" -#include "utils/Variant.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" - -#include -#include -#include - -UmountJob::UmountJob( QObject* parent ) - : Calamares::CppJob( parent ) -{ -} - -UmountJob::~UmountJob() {} - -QString -UmountJob::prettyName() const -{ - return tr( "Unmounting file systems…", "@status" ); -} - -static Calamares::JobResult -unmountTargetMounts( const QString& rootMountPoint ) -{ - QDir targetMount( rootMountPoint ); - if ( !targetMount.exists() ) - { - return Calamares::JobResult::internalError( - QCoreApplication::translate( UmountJob::staticMetaObject.className(), "Could not unmount target system." ), - QCoreApplication::translate( UmountJob::staticMetaObject.className(), - "The target system is not mounted at '%1'." ) - .arg( rootMountPoint ), - Calamares::JobResult::GenericError ); - } - QString targetMountPath = targetMount.absolutePath(); - if ( !targetMountPath.endsWith( '/' ) ) - { - targetMountPath.append( '/' ); - } - - using MtabInfo = Calamares::Partition::MtabInfo; - auto targetMounts = MtabInfo::fromMtabFilteredByPrefix( targetMountPath ); - std::sort( targetMounts.begin(), targetMounts.end(), MtabInfo::mountPointOrder ); - - cDebug() << "Read" << targetMounts.count() << "entries from" << targetMountPath; - for ( const auto& m : qAsConst( targetMounts ) ) - { - // Returns the program's exit code, so 0 is success and non-0 - // (truthy) is a failure. - if ( Calamares::Partition::unmount( m.mountPoint, { "-lv" } ) ) - { - return Calamares::JobResult::error( - QCoreApplication::translate( UmountJob::staticMetaObject.className(), - "Could not unmount target system." ), - QCoreApplication::translate( UmountJob::staticMetaObject.className(), - "The device '%1' is mounted in the target system. It is mounted at '%2'. " - "The device could not be unmounted." ) - .arg( m.device, m.mountPoint ) ); - } - } - return Calamares::JobResult::ok(); -} - -static Calamares::JobResult -exportZFSPools() -{ - auto* gs = Calamares::JobQueue::instance()->globalStorage(); - QStringList poolNames; - { - // The pools are dictionaries / VariantMaps - auto zfs_pool_list = gs->value( "zfsPoolInfo" ).toList(); - for ( const auto& v : zfs_pool_list ) - { - auto m = v.toMap(); - QString poolName = m.value( "poolName" ).toString(); - if ( !poolName.isEmpty() ) - { - poolNames.append( poolName ); - } - } - poolNames.sort(); - } - - for ( const auto& poolName : poolNames ) - { - auto result = Calamares::System::runCommand( { "zpool", "export", poolName }, std::chrono::seconds( 30 ) ); - if ( result.getExitCode() ) - { - cWarning() << "Failed to export pool" << result.getOutput(); - } - } - // Exporting ZFS pools does not cause the install to fail - return Calamares::JobResult::ok(); -} - -Calamares::JobResult -UmountJob::exec() -{ - const auto* sys = Calamares::System::instance(); - if ( !sys ) - { - return Calamares::JobResult::internalError( - "UMount", tr( "No target system available." ), Calamares::JobResult::InvalidConfiguration ); - } - - Calamares::GlobalStorage* gs - = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; - if ( !gs || gs->value( "rootMountPoint" ).toString().isEmpty() ) - { - return Calamares::JobResult::internalError( - "UMount", tr( "No rootMountPoint is set." ), Calamares::JobResult::InvalidConfiguration ); - } - - // Do the unmounting of target-system filesystems - { - auto r = unmountTargetMounts( gs->value( "rootMountPoint" ).toString() ); - if ( !r ) - { - return r; - } - } - // For ZFS systems, export the pools - { - auto r = exportZFSPools(); - if ( !r ) - { - return r; - } - } - - return Calamares::JobResult::ok(); -} - -void -UmountJob::setConfigurationMap( const QVariantMap& map ) -{ - Q_UNUSED( map ) -} - -CALAMARES_PLUGIN_FACTORY_DEFINITION( UmountJobFactory, registerPlugin< UmountJob >(); ) diff --git a/src/modules/umount/UmountJob.h b/src/modules/umount/UmountJob.h deleted file mode 100644 index 6ca5428bc9..0000000000 --- a/src/modules/umount/UmountJob.h +++ /dev/null @@ -1,41 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2021 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef UMOUNTJOB_H -#define UMOUNTJOB_H - -#include "CppJob.h" -#include "DllMacro.h" -#include "utils/PluginFactory.h" - -#include -#include -#include - -/** @brief Write 'random' data: machine id, entropy, UUIDs - * - */ -class PLUGINDLLEXPORT UmountJob : public Calamares::CppJob -{ - Q_OBJECT - -public: - explicit UmountJob( QObject* parent = nullptr ); - ~UmountJob() override; - - QString prettyName() const override; - - Calamares::JobResult exec() override; - - void setConfigurationMap( const QVariantMap& configurationMap ) override; -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( UmountJobFactory ) - -#endif // UMOUNTJOB_H diff --git a/src/modules/umount/umount.conf b/src/modules/umount/umount.conf deleted file mode 100644 index 5842c87808..0000000000 --- a/src/modules/umount/umount.conf +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -### Umount Module -# -# This module represents the last part of the installation, the unmounting -# of partitions used for the install. After this, there is no regular way -# to modify the target system anymore. -# - ---- -# Setting emergency to true will make it so this module is still run -# when a prior module fails -emergency: true diff --git a/src/modules/umount/umount.schema.yaml b/src/modules/umount/umount.schema.yaml deleted file mode 100644 index 37771e5f62..0000000000 --- a/src/modules/umount/umount.schema.yaml +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later ---- -$schema: https://json-schema.org/schema# -$id: https://calamares.io/schemas/umount -additionalProperties: false -type: object -properties: - emergency: { type: boolean } diff --git a/src/modules/unpackfs/main.py b/src/modules/unpackfs/main.py deleted file mode 100644 index 814556f8ba..0000000000 --- a/src/modules/unpackfs/main.py +++ /dev/null @@ -1,500 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2014 Teo Mrnjavac -# SPDX-FileCopyrightText: 2014 Daniel Hillenbrand -# SPDX-FileCopyrightText: 2014 Philip Müller -# SPDX-FileCopyrightText: 2017 Alf Gaida -# SPDX-FileCopyrightText: 2019 Kevin Kofler -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-FileCopyrightText: 2020 Gabriel Craciunescu -# SPDX-License-Identifier: GPL-3.0-or-later -# -# Calamares is Free Software: see the License-Identifier above. -# - -import os -import re -import shutil -import subprocess -import sys -import tempfile - -import libcalamares - -import gettext -_ = gettext.translation("calamares-python", - localedir=libcalamares.utils.gettext_path(), - languages=libcalamares.utils.gettext_languages(), - fallback=True).gettext - -def pretty_name(): - return _("Filling up filesystems.") - -# This is going to be changed from various methods -status = pretty_name() - -def pretty_status_message(): - return status - -class UnpackEntry: - """ - Extraction routine using rsync. - - :param source: - :param sourcefs: - :param destination: - """ - __slots__ = ('source', 'sourcefs', 'destination', 'copied', 'total', 'exclude', 'excludeFile', - 'mountPoint', 'weight') - - def __init__(self, source, sourcefs, destination): - """ - @p source is the source file name (might be an image file, or - a directory, too) - @p sourcefs is a type indication; "file" is special, as is - "squashfs". - @p destination is where the files from the source go. This is - **already** prefixed by rootMountPoint, so should be a - valid absolute path within the host system. - - The members copied and total are filled in by the copying process. - """ - self.source = source - self.sourcefs = sourcefs - self.destination = destination - self.exclude = None - self.excludeFile = None - self.copied = 0 - self.total = 0 - self.mountPoint = None - self.weight = 1 - - def is_file(self): - return self.sourcefs == "file" - - def do_count(self): - """ - Counts the number of files this entry has. - """ - # Need a name we can use like a global - class counter(object): - count = 0 - def cb_count(s): - counter.count += 1 - - if self.sourcefs == "squashfs": - libcalamares.utils.host_env_process_output(["unsquashfs", "-l", self.source], cb_count) - - elif self.sourcefs == "ext4": - libcalamares.utils.host_env_process_output(["find", self.mountPoint, "-type", "f"], cb_count) - - elif self.is_file(): - # Hasn't been mounted, copy directly; find handles both - # files and directories. - libcalamares.utils.host_env_process_output(["find", self.source, "-type", "f"], cb_count) - - self.total = counter.count - return self.total - - def do_mount(self, base): - """ - Mount given @p entry as loop device underneath @p base - - A *file* entry (e.g. one with *sourcefs* set to *file*) - is not mounted and just ignored. - - :param base: directory to place all the mounts in. - - :returns: None, but throws if the mount failed - """ - imgbasename = os.path.splitext( - os.path.basename(self.source))[0] - imgmountdir = os.path.join(base, imgbasename) - os.makedirs(imgmountdir, exist_ok=True) - - # This is where it *would* go (files bail out before actually mounting) - self.mountPoint = imgmountdir - - if self.is_file(): - return - - if os.path.isdir(self.source): - r = libcalamares.utils.mount(self.source, imgmountdir, "", "--bind") - elif os.path.isfile(self.source): - r = libcalamares.utils.mount(self.source, imgmountdir, self.sourcefs, "loop") - else: # self.source is a device - r = libcalamares.utils.mount(self.source, imgmountdir, self.sourcefs, "") - - if r != 0: - libcalamares.utils.debug("Failed to mount '{}' (fs={}) (target={})".format(self.source, self.sourcefs, imgmountdir)) - raise subprocess.CalledProcessError(r, "mount") - - -ON_POSIX = 'posix' in sys.builtin_module_names - - -def global_excludes(): - """ - List excludes for rsync. - """ - lst = [] - extra_mounts = libcalamares.globalstorage.value("extraMounts") - if extra_mounts is None: - extra_mounts = [] - - for extra_mount in extra_mounts: - mount_point = extra_mount["mountPoint"] - - if mount_point: - lst.extend(['--exclude', mount_point + '/']) - - return lst - -def file_copy(source, entry, progress_cb): - """ - Extract given image using rsync. - - :param source: Source file. This may be the place the entry's - image is mounted, or if it's a single file, the entry's source value. - :param entry: The UnpackEntry being copied. - :param progress_cb: A callback function for progress reporting. - Takes a number and a total-number. - """ - import time - - dest = entry.destination - - # `source` *must* end with '/' otherwise a directory named after the source - # will be created in `dest`: ie if `source` is "/foo/bar" and `dest` is - # "/dest", then files will be copied in "/dest/bar". - if not source.endswith("/") and not os.path.isfile(source): - source += "/" - - num_files_total_local = 0 - num_files_copied = 0 # Gets updated through rsync output - - args = ['rsync', '-aHAXSr', '--filter=-x trusted.overlay.*'] - args.extend(global_excludes()) - if entry.excludeFile: - args.extend(["--exclude-from=" + entry.excludeFile]) - if entry.exclude: - for f in entry.exclude: - args.extend(["--exclude", f]) - args.extend(['--progress', source, dest]) - - # last_num_files_copied trails num_files_copied, and whenever at least 107 more - # files (file_count_chunk) have been copied, progress is reported and - # last_num_files_copied is updated. The chunk size isn't "tidy" - # so that all the digits of the progress-reported number change. - # - file_count_chunk = 107 - - class counter(object): - last_num_files_copied = 0 - last_timestamp_reported = time.time() - last_total_reported = 0 - - def output_cb(line): - # rsync outputs progress in parentheses. Each line will have an - # xfer and a chk item (either ir-chk or to-chk) as follows: - # - # - xfer#x => Interpret it as 'file copy try no. x' - # - ir-chk=x/y, where: - # - x = number of files yet to be checked - # - y = currently calculated total number of files. - # - to-chk=x/y, which is similar and happens once the ir-chk - # phase (collecting total files) is over. - # - # If you're copying directory with some links in it, the xfer# - # might not be a reliable counter (for one increase of xfer, many - # files may be created). - m = re.findall(r'xfr#(\d+), ..-chk=(\d+)/(\d+)', line) - - if m: - # we've got a percentage update - num_files_remaining = int(m[0][1]) - num_files_total_local = int(m[0][2]) - # adjusting the offset so that progressbar can be continuesly drawn - num_files_copied = num_files_total_local - num_files_remaining - - now = time.time() - if (num_files_copied - counter.last_num_files_copied >= file_count_chunk) or (now - counter.last_timestamp_reported > 0.5): - counter.last_num_files_copied = num_files_copied - counter.last_timestamp_reported = now - counter.last_total_reported = num_files_total_local - progress_cb(num_files_copied, num_files_total_local) - - try: - returncode = libcalamares.utils.host_env_process_output(args, output_cb) - except subprocess.CalledProcessError as e: - returncode = e.returncode - - progress_cb(counter.last_num_files_copied, counter.last_total_reported) # Push towards 100% - - # Mark this entry as really done - entry.copied = entry.total - - # 23 is the return code rsync returns if it cannot write extended - # attributes (with -X) because the target file system does not support it, - # e.g., the FAT EFI system partition. We need -X because distributions - # using file system capabilities and/or SELinux require the extended - # attributes. But distributions using SELinux may also have SELinux labels - # set on files under /boot/efi, and rsync complains about those. The only - # clean way would be to split the rsync into one with -X and - # --exclude /boot/efi and a separate one without -X for /boot/efi, but only - # if /boot/efi is actually an EFI system partition. For now, this hack will - # have to do. See also: - # https://bugzilla.redhat.com/show_bug.cgi?id=868755#c50 - # for the same issue in Anaconda, which uses a similar workaround. - if returncode != 0 and returncode != 23: - libcalamares.utils.warning("rsync failed with error code {}.".format(returncode)) - return _("rsync failed with error code {}.").format(returncode) - - return None - - -class UnpackOperation: - """ - Extraction routine using unsquashfs. - - :param entries: - """ - - def __init__(self, entries): - self.entries = entries - self.entry_for_source = dict((x.source, x) for x in self.entries) - self.total_weight = sum([e.weight for e in entries]) - - def report_progress(self): - """ - Pass progress to user interface - """ - progress = float(0) - - current_total = 0 - current_done = 0 # Files count in the current entry - complete_count = 0 - complete_weight = 0 # This much weight already finished - for entry in self.entries: - if entry.total == 0: - # Total 0 hasn't counted yet - continue - if entry.total == entry.copied: - complete_weight += entry.weight - complete_count += 1 - else: - # There is at most *one* entry in-progress - current_total = entry.total - current_done = entry.copied - complete_weight += entry.weight * ( 1.0 * current_done ) / current_total - break - - if current_total > 0: - progress = ( 1.0 * complete_weight ) / self.total_weight - - global status - status = _("Unpacking image {}/{}, file {}/{}").format((complete_count+1), len(self.entries), current_done, current_total) - libcalamares.job.setprogress(progress) - - def run(self): - """ - Extract given image using unsquashfs. - - :return: - """ - global status - source_mount_path = tempfile.mkdtemp() - - try: - complete = 0 - for entry in self.entries: - status = _("Starting to unpack {}").format(entry.source) - libcalamares.job.setprogress( ( 1.0 * complete ) / len(self.entries) ) - entry.do_mount(source_mount_path) - entry.do_count() # Fill in the entry.total - - self.report_progress() - error_msg = self.unpack_image(entry, entry.mountPoint) - - if error_msg: - return (_("Failed to unpack image \"{}\"").format(entry.source), - error_msg) - complete += 1 - - return None - finally: - shutil.rmtree(source_mount_path, ignore_errors=True, onerror=None) - - - def unpack_image(self, entry, imgmountdir): - """ - Unpacks image. - - :param entry: - :param imgmountdir: - :return: - """ - def progress_cb(copied, total): - """ Copies file to given destination target. - - :param copied: - """ - entry.copied = copied - if total > entry.total: - entry.total = total - self.report_progress() - - try: - if entry.is_file(): - source = entry.source - else: - source = imgmountdir - - return file_copy(source, entry, progress_cb) - finally: - if not entry.is_file(): - subprocess.check_call(["umount", "-l", imgmountdir]) - - -def get_supported_filesystems_kernel(): - """ - Reads /proc/filesystems (the list of supported filesystems - for the current kernel) and returns a list of (names of) - those filesystems. - """ - PATH_PROCFS = '/proc/filesystems' - - if os.path.isfile(PATH_PROCFS) and os.access(PATH_PROCFS, os.R_OK): - with open(PATH_PROCFS, 'r') as procfile: - filesystems = procfile.read() - filesystems = filesystems.replace( - "nodev", "").replace("\t", "").splitlines() - return filesystems - - return [] - - -def get_supported_filesystems(): - """ - Returns a list of all the supported filesystems - (valid values for the *sourcefs* key in an item. - """ - return ["file"] + get_supported_filesystems_kernel() - - -def repair_root_permissions(root_mount_point): - """ - If the / of the system gets permission 777, change it down - to 755. Any other permission is left alone. This - works around standard behavior from squashfs where - permissions are (easily, accidentally) set to 777. - """ - existing_root_mode = os.stat(root_mount_point).st_mode & 0o777 - if existing_root_mode == 0o777: - try: - os.chmod(root_mount_point, 0o755) # Want / to be rwxr-xr-x - except OSError as e: - libcalamares.utils.warning("Could not set / to safe permissions: {}".format(e)) - # But ignore it - - -def extract_weight(entry): - """ - Given @p entry, a dict representing a single entry in - the *unpack* list, returns its weight (1, or whatever is - set if it is sensible). - """ - w = entry.get("weight", None) - if w: - try: - wi = int(w) - return wi if wi > 0 else 1 - except ValueError: - libcalamares.utils.warning("*weight* setting {!r} is not valid.".format(w)) - except TypeError: - libcalamares.utils.warning("*weight* setting {!r} must be number.".format(w)) - return 1 - - -def run(): - """ - Unsquash filesystem. - """ - root_mount_point = libcalamares.globalstorage.value("rootMountPoint") - - if not root_mount_point: - libcalamares.utils.warning("No mount point for root partition") - return (_("No mount point for root partition"), - _("globalstorage does not contain a \"rootMountPoint\" key.")) - if not os.path.exists(root_mount_point): - libcalamares.utils.warning("Bad root mount point \"{}\"".format(root_mount_point)) - return (_("Bad mount point for root partition"), - _("rootMountPoint is \"{}\", which does not exist.".format(root_mount_point))) - - if libcalamares.job.configuration.get("unpack", None) is None: - libcalamares.utils.warning("No *unpack* key in job configuration.") - return (_("Bad unpackfs configuration"), - _("There is no configuration information.")) - - supported_filesystems = get_supported_filesystems() - - # Bail out before we start when there are obvious problems - # - unsupported filesystems - # - non-existent sources - # - missing tools for specific FS - for entry in libcalamares.job.configuration["unpack"]: - source = os.path.abspath(entry["source"]) - sourcefs = entry["sourcefs"] - - if sourcefs not in supported_filesystems: - libcalamares.utils.warning("The filesystem for \"{}\" ({}) is not supported by your current kernel".format(source, sourcefs)) - libcalamares.utils.warning(" ... modprobe {} may solve the problem".format(sourcefs)) - return (_("Bad unpackfs configuration"), - _("The filesystem for \"{}\" ({}) is not supported by your current kernel").format(source, sourcefs)) - if not os.path.exists(source): - libcalamares.utils.warning("The source filesystem \"{}\" does not exist".format(source)) - return (_("Bad unpackfs configuration"), - _("The source filesystem \"{}\" does not exist").format(source)) - if sourcefs == "squashfs": - if shutil.which("unsquashfs") is None: - libcalamares.utils.warning("Failed to find unsquashfs") - - return (_("Bad unpackfs configuration"), - _("Failed to find unsquashfs, make sure you have the squashfs-tools package installed.") + - " " + _("Failed to unpack image \"{}\"").format(source)) - - unpack = list() - - is_first = True - for entry in libcalamares.job.configuration["unpack"]: - source = os.path.abspath(entry["source"]) - sourcefs = entry["sourcefs"] - destination = os.path.abspath(root_mount_point + entry["destination"]) - - if not os.path.isdir(destination) and sourcefs != "file": - libcalamares.utils.warning(("The destination \"{}\" in the target system is not a directory").format(destination)) - if is_first: - return (_("Bad unpackfs configuration"), - _("The destination \"{}\" in the target system is not a directory").format(destination)) - else: - libcalamares.utils.debug(".. assuming that the previous targets will create that directory.") - - unpack.append(UnpackEntry(source, sourcefs, destination)) - # Optional settings - if entry.get("exclude", None): - unpack[-1].exclude = entry["exclude"] - if entry.get("excludeFile", None): - unpack[-1].excludeFile = entry["excludeFile"] - unpack[-1].weight = extract_weight(entry) - - is_first = False - - repair_root_permissions(root_mount_point) - try: - unpackop = UnpackOperation(unpack) - return unpackop.run() - finally: - repair_root_permissions(root_mount_point) diff --git a/src/modules/unpackfs/module.desc b/src/modules/unpackfs/module.desc deleted file mode 100644 index 2723c3c461..0000000000 --- a/src/modules/unpackfs/module.desc +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# Syntax is YAML 1.2 ---- -type: "job" -name: "unpackfs" -interface: "python" -script: "main.py" -requiredModules: [ mount ] -weight: 12 diff --git a/src/modules/unpackfs/runtests.sh b/src/modules/unpackfs/runtests.sh deleted file mode 100644 index 2269b078a7..0000000000 --- a/src/modules/unpackfs/runtests.sh +++ /dev/null @@ -1,37 +0,0 @@ -#! /bin/sh -# -# SPDX-FileCopyrightText: 2019 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# -# Test preparation for unpackfs; since there's a bunch -# of fiddly bits than need to be present for the tests, -# do that in a script rather than entirely in CTest. -# -SRCDIR=$( dirname "$0" ) - -# For test 3 -mkdir /tmp/unpackfs-test-run-rootdir3 - -# For test 7 -mkdir /tmp/unpackfs-test-run-rootdir3/realdest - -# For test 9 -mkdir /tmp/unpackfs-test-run-rootdir3/smalldest -if test 0 = $( id -u ) ; then - mount -t tmpfs -o size=32M tmpfs /tmp/unpackfs-test-run-rootdir3/smalldest - dd if=/dev/zero of=/tmp/unpackfs-test-run-rootdir3/smalldest/bogus.zero bs=1M count=1 -fi - -# Run tests -sh "$SRCDIR/../testpythonrun.sh" unpackfs - -# Cleanup test 9 -if test 0 = $( id -u ) ; then - umount /tmp/unpackfs-test-run-rootdir3/smalldest -fi - -# Cleanup test 7 -rm -rf /tmp/unpackfs-test-run-rootdir3/realdest - -# Cleanup test 3 -rmdir /tmp/unpackfs-test-run-rootdir3 diff --git a/src/modules/unpackfs/tests/1.global b/src/modules/unpackfs/tests/1.global deleted file mode 100644 index 7dedc15274..0000000000 --- a/src/modules/unpackfs/tests/1.global +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -bogus: true diff --git a/src/modules/unpackfs/tests/2.global b/src/modules/unpackfs/tests/2.global deleted file mode 100644 index d1e61caf3a..0000000000 --- a/src/modules/unpackfs/tests/2.global +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -rootMountPoint: /tmp/unpackfs-test-run-rootdir/ diff --git a/src/modules/unpackfs/tests/3.global b/src/modules/unpackfs/tests/3.global deleted file mode 100644 index 1c25cbe208..0000000000 --- a/src/modules/unpackfs/tests/3.global +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -rootMountPoint: /tmp/unpackfs-test-run-rootdir3/ diff --git a/src/modules/unpackfs/tests/3.job b/src/modules/unpackfs/tests/3.job deleted file mode 100644 index 82d353108d..0000000000 --- a/src/modules/unpackfs/tests/3.job +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -unpack: [] diff --git a/src/modules/unpackfs/tests/4.global b/src/modules/unpackfs/tests/4.global deleted file mode 100644 index 1c25cbe208..0000000000 --- a/src/modules/unpackfs/tests/4.global +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -rootMountPoint: /tmp/unpackfs-test-run-rootdir3/ diff --git a/src/modules/unpackfs/tests/4.job b/src/modules/unpackfs/tests/4.job deleted file mode 100644 index e6b067ddb7..0000000000 --- a/src/modules/unpackfs/tests/4.job +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Test that a "bogus" sourcefs (a filesystem kind that does not -# exist) fails gracefully. ---- -unpack: - - source: . - sourcefs: bogus - destination: / diff --git a/src/modules/unpackfs/tests/5.global b/src/modules/unpackfs/tests/5.global deleted file mode 100644 index 1c25cbe208..0000000000 --- a/src/modules/unpackfs/tests/5.global +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -rootMountPoint: /tmp/unpackfs-test-run-rootdir3/ diff --git a/src/modules/unpackfs/tests/5.job b/src/modules/unpackfs/tests/5.job deleted file mode 100644 index 268ee7ce34..0000000000 --- a/src/modules/unpackfs/tests/5.job +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -unpack: - - source: ./fakesource - sourcefs: ext4 - destination: fakedest diff --git a/src/modules/unpackfs/tests/6.global b/src/modules/unpackfs/tests/6.global deleted file mode 100644 index 1c25cbe208..0000000000 --- a/src/modules/unpackfs/tests/6.global +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -rootMountPoint: /tmp/unpackfs-test-run-rootdir3/ diff --git a/src/modules/unpackfs/tests/6.job b/src/modules/unpackfs/tests/6.job deleted file mode 100644 index 1ec0840cac..0000000000 --- a/src/modules/unpackfs/tests/6.job +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -unpack: - - source: . - sourcefs: ext4 - destination: fakedest diff --git a/src/modules/unpackfs/tests/7.global b/src/modules/unpackfs/tests/7.global deleted file mode 100644 index 1c25cbe208..0000000000 --- a/src/modules/unpackfs/tests/7.global +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -rootMountPoint: /tmp/unpackfs-test-run-rootdir3/ diff --git a/src/modules/unpackfs/tests/7.job b/src/modules/unpackfs/tests/7.job deleted file mode 100644 index ffd898f1b1..0000000000 --- a/src/modules/unpackfs/tests/7.job +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -unpack: - - source: . - sourcefs: ext4 - destination: realdest diff --git a/src/modules/unpackfs/tests/8.global b/src/modules/unpackfs/tests/8.global deleted file mode 100644 index 15c3085458..0000000000 --- a/src/modules/unpackfs/tests/8.global +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -rootMountPoint: /tmp/unpackfs-test-run-rootdir/ -localeConf: - - LANG: nl diff --git a/src/modules/unpackfs/tests/8.job b/src/modules/unpackfs/tests/8.job deleted file mode 100644 index ffd898f1b1..0000000000 --- a/src/modules/unpackfs/tests/8.job +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -unpack: - - source: . - sourcefs: ext4 - destination: realdest diff --git a/src/modules/unpackfs/tests/9.global b/src/modules/unpackfs/tests/9.global deleted file mode 100644 index e7a2cd989f..0000000000 --- a/src/modules/unpackfs/tests/9.global +++ /dev/null @@ -1,5 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# This test uses a small destination FS, to make rsync fail ---- -rootMountPoint: /tmp/unpackfs-test-run-rootdir3/ diff --git a/src/modules/unpackfs/tests/9.job b/src/modules/unpackfs/tests/9.job deleted file mode 100644 index b896334719..0000000000 --- a/src/modules/unpackfs/tests/9.job +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# This test uses a small destination FS, to make rsync fail ---- -unpack: - - source: . - sourcefs: ext4 - destination: smalldest diff --git a/src/modules/unpackfs/unpackfs.conf b/src/modules/unpackfs/unpackfs.conf deleted file mode 100644 index d12110b603..0000000000 --- a/src/modules/unpackfs/unpackfs.conf +++ /dev/null @@ -1,100 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Unsquash / unpack a filesystem. Multiple sources are supported, and -# they may be squashed or plain filesystems. -# -# Configuration: -# -# from globalstorage: rootMountPoint -# from job.configuration: the path to where to mount the source image(s) -# for copying an ordered list of unpack mappings for image file <-> -# target dir relative to rootMountPoint. - ---- -# Each list item is unpacked, in order, to the target system. -# -# Each list item has the following **mandatory** attributes: -# - *source* path relative to the live / intstalling system to the image -# - *sourcefs* the type of the source files; valid entries are -# - `ext4` (copies the filesystem contents) -# - `squashfs` (unsquashes) -# - `file` (copies a file or directory) -# - (may be others if mount supports it) -# - *destination* path relative to rootMountPoint (so in the target -# system) where this filesystem is unpacked. It may be an -# empty string, which effectively is / (the root) of the target -# system. -# -# Each list item **optionally** can include the following attributes: -# - *exclude* is a list of values that is expanded into --exclude -# arguments for rsync (each entry in exclude gets its own --exclude). -# - *excludeFile* is a single file that is passed to rsync as an -# --exclude-file argument. This should be a full pathname -# inside the **host** filesystem. -# - *weight* is useful when the entries take wildly different -# times to unpack (e.g. with a squashfs, and one single file) -# and the total weight of this module should be distributed -# differently between the entries. (This is only relevant when -# there is more than one entry; by default all the entries -# have the same weight, 1) -# -# EXAMPLES -# -# Usually you list a filesystem image to unpack; you can use -# squashfs or an ext4 image. An empty destination is equivalent to "/", -# the root of the target system. The destination directory must exist -# in the target system. -# -# - source: "/path/to/filesystem.sqfs" -# sourcefs: "squashfs" -# destination: "" -# -# Multiple entries are unpacked in-order; if there is more than one -# item then only the first must exist beforehand -- it's ok to -# create directories with one unsquash and then to use those -# directories as a target from a second unsquash. -# -# - source: "/path/to/another/filesystem.img" -# sourcefs: "ext4" -# destination: "" -# - source: "/path/to/another/filesystem2.img" -# sourcefs: "ext4" -# destination: "/usr/lib/extra" -# -# You can list filesystem source paths relative to the Calamares run -# directory, if you use -d (this is only useful for testing, though). -# -# - source: ./example.sqfs -# sourcefs: squashfs -# destination: "" -# -# You can list individual files (copied one-by-one), or directories -# (the files inside this directory are copied directly to the destination, -# so no "dummycpp/" subdirectory is created in this example). -# Do note that the target directory must exist already (e.g. from -# extracting some other filesystem). -# -# - source: ../CHANGES -# sourcefs: file -# destination: "/tmp/derp" -# - source: ../src/modules/dummycpp -# sourcefs: file -# destination: "/tmp/derp" -# -# The *destination* and *source* are handed off to rsync, so the semantics -# of trailing slashes apply. In order to *rename* a file as it is -# copied, specify one single file (e.g. CHANGES) and a full pathname -# for its destination name, as in the example below. - -unpack: - - source: ../CHANGES - sourcefs: file - destination: "/tmp/changes.txt" - weight: 1 # Single file - - source: src/qml/calamares/slideshow - sourcefs: file - destination: "/tmp/slideshow/" - exclude: [ "*.qmlc", "qmldir" ] - weight: 5 # Lots of files - # excludeFile: /etc/calamares/modules/unpackfs/exclude-list.txt diff --git a/src/modules/unpackfs/unpackfs.schema.yaml b/src/modules/unpackfs/unpackfs.schema.yaml deleted file mode 100644 index 0d96fe9cb6..0000000000 --- a/src/modules/unpackfs/unpackfs.schema.yaml +++ /dev/null @@ -1,21 +0,0 @@ -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later ---- -$schema: https://json-schema.org/schema# -$id: https://calamares.io/schemas/unpackfs -additionalProperties: false -type: object -properties: - unpack: - type: array - items: - type: object - additionalProperties: false - properties: - source: { type: string } - sourcefs: { type: string } - destination: { type: string } - excludeFile: { type: string } - exclude: { type: array, items: { type: string } } - weight: { type: integer, exclusiveMinimum: 0 } - required: [ source , sourcefs, destination ] diff --git a/src/modules/users/CMakeLists.txt b/src/modules/users/CMakeLists.txt deleted file mode 100644 index 7a8a944b7d..0000000000 --- a/src/modules/users/CMakeLists.txt +++ /dev/null @@ -1,137 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# -find_package(${qtname} ${QT_VERSION} CONFIG REQUIRED Core DBus Network) -find_package(Crypt REQUIRED) - -# Provide modern alias for -lcrypt -add_library(crypt_crypt INTERFACE) -add_library(crypt::crypt ALIAS crypt_crypt) -if(Crypt_FOUND) - target_link_libraries(crypt_crypt INTERFACE ${CRYPT_LIBRARIES}) -endif() - -# Check for crypt_gensalt -if(Crypt_FOUND) - set(_old_CRL "${CMAKE_REQUIRED_LIBRARIES}") - list(APPEND CMAKE_REQUIRED_LIBRARIES crypt) - include(CheckSymbolExists) - check_symbol_exists(crypt_gensalt crypt.h HAS_CRYPT_GENSALT) - set(CMAKE_REQUIRED_LIBRARIES "${_old_CRL}") - - if(HAS_CRYPT_GENSALT) - target_compile_definitions(crypt_crypt INTERFACE HAVE_CRYPT_GENSALT) - endif() -endif() - -# Add optional libraries here -set(USER_EXTRA_LIB - ${kfname}::CoreAddons - ${qtname}::DBus - crypt::crypt -) - -find_package(LibPWQuality) -set_package_properties(LibPWQuality PROPERTIES PURPOSE "Extra checks of password quality") - -if(LibPWQuality_FOUND) - list(APPEND USER_EXTRA_LIB ${LibPWQuality_LIBRARIES}) - include_directories(${LibPWQuality_INCLUDE_DIRS}) - add_definitions(-DCHECK_PWQUALITY -DHAVE_LIBPWQUALITY) -endif() - -find_package(ICU COMPONENTS uc i18n) -set_package_properties(ICU PROPERTIES PURPOSE "Transliteration support for full name to username conversion") - -if(ICU_FOUND) - list(APPEND USER_EXTRA_LIB ICU::uc ICU::i18n) - include_directories(${ICU_INCLUDE_DIRS}) - add_definitions(-DHAVE_ICU) -endif() - -include_directories(${PROJECT_BINARY_DIR}/src/libcalamaresui) - -set(_users_src - # Jobs - CreateUserJob.cpp - MiscJobs.cpp - SetPasswordJob.cpp - SetHostNameJob.cpp - # Configuration - CheckPWQuality.cpp - Config.cpp -) - -# This part of the code is shared with the usersq module -add_library(users_internal - OBJECT - ${_users_src} -) -target_link_libraries(users_internal - PRIVATE - ${USER_EXTRA_LIB} - ${Calamares_LIBRARIES} - ${qtname}::Core - ${qtname}::Gui - ${qtname}::Widgets -) -target_compile_definitions(users_internal PUBLIC PLUGINDLLEXPORT_PRO) -target_compile_options(users_internal PUBLIC -fPIC) -calamares_automoc(users_internal) - -calamares_add_plugin(users - TYPE viewmodule - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - UsersViewStep.cpp - UsersPage.cpp - UI - page_usersetup.ui - RESOURCES - users.qrc - LINK_PRIVATE_LIBRARIES - users_internal - crypt::crypt - ${USER_EXTRA_LIB} - SHARED_LIB -) - -if(NOT HAS_CRYPT_GENSALT) - # Test checks characteristics of the generated hash, but - # when HAVE_CRYPT_GENSALT is used, the chosen hash is the "best" - # one -- difficult to set expectations in the tests, so skip it. - calamares_add_test(userspasswordtest SOURCES TestPasswordJob.cpp SetPasswordJob.cpp LIBRARIES crypt::crypt) -endif() - -calamares_add_test( - usersgroupstest - SOURCES - TestGroupInformation.cpp - ${_users_src} # Build again with test-visibility - LIBRARIES - ${kfname}::CoreAddons - ${qtname}::DBus # HostName job can use DBus to systemd - crypt::crypt # SetPassword job uses crypt() - ${USER_EXTRA_LIB} -) - -calamares_add_test( - usershostnametest - SOURCES TestSetHostNameJob.cpp SetHostNameJob.cpp - LIBRARIES - ${qtname}::DBus # HostName job can use DBus to systemd -) - -calamares_add_test( - userstest - SOURCES - Tests.cpp - ${_users_src} # Build again with test-visibility - LIBRARIES - ${kfname}::CoreAddons - ${qtname}::DBus # HostName job can use DBus to systemd - crypt::crypt # SetPassword job uses crypt() - ${USER_EXTRA_LIB} -) diff --git a/src/modules/users/CheckPWQuality.cpp b/src/modules/users/CheckPWQuality.cpp deleted file mode 100644 index f657f8f626..0000000000 --- a/src/modules/users/CheckPWQuality.cpp +++ /dev/null @@ -1,400 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Contains strings from libpwquality under the terms of the - * GPL-3.0-or-later (libpwquality is BSD-3-clause or GPL-2.0-or-later, - * so we pick GPL-3.0-or-later). - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "CheckPWQuality.h" - -#include "compat/Variant.h" -#include "utils/Logger.h" - -#include -#include - -#ifdef HAVE_LIBPWQUALITY -#include -#endif - -#include - -PasswordCheck::PasswordCheck() - : m_weight( 0 ) - , m_message() - , m_accept( []( const QString& ) { return true; } ) -{ -} - -PasswordCheck::PasswordCheck( MessageFunc m, AcceptFunc a, Weight weight ) - : m_weight( weight ) - , m_message( m ) - , m_accept( a ) -{ -} - -DEFINE_CHECK_FUNC( minLength ) -{ - int minLength = -1; - if ( value.canConvert< int >() ) - { - minLength = value.toInt(); - } - if ( minLength > 0 ) - { - 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; }, - PasswordCheck::Weight( 10 ) ) ); - } -} - -DEFINE_CHECK_FUNC( maxLength ) -{ - int maxLength = -1; - if ( value.canConvert< int >() ) - { - maxLength = value.toInt(); - } - if ( maxLength > 0 ) - { - 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; }, - PasswordCheck::Weight( 10 ) ) ); - } -} - -#ifdef HAVE_LIBPWQUALITY -/* NOTE: - * - * The munge*() functions are here because libpwquality uses void* to - * represent user-data in callbacks and as a general "pass some parameter" - * type. These need to be munged to the right C++ type. - */ - -/// @brief Handle libpwquality using void* to represent a long -static inline long -mungeLong( void* p ) -{ - return static_cast< long >( reinterpret_cast< intptr_t >( p ) ); -} - -/// @brief Handle libpwquality using void* to represent a char* -static inline const char* -mungeString( void* p ) -{ - return reinterpret_cast< const char* >( p ); -} - -/** - * Class that acts as a RAII placeholder for pwquality_settings_t pointers. - * Gets a new pointer and ensures it is deleted only once; provides - * convenience functions for setting options and checking passwords. - */ -class PWSettingsHolder -{ -public: - static constexpr int arbitrary_minimum_strength = 40; - - PWSettingsHolder() - : m_settings( pwquality_default_settings() ) - { - } - - ~PWSettingsHolder() { pwquality_free_settings( m_settings ); } - - /// Sets an option via the configuration string @p v, = style. - int set( const QString& v ) { return pwquality_set_option( m_settings, v.toUtf8().constData() ); } - - /** @brief Checks the given password @p pwd against the current configuration - * - * Resets m_errorString and m_errorCount and then sets them appropriately - * so that explanation() can be called afterwards. Sets m_rv as well. - */ - - int check( const QString& pwd ) - { - void* auxerror = nullptr; - m_rv = pwquality_check( m_settings, pwd.toUtf8().constData(), nullptr, nullptr, &auxerror ); - - // Positive return values could be ignored; some negative ones - // place extra information in auxerror, which is a void* and - // which needs interpretation to long- or string-values. - m_errorCount = 0; - m_errorString = QString(); - - switch ( m_rv ) - { - case PWQ_ERROR_CRACKLIB_CHECK: - if ( auxerror ) - { - /* Here the string comes from cracklib, don't free? */ - m_errorString = mungeString( auxerror ); - } - break; - case PWQ_ERROR_MEM_ALLOC: - case PWQ_ERROR_UNKNOWN_SETTING: - case PWQ_ERROR_INTEGER: - case PWQ_ERROR_NON_INT_SETTING: - case PWQ_ERROR_NON_STR_SETTING: - if ( auxerror ) - { - m_errorString = mungeString( auxerror ); - free( auxerror ); - } - break; - case PWQ_ERROR_MIN_DIGITS: - case PWQ_ERROR_MIN_UPPERS: - case PWQ_ERROR_MIN_LOWERS: - case PWQ_ERROR_MIN_OTHERS: - case PWQ_ERROR_MIN_LENGTH: - case PWQ_ERROR_MIN_CLASSES: - case PWQ_ERROR_MAX_CONSECUTIVE: - case PWQ_ERROR_MAX_CLASS_REPEAT: - case PWQ_ERROR_MAX_SEQUENCE: - if ( auxerror ) - { - m_errorCount = mungeLong( auxerror ); - } - break; - default: - break; - } - - return m_rv; - } - - /** @brief Explain the results of the last call to check() - * - * This is roughly the same as the function pwquality_strerror, - * only with QStrings instead, and using the Qt translation scheme. - * It is used under the terms of the GNU GPL v3 or later, as - * allowed by the libpwquality license (LICENSES/GPLv2+-libpwquality) - */ - QString explanation() - { - if ( m_rv >= arbitrary_minimum_strength ) - { - return QString(); - } - if ( m_rv >= 0 ) - { - return QCoreApplication::translate( "PWQ", "Password is too weak" ); - } - - switch ( m_rv ) - { - case PWQ_ERROR_MEM_ALLOC: - if ( !m_errorString.isEmpty() ) - { - return QCoreApplication::translate( "PWQ", "Memory allocation error when setting '%1'" ) - .arg( m_errorString ); - } - return QCoreApplication::translate( "PWQ", "Memory allocation error" ); - case PWQ_ERROR_SAME_PASSWORD: - return QCoreApplication::translate( "PWQ", "The password is the same as the old one" ); - case PWQ_ERROR_PALINDROME: - return QCoreApplication::translate( "PWQ", "The password is a palindrome" ); - case PWQ_ERROR_CASE_CHANGES_ONLY: - return QCoreApplication::translate( "PWQ", "The password differs with case changes only" ); - case PWQ_ERROR_TOO_SIMILAR: - return QCoreApplication::translate( "PWQ", "The password is too similar to the old one" ); - case PWQ_ERROR_USER_CHECK: - return QCoreApplication::translate( "PWQ", "The password contains the user name in some form" ); - case PWQ_ERROR_GECOS_CHECK: - return QCoreApplication::translate( - "PWQ", "The password contains words from the real name of the user in some form" ); - case PWQ_ERROR_BAD_WORDS: - return QCoreApplication::translate( "PWQ", "The password contains forbidden words in some form" ); - case PWQ_ERROR_MIN_DIGITS: - if ( m_errorCount ) - { - return QCoreApplication::translate( - "PWQ", "The password contains fewer than %n digits", nullptr, m_errorCount ); - } - return QCoreApplication::translate( "PWQ", "The password contains too few digits" ); - case PWQ_ERROR_MIN_UPPERS: - if ( m_errorCount ) - { - return QCoreApplication::translate( - "PWQ", "The password contains fewer than %n uppercase letters", nullptr, m_errorCount ); - } - return QCoreApplication::translate( "PWQ", "The password contains too few uppercase letters" ); - case PWQ_ERROR_MIN_LOWERS: - if ( m_errorCount ) - { - return QCoreApplication::translate( - "PWQ", "The password contains fewer than %n lowercase letters", nullptr, m_errorCount ); - } - return QCoreApplication::translate( "PWQ", "The password contains too few lowercase letters" ); - case PWQ_ERROR_MIN_OTHERS: - if ( m_errorCount ) - { - return QCoreApplication::translate( - "PWQ", "The password contains fewer than %n non-alphanumeric characters", nullptr, m_errorCount ); - } - return QCoreApplication::translate( "PWQ", "The password contains too few non-alphanumeric characters" ); - case PWQ_ERROR_MIN_LENGTH: - if ( m_errorCount ) - { - return QCoreApplication::translate( - "PWQ", "The password is shorter than %n characters", nullptr, m_errorCount ); - } - return QCoreApplication::translate( "PWQ", "The password is too short" ); - case PWQ_ERROR_ROTATED: - return QCoreApplication::translate( "PWQ", "The password is a rotated version of the previous one" ); - case PWQ_ERROR_MIN_CLASSES: - if ( m_errorCount ) - { - return QCoreApplication::translate( - "PWQ", "The password contains fewer than %n character classes", nullptr, m_errorCount ); - } - return QCoreApplication::translate( "PWQ", "The password does not contain enough character classes" ); - case PWQ_ERROR_MAX_CONSECUTIVE: - if ( m_errorCount ) - { - return QCoreApplication::translate( - "PWQ", "The password contains more than %n same characters consecutively", nullptr, m_errorCount ); - } - return QCoreApplication::translate( "PWQ", "The password contains too many same characters consecutively" ); - case PWQ_ERROR_MAX_CLASS_REPEAT: - if ( m_errorCount ) - { - return QCoreApplication::translate( - "PWQ", - "The password contains more than %n characters of the same class consecutively", - nullptr, - m_errorCount ); - } - return QCoreApplication::translate( - "PWQ", "The password contains too many characters of the same class consecutively" ); - case PWQ_ERROR_MAX_SEQUENCE: - if ( m_errorCount ) - { - return QCoreApplication::translate( - "PWQ", - "The password contains monotonic sequence longer than %n characters", - nullptr, - m_errorCount ); - } - return QCoreApplication::translate( "PWQ", - "The password contains too long of a monotonic character sequence" ); - case PWQ_ERROR_EMPTY_PASSWORD: - return QCoreApplication::translate( "PWQ", "No password supplied" ); - case PWQ_ERROR_RNG: - return QCoreApplication::translate( "PWQ", "Cannot obtain random numbers from the RNG device" ); - case PWQ_ERROR_GENERATION_FAILED: - return QCoreApplication::translate( "PWQ", - "Password generation failed - required entropy too low for settings" ); - case PWQ_ERROR_CRACKLIB_CHECK: - if ( !m_errorString.isEmpty() ) - { - return QCoreApplication::translate( "PWQ", "The password fails the dictionary check - %1" ) - .arg( m_errorString ); - } - return QCoreApplication::translate( "PWQ", "The password fails the dictionary check" ); - case PWQ_ERROR_UNKNOWN_SETTING: - if ( !m_errorString.isEmpty() ) - { - return QCoreApplication::translate( "PWQ", "Unknown setting - %1" ).arg( m_errorString ); - } - return QCoreApplication::translate( "PWQ", "Unknown setting" ); - case PWQ_ERROR_INTEGER: - if ( !m_errorString.isEmpty() ) - { - return QCoreApplication::translate( "PWQ", "Bad integer value of setting - %1" ).arg( m_errorString ); - } - return QCoreApplication::translate( "PWQ", "Bad integer value" ); - case PWQ_ERROR_NON_INT_SETTING: - if ( !m_errorString.isEmpty() ) - { - return QCoreApplication::translate( "PWQ", "Setting %1 is not of integer type" ).arg( m_errorString ); - } - return QCoreApplication::translate( "PWQ", "Setting is not of integer type" ); - case PWQ_ERROR_NON_STR_SETTING: - if ( !m_errorString.isEmpty() ) - { - return QCoreApplication::translate( "PWQ", "Setting %1 is not of string type" ).arg( m_errorString ); - } - return QCoreApplication::translate( "PWQ", "Setting is not of string type" ); - case PWQ_ERROR_CFGFILE_OPEN: - return QCoreApplication::translate( "PWQ", "Opening the configuration file failed" ); - case PWQ_ERROR_CFGFILE_MALFORMED: - return QCoreApplication::translate( "PWQ", "The configuration file is malformed" ); - case PWQ_ERROR_FATAL_FAILURE: - return QCoreApplication::translate( "PWQ", "Fatal failure" ); - default: - return QCoreApplication::translate( "PWQ", "Unknown error" ); - } - } - -private: - QString m_errorString; ///< Textual error from last call to check() - int m_errorCount = 0; ///< Count (used in %n) error from last call to check() - int m_rv = 0; ///< Return value from libpwquality - - pwquality_settings_t* m_settings = nullptr; -}; - -DEFINE_CHECK_FUNC( libpwquality ) -{ - if ( !value.canConvert< QVariantList >() ) - { - cWarning() << "libpwquality settings is not a list"; - return; - } - - QVariantList l = value.toList(); - unsigned int requirement_count = 0; - auto settings = std::make_shared< PWSettingsHolder >(); - for ( const auto& v : l ) - { - if ( Calamares::typeOf( v ) == Calamares::StringVariantType ) - { - QString option = v.toString(); - int r = settings->set( option ); - if ( r ) - { - cWarning() << "unrecognized libpwquality setting" << option; - } - else - { - cDebug() << Logger::SubEntry << "libpwquality setting" << option; - ++requirement_count; - } - } - else - { - cWarning() << "unrecognized libpwquality setting" << v; - } - } - - /* Something actually added? */ - if ( requirement_count ) - { - checks.push_back( PasswordCheck( [ settings ]() { return settings->explanation(); }, - [ settings ]( const QString& s ) - { - int r = settings->check( s ); - if ( r < 0 ) - { - cWarning() << "libpwquality error" << r - << pwquality_strerror( nullptr, 256, r, nullptr ); - } - else if ( r < settings->arbitrary_minimum_strength ) - { - cDebug() << "Password strength" << r << "too low"; - } - return r >= settings->arbitrary_minimum_strength; - }, - PasswordCheck::Weight( 100 ) ) ); - } -} -#endif diff --git a/src/modules/users/CheckPWQuality.h b/src/modules/users/CheckPWQuality.h deleted file mode 100644 index db2cba0af2..0000000000 --- a/src/modules/users/CheckPWQuality.h +++ /dev/null @@ -1,80 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef CHECKPWQUALITY_H -#define CHECKPWQUALITY_H - -#include -#include -#include - -#include - -/** - * Support for (dynamic) checks on the password's validity. - * This can be used to implement password requirements like - * "at least 6 characters". Function addPasswordCheck() - * instantiates these and adds them to the list of checks. - */ -class PasswordCheck -{ -public: - /** Return true if the string is acceptable. */ - using AcceptFunc = std::function< bool( const QString& ) >; - using MessageFunc = std::function< QString() >; - - using Weight = size_t; - - /** @brief Generate a @p message if @p filter returns true - * - * When @p filter returns true on the proposed password, the - * password is accepted (by this check). If false, then the - * @p message will be shown to the user. - * - * @p weight is used to order the checks (low-weight goes first). - */ - PasswordCheck( MessageFunc message, AcceptFunc filter, Weight weight = 1000 ); - /** @brief Null check, always accepts, no message */ - PasswordCheck(); - - /** Applies this check to the given password string @p s - * and returns an empty string if the password is ok - * according to this filter. Returns a message describing - * what is wrong if not. - */ - QString filter( const QString& s ) const { return m_accept( s ) ? QString() : m_message(); } - - Weight weight() const { return m_weight; } - bool operator<( const PasswordCheck& other ) const { return weight() < other.weight(); } - -private: - Weight m_weight; - MessageFunc m_message; - AcceptFunc m_accept; -}; - -using PasswordCheckList = QVector< PasswordCheck >; - -/* Each of these functions adds a check (if possible) to the list - * of checks; they use the configuration value(s) from the - * variant. If the value doesn't make sense, each function - * may skip adding a check, and do nothing (it should log - * an error, though). - */ -#define DEFINE_CHECK_FUNC_impl( x ) add_check_##x( PasswordCheckList& checks, const QVariant& value ) -#define DEFINE_CHECK_FUNC( x ) void DEFINE_CHECK_FUNC_impl( x ) -#define DECLARE_CHECK_FUNC( x ) void DEFINE_CHECK_FUNC_impl( x ); - -DECLARE_CHECK_FUNC( minLength ) -DECLARE_CHECK_FUNC( maxLength ) -#ifdef HAVE_LIBPWQUALITY -DECLARE_CHECK_FUNC( libpwquality ) -#endif - -#endif diff --git a/src/modules/users/Config.cpp b/src/modules/users/Config.cpp deleted file mode 100644 index 1e6db0f334..0000000000 --- a/src/modules/users/Config.cpp +++ /dev/null @@ -1,1009 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "Config.h" - -#include "CreateUserJob.h" -#include "MiscJobs.h" -#include "SetHostNameJob.h" -#include "SetPasswordJob.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "compat/Variant.h" -#include "utils/Logger.h" -#include "utils/String.h" -#include "utils/StringExpander.h" -#include "utils/Variant.h" - -#include -#include -#include -#include -#include - -#ifdef HAVE_ICU -#include -#include - -//Needed for ICU to apply some transliteration ruleset. -//Still needs to be adjusted to fit the needs of the most of users -static const char TRANSLITERATOR_ID[] = "Russian-Latin/BGN;" - "Greek-Latin/UNGEGN;" - "Any-Latin;" - "Latin-ASCII"; -#endif - -#include - -static const QRegularExpression USERNAME_RX( "^[a-z_][a-z0-9_-]*[$]?$" ); // Note anchors begin and end -static constexpr const int USERNAME_MAX_LENGTH = 31; - -static const QRegularExpression HOSTNAME_RX( "^[a-zA-Z0-9][-a-zA-Z0-9_]*$" ); // Note anchors begin and end -static constexpr const int HOSTNAME_MIN_LENGTH = 2; -static constexpr const int HOSTNAME_MAX_LENGTH = 63; - -static void -updateGSAutoLogin( bool doAutoLogin, const QString& login ) -{ - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - if ( !gs ) - { - cWarning() << "No Global Storage available"; - return; - } - - if ( doAutoLogin && !login.isEmpty() ) - { - gs->insert( "autoLoginUser", login ); - } - else - { - gs->remove( "autoLoginUser" ); - } - - if ( login.isEmpty() ) - { - gs->remove( "username" ); - } - else - { - gs->insert( "username", 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() -{ - // *INDENT-OFF* - // clang-format off - static const NamedEnumTable< HostNameAction > names { - { QStringLiteral( "none" ), HostNameAction::None }, - { QStringLiteral( "etcfile" ), HostNameAction::EtcHostname }, - { QStringLiteral( "etc" ), HostNameAction::EtcHostname }, - { QStringLiteral( "hostnamed" ), HostNameAction::SystemdHostname }, - { QStringLiteral( "transient" ), HostNameAction::Transient }, - }; - // clang-format on - // *INDENT-ON* - - return names; -} - -Config::Config( QObject* parent ) - : Calamares::ModuleSystem::Config( parent ) - , m_forbiddenHostNames( alwaysForbiddenHostNames() ) - , m_forbiddenLoginNames( alwaysForbiddenLoginNames() ) -{ - emit readyChanged( m_isReady ); // false - - // Gang together all the changes of status to one readyChanged() signal - connect( this, &Config::hostnameStatusChanged, this, &Config::checkReady ); - connect( this, &Config::loginNameStatusChanged, this, &Config::checkReady ); - connect( this, &Config::fullNameChanged, this, &Config::checkReady ); - connect( this, &Config::userPasswordStatusChanged, this, &Config::checkReady ); - connect( this, &Config::rootPasswordStatusChanged, this, &Config::checkReady ); - connect( this, &Config::reuseUserPasswordForRootChanged, this, &Config::checkReady ); - connect( this, &Config::requireStrongPasswordsChanged, this, &Config::checkReady ); -} - -Config::~Config() {} - -void -Config::setUserShell( const QString& shell ) -{ - if ( !shell.isEmpty() && !shell.startsWith( '/' ) ) - { - cWarning() << "User shell" << shell << "is not an absolute path."; - return; - } - if ( shell != m_userShell ) - { - m_userShell = shell; - emit userShellChanged( shell ); - // The shell is put into GS as well. - auto* gs = Calamares::JobQueue::instance()->globalStorage(); - if ( gs ) - { - gs->insert( "userShell", shell ); - } - } -} - -static inline void -insertInGlobalStorage( const QString& key, const QString& group ) -{ - auto* gs = Calamares::JobQueue::instance()->globalStorage(); - if ( !gs || group.isEmpty() ) - { - return; - } - gs->insert( key, group ); -} - -void -Config::setAutoLoginGroup( const QString& group ) -{ - if ( group != m_autoLoginGroup ) - { - m_autoLoginGroup = group; - insertInGlobalStorage( QStringLiteral( "autoLoginGroup" ), group ); - emit autoLoginGroupChanged( group ); - } -} - -QStringList -Config::groupsForThisUser() const -{ - QStringList l; - l.reserve( defaultGroups().size() + 1 ); - - for ( const auto& g : defaultGroups() ) - { - l << g.name(); - } - if ( doAutoLogin() && !autoLoginGroup().isEmpty() ) - { - l << autoLoginGroup(); - } - - return l; -} - -void -Config::setSudoersGroup( const QString& group ) -{ - if ( group != m_sudoersGroup ) - { - m_sudoersGroup = group; - insertInGlobalStorage( QStringLiteral( "sudoersGroup" ), group ); - emit sudoersGroupChanged( group ); - } -} - -void -Config::setLoginName( const QString& login ) -{ - CONFIG_PREVENT_EDITING( QString, "loginName" ); - if ( login != m_loginName ) - { - m_customLoginName = !login.isEmpty(); - m_loginName = login; - updateGSAutoLogin( doAutoLogin(), login ); - emit loginNameChanged( login ); - emit loginNameStatusChanged( loginNameStatus() ); - } -} - -const QStringList& -Config::forbiddenLoginNames() const -{ - return m_forbiddenLoginNames; -} - -QString -Config::loginNameStatus() const -{ - // An empty login is "ok", even if it isn't really - if ( m_loginName.isEmpty() ) - { - return QString(); - } - - if ( m_loginName.length() > USERNAME_MAX_LENGTH ) - { - return tr( "Your username is too long." ); - } - - QRegularExpression validateFirstLetter( "^[a-z_]" ); - if ( m_loginName.indexOf( validateFirstLetter ) != 0 ) - { - return tr( "Your username must start with a lowercase letter or underscore." ); - } - if ( m_loginName.indexOf( USERNAME_RX ) != 0 ) - { - 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(); -} - -void -Config::setHostName( const QString& host ) -{ - if ( hostnameAction() != HostNameAction::EtcHostname && hostnameAction() != HostNameAction::SystemdHostname ) - { - cDebug() << "Ignoring hostname" << host << "No hostname will be set."; - return; - } - if ( host != m_hostname ) - { - m_customHostName = !host.isEmpty(); - m_hostname = host; - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - if ( host.isEmpty() ) - { - gs->remove( "hostname" ); - } - else - { - gs->insert( "hostname", host ); - } - emit hostnameChanged( host ); - emit hostnameStatusChanged( hostnameStatus() ); - } -} - -const QStringList& -Config::forbiddenHostNames() const -{ - return m_forbiddenHostNames; -} - -QString -Config::hostnameStatus() const -{ - // An empty hostname is "ok", even if it isn't really - if ( m_hostname.isEmpty() ) - { - return QString(); - } - - if ( m_hostname.length() < HOSTNAME_MIN_LENGTH ) - { - return tr( "Your hostname is too short." ); - } - if ( m_hostname.length() > HOSTNAME_MAX_LENGTH ) - { - return tr( "Your hostname is too long." ); - } - - // "LocalHost" is just as forbidden as "localhost" - if ( forbiddenHostNames().contains( m_hostname, Qt::CaseInsensitive ) ) - { - return tr( "'%1' is not allowed as hostname." ).arg( m_hostname ); - } - - if ( m_hostname.indexOf( HOSTNAME_RX ) != 0 ) - { - return tr( "Only letters, numbers, underscore and hyphen are allowed." ); - } - - return QString(); -} - -static QString -cleanupForHostname( const QString& s ) -{ - QRegularExpression dmirx( "(^Apple|\\(.*\\)|[^a-zA-Z0-9])", QRegularExpression::CaseInsensitiveOption ); - return s.toLower().replace( dmirx, " " ).remove( ' ' ); -} - -/** @brief Guess the machine's name - * - * If there is DMI data, use that; otherwise, just call the machine "-pc". - * Reads the DMI data just once. - */ -static QString -guessProductName() -{ - static bool tried = false; - static QString dmiProduct; - - if ( !tried ) - { - QFile dmiFile( QStringLiteral( "/sys/devices/virtual/dmi/id/product_name" ) ); - QFile modelFile( QStringLiteral( "/proc/device-tree/model" ) ); - - if ( dmiFile.exists() && dmiFile.open( QIODevice::ReadOnly ) ) - { - dmiProduct = cleanupForHostname( QString::fromLocal8Bit( dmiFile.readAll().simplified().data() ) ); - if ( !dmiProduct.isEmpty() ) - { - tried = true; - return dmiProduct; - } - } - - if ( modelFile.exists() && modelFile.open( QIODevice::ReadOnly ) ) - { - dmiProduct - = cleanupForHostname( QString::fromLocal8Bit( modelFile.readAll().chopped( 1 ).simplified().data() ) ); - if ( !dmiProduct.isEmpty() ) - { - tried = true; - return dmiProduct; - } - } - - dmiProduct = QStringLiteral( "pc" ); - tried = true; - } - return dmiProduct; -} -#ifdef HAVE_ICU -static QString -transliterate( const QString& input ) -{ - static auto ue = UErrorCode::U_ZERO_ERROR; - static auto transliterator = std::unique_ptr< icu::Transliterator >( - icu::Transliterator::createInstance( TRANSLITERATOR_ID, UTRANS_FORWARD, ue ) ); - - if ( ue != UErrorCode::U_ZERO_ERROR ) - { - cWarning() << "Can't create transliterator"; - - //it'll be checked later for non-ASCII characters - return input; - } - - icu::UnicodeString transliterable( input.utf16() ); - transliterator->transliterate( transliterable ); - return QString::fromUtf16( transliterable.getTerminatedBuffer() ); -} -#else -static QString -transliterate( const QString& input ) -{ - return input; -} -#endif - -static QString -makeLoginNameSuggestion( const QStringList& parts ) -{ - if ( parts.isEmpty() || parts.first().isEmpty() ) - { - return QString(); - } - - QString usernameSuggestion = parts.first(); - for ( int i = 1; i < parts.length(); ++i ) - { - if ( !parts.value( i ).isEmpty() ) - { - usernameSuggestion.append( parts.value( i ).at( 0 ) ); - } - } - - return usernameSuggestion.indexOf( USERNAME_RX ) != -1 ? usernameSuggestion : QString(); -} - -/** @brief Return an invalid string for use in a hostname, if @p s is empty - * - * Maps empty to "^" (which is invalid in a hostname), everything else - * returns @p s itself. - */ -static QString -invalidEmpty( const QString& s ) -{ - return s.isEmpty() ? QStringLiteral( "^" ) : s; -} - -STATICTEST QString -makeHostnameSuggestion( const QString& templateString, const QStringList& fullNameParts, const QString& loginName ) -{ - Calamares::String::DictionaryExpander d; - // User data - d.add( QStringLiteral( "first" ), - invalidEmpty( fullNameParts.isEmpty() ? QString() : cleanupForHostname( fullNameParts.first() ) ) ) - .add( QStringLiteral( "name" ), invalidEmpty( cleanupForHostname( fullNameParts.join( QString() ) ) ) ) - .add( QStringLiteral( "login" ), invalidEmpty( cleanupForHostname( loginName ) ) ) - // Hardware data - .add( QStringLiteral( "product" ), guessProductName() ) - .add( QStringLiteral( "product2" ), cleanupForHostname( QSysInfo::prettyProductName() ) ) - .add( QStringLiteral( "cpu" ), cleanupForHostname( QSysInfo::currentCpuArchitecture() ) ) - // Hostname data - .add( QStringLiteral( "host" ), invalidEmpty( cleanupForHostname( QSysInfo::machineHostName() ) ) ); - - QString hostnameSuggestion = d.expand( templateString ); - - // RegExp for valid hostnames; if the suggestion produces a valid name, return it - static const QRegularExpression HOSTNAME_RX( "^[a-zA-Z0-9][-a-zA-Z0-9_]*$" ); - return hostnameSuggestion.indexOf( HOSTNAME_RX ) != -1 ? hostnameSuggestion : QString(); -} - -void -Config::setFullName( const QString& name ) -{ - CONFIG_PREVENT_EDITING( QString, "fullName" ); - - if ( name.isEmpty() && !m_fullName.isEmpty() ) - { - if ( !m_customHostName ) - { - setHostName( name ); - } - if ( !m_customLoginName ) - { - setLoginName( name ); - } - m_fullName = name; - emit fullNameChanged( name ); - } - - if ( name != m_fullName ) - { - m_fullName = name; - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - if ( name.isEmpty() ) - { - gs->remove( "fullname" ); - } - else - { - gs->insert( "fullname", name ); - } - emit fullNameChanged( name ); - - // Build login and hostname, if needed - static QRegularExpression rx( "[^a-zA-Z0-9 ]" ); - - const QString cleanName = Calamares::String::removeDiacritics( transliterate( name ) ) - .replace( QRegularExpression( "[-']" ), "" ) - .replace( rx, " " ) - .toLower() - .simplified(); - - QStringList cleanParts = cleanName.split( ' ' ); - - if ( !m_customLoginName ) - { - const QString login = makeLoginNameSuggestion( cleanParts ); - if ( !login.isEmpty() && login != m_loginName ) - { - setLoginName( login ); - // It's **still** not custom, though setLoginName() sets that - m_customLoginName = false; - } - } - if ( !m_customHostName ) - { - const QString hostname = makeHostnameSuggestion( m_hostnameTemplate, cleanParts, loginName() ); - if ( !hostname.isEmpty() && hostname != m_hostname ) - { - setHostName( hostname ); - // Still not custom - m_customHostName = false; - } - } - } -} - -void -Config::setAutoLogin( bool b ) -{ - if ( b != m_doAutoLogin ) - { - m_doAutoLogin = b; - updateGSAutoLogin( b, loginName() ); - emit autoLoginChanged( b ); - } -} - -void -Config::setReuseUserPasswordForRoot( bool reuse ) -{ - if ( reuse != m_reuseUserPasswordForRoot ) - { - m_reuseUserPasswordForRoot = reuse; - emit reuseUserPasswordForRootChanged( reuse ); - { - auto rp = rootPasswordStatus(); - emit rootPasswordStatusChanged( rp.first, rp.second ); - } - } -} - -void -Config::setRequireStrongPasswords( bool strong ) -{ - if ( strong != m_requireStrongPasswords ) - { - m_requireStrongPasswords = strong; - emit requireStrongPasswordsChanged( strong ); - { - auto rp = rootPasswordStatus(); - emit rootPasswordStatusChanged( rp.first, rp.second ); - } - { - auto up = userPasswordStatus(); - emit userPasswordStatusChanged( up.first, up.second ); - } - } -} - -void -Config::setUserPassword( const QString& s ) -{ - if ( s != m_userPassword ) - { - m_userPassword = s; - const auto p = passwordStatus( m_userPassword, m_userPasswordSecondary ); - emit userPasswordStatusChanged( p.first, p.second ); - emit userPasswordChanged( s ); - } -} - -void -Config::setUserPasswordSecondary( const QString& s ) -{ - if ( s != m_userPasswordSecondary ) - { - m_userPasswordSecondary = s; - const auto p = passwordStatus( m_userPassword, m_userPasswordSecondary ); - emit userPasswordStatusChanged( p.first, p.second ); - emit userPasswordSecondaryChanged( s ); - } -} - -/** @brief Checks two copies of the password for validity - * - * Given two copies of the password -- generally the password and - * the secondary fields -- checks them for validity and returns - * a pair of . - * - */ -Config::PasswordStatus -Config::passwordStatus( const QString& pw1, const QString& pw2 ) const -{ - if ( pw1 != pw2 ) - { - return qMakePair( PasswordValidity::Invalid, tr( "Your passwords do not match!" ) ); - } - - bool failureIsFatal = requireStrongPasswords(); - for ( const auto& pc : m_passwordChecks ) - { - QString message = pc.filter( pw1 ); - - if ( !message.isEmpty() ) - { - return qMakePair( failureIsFatal ? PasswordValidity::Invalid : PasswordValidity::Weak, message ); - } - } - - return qMakePair( PasswordValidity::Valid, tr( "OK!" ) ); -} - -Config::PasswordStatus -Config::userPasswordStatus() const -{ - return passwordStatus( m_userPassword, m_userPasswordSecondary ); -} - -int -Config::userPasswordValidity() const -{ - auto p = userPasswordStatus(); - return p.first; -} - -QString -Config::userPasswordMessage() const -{ - auto p = userPasswordStatus(); - return p.second; -} - -void -Config::setRootPassword( const QString& s ) -{ - if ( writeRootPassword() && s != m_rootPassword ) - { - m_rootPassword = s; - const auto p = passwordStatus( m_rootPassword, m_rootPasswordSecondary ); - emit rootPasswordStatusChanged( p.first, p.second ); - emit rootPasswordChanged( s ); - } -} - -void -Config::setRootPasswordSecondary( const QString& s ) -{ - if ( writeRootPassword() && s != m_rootPasswordSecondary ) - { - m_rootPasswordSecondary = s; - const auto p = passwordStatus( m_rootPassword, m_rootPasswordSecondary ); - emit rootPasswordStatusChanged( p.first, p.second ); - emit rootPasswordSecondaryChanged( s ); - } -} - -QString -Config::rootPassword() const -{ - if ( writeRootPassword() ) - { - if ( reuseUserPasswordForRoot() ) - { - return userPassword(); - } - return m_rootPassword; - } - return QString(); -} - -QString -Config::rootPasswordSecondary() const -{ - if ( writeRootPassword() ) - { - if ( reuseUserPasswordForRoot() ) - { - return userPasswordSecondary(); - } - return m_rootPasswordSecondary; - } - return QString(); -} - -Config::PasswordStatus -Config::rootPasswordStatus() const -{ - if ( writeRootPassword() && !reuseUserPasswordForRoot() ) - { - return passwordStatus( m_rootPassword, m_rootPasswordSecondary ); - } - else - { - return userPasswordStatus(); - } -} - -int -Config::rootPasswordValidity() const -{ - auto p = rootPasswordStatus(); - return p.first; -} - -QString -Config::rootPasswordMessage() const -{ - auto p = rootPasswordStatus(); - return p.second; -} - -bool -Config::isReady() const -{ - bool readyFullName = !fullName().isEmpty(); // Needs some text - bool readyHostname = hostnameStatus().isEmpty(); // .. no warning message - bool readyUsername = !loginName().isEmpty() && loginNameStatus().isEmpty(); // .. no warning message - bool readyUserPassword = userPasswordValidity() != Config::PasswordValidity::Invalid; - bool readyRootPassword = rootPasswordValidity() != Config::PasswordValidity::Invalid; - return readyFullName && readyHostname && readyUsername && readyUserPassword && readyRootPassword; -} - -/** @brief Update ready status and emit signal - * - * This is a "concentrator" private slot for all the status-changed - * signals, so that readyChanged() is emitted only when needed. - */ -void -Config::checkReady() -{ - bool b = isReady(); - if ( b != m_isReady ) - { - m_isReady = b; - emit readyChanged( b ); - } -} - -STATICTEST void -setConfigurationDefaultGroups( const QVariantMap& map, QList< GroupDescription >& defaultGroups ) -{ - defaultGroups.clear(); - - const QString key( "defaultGroups" ); - auto groupsFromConfig = map.value( key ).toList(); - if ( groupsFromConfig.isEmpty() ) - { - if ( map.contains( key ) && map.value( key ).isValid() && map.value( key ).canConvert< QVariantList >() ) - { - // Explicitly set, but empty: this is valid, but unusual. - cDebug() << key << "has explicit empty value."; - } - else - { - // By default give the user a handful of "traditional" groups, if - // none are specified at all. These are system (GID < 1000) groups. - cWarning() << "Using fallback groups. Please check *defaultGroups* value in users.conf"; - for ( const auto& s : { "lp", "video", "network", "storage", "wheel", "audio" } ) - { - defaultGroups.append( - GroupDescription( s, GroupDescription::CreateIfNeeded {}, GroupDescription::SystemGroup {} ) ); - } - } - } - else - { - for ( const auto& v : groupsFromConfig ) - { - if ( Calamares::typeOf( v ) == Calamares::StringVariantType ) - { - defaultGroups.append( GroupDescription( v.toString() ) ); - } - else if ( Calamares::typeOf( v ) == Calamares::MapVariantType ) - { - const auto innermap = v.toMap(); - QString name = Calamares::getString( innermap, "name" ); - if ( !name.isEmpty() ) - { - defaultGroups.append( GroupDescription( name, - Calamares::getBool( innermap, "must_exist", false ), - Calamares::getBool( innermap, "system", false ) ) ); - } - else - { - cWarning() << "Ignoring *defaultGroups* entry without a name" << v; - } - } - else - { - cWarning() << "Unknown *defaultGroups* entry" << v; - } - } - } -} - -STATICTEST HostNameAction -getHostNameAction( const QVariantMap& configurationMap ) -{ - HostNameAction setHostName = HostNameAction::EtcHostname; - QString hostnameActionString = Calamares::getString( configurationMap, "location" ); - if ( !hostnameActionString.isEmpty() ) - { - bool ok = false; - setHostName = hostnameActionNames().find( hostnameActionString, ok ); - if ( !ok ) - { - setHostName = HostNameAction::EtcHostname; // Rather than none - } - } - - return setHostName; -} - -/** @brief Process entries in the passwordRequirements config entry - * - * Called once for each item in the config entry, which should - * be a key-value pair. What makes sense as a value depends on - * the key. Supported keys are documented in users.conf. - * - * @return if the check was added, returns @c true - */ -STATICTEST bool -addPasswordCheck( const QString& key, const QVariant& value, PasswordCheckList& passwordChecks ) -{ - if ( key == "minLength" ) - { - add_check_minLength( passwordChecks, value ); - } - else if ( key == "maxLength" ) - { - add_check_maxLength( passwordChecks, value ); - } - else if ( key == "nonempty" ) - { - cWarning() << "nonempty check is ignored; use minLength: 1"; - return false; - } -#ifdef CHECK_PWQUALITY - else if ( key == "libpwquality" ) - { - add_check_libpwquality( passwordChecks, value ); - } -#endif // CHECK_PWQUALITY - else - { - cWarning() << "Unknown password-check key" << key; - return false; - } - return true; -} - -/** @brief Returns a value of either key from the map - * - * Takes a function (e.g. getBool, or getString) and two keys, - * returning the value in the map of the one that is there (or @p defaultArg) - */ -template < typename T, typename U > -T -either( T ( *f )( const QVariantMap&, const QString&, U ), - const QVariantMap& configurationMap, - const QString& oldKey, - const QString& newKey, - U defaultArg ) -{ - if ( configurationMap.contains( oldKey ) ) - { - return f( configurationMap, oldKey, defaultArg ); - } - else - { - return f( configurationMap, newKey, defaultArg ); - } -} - -/** @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 ) -{ - // Handle *user* key and subkeys and legacy settings - { - bool ok = false; // Ignored - QVariantMap userSettings = Calamares::getSubMap( configurationMap, "user", ok ); - - QString shell( QLatin1String( "/bin/bash" ) ); // as if it's not set at all - if ( userSettings.contains( "shell" ) ) - { - shell = Calamares::getString( userSettings, "shell" ); - } - // Now it might be explicitly set to empty, which is ok - setUserShell( shell ); - - m_forbiddenLoginNames = Calamares::getStringList( userSettings, "forbidden_names" ); - m_forbiddenLoginNames << alwaysForbiddenLoginNames(); - tidy( m_forbiddenLoginNames ); - } - - setAutoLoginGroup( either< QString, const QString& >( - Calamares::getString, configurationMap, "autologinGroup", "autoLoginGroup", QString() ) ); - setSudoersGroup( Calamares::getString( configurationMap, "sudoersGroup" ) ); - m_sudoStyle = Calamares::getBool( configurationMap, "sudoersConfigureWithGroup", false ) ? SudoStyle::UserAndGroup - : SudoStyle::UserOnly; - - // Handle *hostname* key and subkeys and legacy settings - { - bool ok = false; // Ignored - QVariantMap hostnameSettings = Calamares::getSubMap( configurationMap, "hostname", ok ); - - m_hostnameAction = getHostNameAction( hostnameSettings ); - m_writeEtcHosts = Calamares::getBool( hostnameSettings, "writeHostsFile", true ); - m_hostnameTemplate - = Calamares::getString( hostnameSettings, "template", QStringLiteral( "${first}-${product}" ) ); - - m_forbiddenHostNames = Calamares::getStringList( hostnameSettings, "forbidden_names" ); - m_forbiddenHostNames << alwaysForbiddenHostNames(); - tidy( m_forbiddenHostNames ); - } - - setConfigurationDefaultGroups( configurationMap, m_defaultGroups ); - - // Renaming of Autologin -> AutoLogin in 4ffa79d4cf also affected - // configuration keys, which was not intended. Accept both. - m_doAutoLogin = either( - Calamares::getBool, configurationMap, QStringLiteral( "doAutologin" ), QStringLiteral( "doAutoLogin" ), false ); - - m_writeRootPassword = Calamares::getBool( configurationMap, "setRootPassword", true ); - Calamares::JobQueue::instance()->globalStorage()->insert( "setRootPassword", m_writeRootPassword ); - - m_reuseUserPasswordForRoot = Calamares::getBool( configurationMap, "doReusePassword", false ); - - m_permitWeakPasswords = Calamares::getBool( configurationMap, "allowWeakPasswords", false ); - m_requireStrongPasswords - = !m_permitWeakPasswords || !Calamares::getBool( configurationMap, "allowWeakPasswordsDefault", false ); - - // If the value doesn't exist, or isn't a map, this gives an empty map -- no problem - auto pr_checks( configurationMap.value( "passwordRequirements" ).toMap() ); - for ( decltype( pr_checks )::const_iterator i = pr_checks.constBegin(); i != pr_checks.constEnd(); ++i ) - { - addPasswordCheck( i.key(), i.value(), m_passwordChecks ); - } - std::sort( m_passwordChecks.begin(), m_passwordChecks.end() ); - - updateGSAutoLogin( doAutoLogin(), loginName() ); - checkReady(); - - ApplyPresets( *this, configurationMap ) << "fullName" - << "loginName"; -} - -void -Config::finalizeGlobalStorage() const -{ - updateGSAutoLogin( doAutoLogin(), loginName() ); - - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - if ( writeRootPassword() ) - { - gs->insert( "reuseRootPassword", reuseUserPasswordForRoot() ); - } - gs->insert( "password", Calamares::String::obscure( userPassword() ) ); -} - -Calamares::JobList -Config::createJobs() const -{ - Calamares::JobList jobs; - - if ( !isReady() ) - { - return jobs; - } - - Calamares::Job* j; - - if ( !m_sudoersGroup.isEmpty() ) - { - j = new SetupSudoJob( m_sudoersGroup, m_sudoStyle ); - jobs.append( Calamares::job_ptr( j ) ); - } - - j = new SetupGroupsJob( this ); - jobs.append( Calamares::job_ptr( j ) ); - - j = new CreateUserJob( this ); - jobs.append( Calamares::job_ptr( j ) ); - - j = new SetPasswordJob( loginName(), userPassword() ); - jobs.append( Calamares::job_ptr( j ) ); - - j = new SetPasswordJob( "root", rootPassword() ); - jobs.append( Calamares::job_ptr( j ) ); - - j = new SetHostNameJob( this ); - jobs.append( Calamares::job_ptr( j ) ); - - return jobs; -} diff --git a/src/modules/users/Config.h b/src/modules/users/Config.h deleted file mode 100644 index 599fcd6bd7..0000000000 --- a/src/modules/users/Config.h +++ /dev/null @@ -1,356 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef USERS_CONFIG_H -#define USERS_CONFIG_H - -#include "CheckPWQuality.h" - -#include "Job.h" -#include "modulesystem/Config.h" -#include "utils/NamedEnum.h" - -#include -#include -#include - -enum class HostNameAction -{ - None, - EtcHostname, // Write to /etc/hostname directly - SystemdHostname, // Set via hostnamed(1) - Transient, // Force target system transient, remove /etc/hostname -}; - -const NamedEnumTable< HostNameAction >& hostnameActionNames(); - -/** @brief Settings for a single group - * - * The list of defaultgroups from the configuration can be - * set up in a fine-grained way, with both user- and system- - * level groups; this class stores a configuration for each. - */ -class GroupDescription -{ -public: - // TODO: still too-weakly typed, add a macro to define strongly-typed bools - class MustExist : public std::true_type - { - }; - class CreateIfNeeded : public std::false_type - { - }; - class SystemGroup : public std::true_type - { - }; - class UserGroup : public std::false_type - { - }; - - ///@brief An invalid, empty group - GroupDescription() {} - - ///@brief A group with full details - GroupDescription( const QString& name, bool mustExistAlready = CreateIfNeeded {}, bool isSystem = UserGroup {} ) - : m_name( name ) - , m_isValid( !name.isEmpty() ) - , m_mustAlreadyExist( mustExistAlready ) - , m_isSystem( isSystem ) - { - } - - bool isValid() const { return m_isValid; } - bool isSystemGroup() const { return m_isSystem; } - bool mustAlreadyExist() const { return m_mustAlreadyExist; } - QString name() const { return m_name; } - - ///@brief Equality of groups depends only on name and kind - bool operator==( const GroupDescription& rhs ) const - { - return rhs.name() == name() && rhs.isSystemGroup() == isSystemGroup(); - } - -private: - QString m_name; - bool m_isValid = false; - bool m_mustAlreadyExist = false; - bool m_isSystem = false; -}; - - -class PLUGINDLLEXPORT Config : public Calamares::ModuleSystem::Config -{ - Q_OBJECT - - Q_PROPERTY( QString userShell READ userShell WRITE setUserShell NOTIFY userShellChanged ) - - Q_PROPERTY( QString autoLoginGroup READ autoLoginGroup WRITE setAutoLoginGroup NOTIFY autoLoginGroupChanged ) - Q_PROPERTY( QString sudoersGroup READ sudoersGroup WRITE setSudoersGroup NOTIFY sudoersGroupChanged ) - - Q_PROPERTY( bool doAutoLogin READ doAutoLogin WRITE setAutoLogin NOTIFY autoLoginChanged ) - - Q_PROPERTY( QString fullName READ fullName WRITE setFullName NOTIFY fullNameChanged ) - Q_PROPERTY( QString loginName READ loginName WRITE setLoginName NOTIFY loginNameChanged ) - Q_PROPERTY( QString loginNameStatus READ loginNameStatus NOTIFY loginNameStatusChanged ) - - Q_PROPERTY( QString hostname READ hostname WRITE setHostName NOTIFY hostnameChanged ) - Q_PROPERTY( QString hostnameStatus READ hostnameStatus NOTIFY hostnameStatusChanged ) - Q_PROPERTY( HostNameAction hostnameAction READ hostnameAction CONSTANT ) - - Q_PROPERTY( QString userPassword READ userPassword WRITE setUserPassword NOTIFY userPasswordChanged ) - Q_PROPERTY( QString userPasswordSecondary READ userPasswordSecondary WRITE setUserPasswordSecondary NOTIFY - userPasswordSecondaryChanged ) - Q_PROPERTY( int userPasswordValidity READ userPasswordValidity NOTIFY userPasswordStatusChanged STORED false ) - Q_PROPERTY( QString userPasswordMessage READ userPasswordMessage NOTIFY userPasswordStatusChanged STORED false ) - - Q_PROPERTY( QString rootPassword READ rootPassword WRITE setRootPassword NOTIFY rootPasswordChanged ) - Q_PROPERTY( QString rootPasswordSecondary READ rootPasswordSecondary WRITE setRootPasswordSecondary NOTIFY - rootPasswordSecondaryChanged ) - Q_PROPERTY( int rootPasswordValidity READ rootPasswordValidity NOTIFY rootPasswordStatusChanged STORED false ) - Q_PROPERTY( QString rootPasswordMessage READ rootPasswordMessage NOTIFY rootPasswordStatusChanged STORED false ) - - Q_PROPERTY( bool writeRootPassword READ writeRootPassword CONSTANT ) - Q_PROPERTY( bool reuseUserPasswordForRoot READ reuseUserPasswordForRoot WRITE setReuseUserPasswordForRoot NOTIFY - reuseUserPasswordForRootChanged ) - - Q_PROPERTY( bool permitWeakPasswords READ permitWeakPasswords CONSTANT ) - Q_PROPERTY( bool requireStrongPasswords READ requireStrongPasswords WRITE setRequireStrongPasswords NOTIFY - requireStrongPasswordsChanged ) - - Q_PROPERTY( bool ready READ isReady NOTIFY readyChanged STORED false ) - -public: - /** @brief Validity (status) of a password - * - * Valid passwords are: - * - primary and secondary are equal **and** - * - all the password-strength checks pass - * Weak passwords: - * - primary and secondary are equal **and** - * - not all the checks pass **and** - * - permitWeakPasswords is @c true **and** - * - requireStrongPasswords is @c false - * Invalid passwords (all other cases): - * - the primary and secondary values are not equal **or** - * - not all the checks pass and weak passwords are not permitted - */ - enum PasswordValidity - { - Valid = 0, - Weak = 1, - Invalid = 2 - }; - - /** @brief Full password status - * - * A password's status is in two parts: - * - a validity (valid, weak or invalid) - * - a message describing that validity - * The message is empty when the password is valid, but - * weak and invalid passwords have an explanatory message. - */ - using PasswordStatus = QPair< PasswordValidity, QString >; - - Config( QObject* parent = nullptr ); - ~Config() override; - - void setConfigurationMap( const QVariantMap& ) override; - - /** @brief Fill Global Storage with some settings - * - * This should be called when moving on from the view step, - * and copies some things to GS that otherwise would not. - */ - void finalizeGlobalStorage() const; - - /** @brief Jobs for creating user, setting passwords - * - * If the Config object isn't ready yet, returns an empty list. - */ - Calamares::JobList createJobs() const; - - /** @brief Full path to the user's shell executable - * - * Typically this will be /bin/bash, but it can be set from - * the config file with the *userShell* setting. - */ - QString userShell() const { return m_userShell; } - - /// The group of which auto-login users must be a member - QString autoLoginGroup() const { return m_autoLoginGroup; } - - enum class SudoStyle - { - UserOnly, - UserAndGroup - }; - /// The group of which users who can "sudo" must be a member - QString sudoersGroup() const { return m_sudoersGroup; } - SudoStyle sudoStyle() const { return m_sudoStyle; } - - /// The full (GECOS) name of the user - QString fullName() const { return m_fullName; } - /// The login name of the user - QString loginName() const { return m_loginName; } - /// Status message about login -- empty for "ok" - QString loginNameStatus() const; - - /// The host name (name for the system) - QString hostname() const - { - return ( ( hostnameAction() == HostNameAction::EtcHostname ) - || ( hostnameAction() == HostNameAction::SystemdHostname ) ) - ? m_hostname - : QString(); - } - /// Status message about hostname -- empty for "ok" - QString hostnameStatus() const; - /// How to write the hostname - HostNameAction hostnameAction() const { return m_hostnameAction; } - /// Write /etc/hosts ? - bool writeEtcHosts() const { return m_writeEtcHosts; } - - /// Should the user be automatically logged-in? - bool doAutoLogin() const { return m_doAutoLogin; } - /// Should the root password be written (if false, no password is set and the root account is disabled for login) - bool writeRootPassword() const { return m_writeRootPassword; } - /// Should the user's password be used for root, too? (if root is written at all) - bool reuseUserPasswordForRoot() const { return m_reuseUserPasswordForRoot; } - /// Show UI to change the "require strong password" setting? - bool permitWeakPasswords() const { return m_permitWeakPasswords; } - /// Current setting for "require strong password"? - bool requireStrongPasswords() const { return m_requireStrongPasswords; } - - const QList< GroupDescription >& defaultGroups() const { return m_defaultGroups; } - /** @brief the names of all the groups for the current user - * - * Takes into account defaultGroups and autoLogin behavior. - */ - QStringList groupsForThisUser() const; - - // The user enters a password (and again in a separate UI element) - QString userPassword() const { return m_userPassword; } - QString userPasswordSecondary() const { return m_userPasswordSecondary; } - int userPasswordValidity() const; - QString userPasswordMessage() const; - PasswordStatus userPasswordStatus() const; - - // The root password **may** be entered in the UI, or may be suppressed - // entirely when writeRootPassword is off, or may be equal to - // the user password when reuseUserPasswordForRoot is on. - QString rootPassword() const; - QString rootPasswordSecondary() const; - int rootPasswordValidity() const; - QString rootPasswordMessage() const; - PasswordStatus rootPasswordStatus() const; - - bool isReady() const; - - const QStringList& forbiddenLoginNames() const; - const QStringList& forbiddenHostNames() const; - -public Q_SLOTS: - /** @brief Sets the user's shell if possible - * - * If the path is empty, that's ok: no shell will be explicitly set, - * so the user will get whatever shell is set to default in the target. - * - * The given non-empty @p path must be an absolute path (for use inside - * the target system!); if it is not, the shell is not changed. - */ - void setUserShell( const QString& path ); - - /// Sets the autoLogin group; empty is ignored - void setAutoLoginGroup( const QString& group ); - /// Sets the sudoer group; empty is ignored - void setSudoersGroup( const QString& group ); - - /// Sets the full name, may guess a loginName - void setFullName( const QString& name ); - /// Sets the login name (flags it as "custom") - void setLoginName( const QString& login ); - - /// Sets the host name (flags it as "custom") - void setHostName( const QString& host ); - - /// Sets the autoLogin flag - void setAutoLogin( bool b ); - - /// Set to true to use the user password, unchanged, for root too - void setReuseUserPasswordForRoot( bool reuse ); - /// Change setting for "require strong password" - void setRequireStrongPasswords( bool strong ); - - void setUserPassword( const QString& ); - void setUserPasswordSecondary( const QString& ); - void setRootPassword( const QString& ); - void setRootPasswordSecondary( const QString& ); - -signals: - void userShellChanged( const QString& ); - void autoLoginGroupChanged( const QString& ); - void sudoersGroupChanged( const QString& ); - void fullNameChanged( const QString& ); - void loginNameChanged( const QString& ); - void loginNameStatusChanged( const QString& ); - void hostnameChanged( const QString& ); - void hostnameStatusChanged( const QString& ); - void autoLoginChanged( bool ); - void reuseUserPasswordForRootChanged( bool ); - void requireStrongPasswordsChanged( bool ); - void userPasswordChanged( const QString& ); - void userPasswordSecondaryChanged( const QString& ); - void userPasswordStatusChanged( int, const QString& ); - void rootPasswordChanged( const QString& ); - void rootPasswordSecondaryChanged( const QString& ); - void rootPasswordStatusChanged( int, const QString& ); - void readyChanged( bool ) const; - -private: - PasswordStatus passwordStatus( const QString&, const QString& ) const; - void checkReady(); - - QList< GroupDescription > m_defaultGroups; - QString m_userShell; - QString m_autoLoginGroup; - QString m_sudoersGroup; - SudoStyle m_sudoStyle = SudoStyle::UserOnly; - QString m_fullName; - QString m_loginName; - QString m_hostname; - - QString m_userPassword; - QString m_userPasswordSecondary; // enter again to be sure - QString m_rootPassword; - QString m_rootPasswordSecondary; - - bool m_doAutoLogin = false; - - bool m_writeRootPassword = true; - bool m_reuseUserPasswordForRoot = false; - - bool m_permitWeakPasswords = false; - bool m_requireStrongPasswords = true; - - bool m_customLoginName = false; - bool m_customHostName = false; - - bool m_isReady = false; ///< Used to reduce readyChanged signals - - HostNameAction m_hostnameAction = HostNameAction::EtcHostname; - bool m_writeEtcHosts = false; - QString m_hostnameTemplate; - - QStringList m_forbiddenHostNames; - QStringList m_forbiddenLoginNames; - - PasswordCheckList m_passwordChecks; -}; - -#endif diff --git a/src/modules/users/CreateUserJob.cpp b/src/modules/users/CreateUserJob.cpp deleted file mode 100644 index 4e36c5081d..0000000000 --- a/src/modules/users/CreateUserJob.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -#include "CreateUserJob.h" - -#include "Config.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "utils/Logger.h" -#include "utils/Permissions.h" -#include "utils/System.h" - -#include -#include -#include -#include -#include - -CreateUserJob::CreateUserJob( const Config* config ) - : Calamares::Job() - , m_config( config ) -{ -} - -QString -CreateUserJob::prettyName() const -{ - return tr( "Create user %1" ).arg( m_config->loginName() ); -} - -QString -CreateUserJob::prettyDescription() const -{ - return tr( "Create user %1" ).arg( m_config->loginName() ); -} - -QString -CreateUserJob::prettyStatusMessage() const -{ - return m_status.isEmpty() ? tr( "Creating user %1…", "@status" ).arg( m_config->loginName() ) : m_status; -} - -static Calamares::JobResult -createUser( const QString& loginName, const QString& fullName, const QString& shell ) -{ - QStringList useraddCommand; -#ifdef __FreeBSD__ - useraddCommand << "pw" - << "useradd" - << "-n" << loginName << "-m" - << "-c" << fullName; - if ( !shell.isEmpty() ) - { - useraddCommand << "-s" << shell; - } -#else - useraddCommand << "useradd" - << "-m" - << "-U"; - if ( !shell.isEmpty() ) - { - useraddCommand << "-s" << shell; - } - useraddCommand << "-c" << fullName; - useraddCommand << loginName; -#endif - - auto commandResult = Calamares::System::instance()->targetEnvCommand( useraddCommand ); - if ( commandResult.getExitCode() ) - { - cError() << "useradd failed" << commandResult.getExitCode(); - return commandResult.explainProcess( useraddCommand, std::chrono::seconds( 10 ) /* bogus timeout */ ); - } - return Calamares::JobResult::ok(); -} - -static Calamares::JobResult -setUserGroups( const QString& loginName, const QStringList& groups ) -{ - QStringList setgroupsCommand; -#ifdef __FreeBSD__ - setgroupsCommand << "pw" - << "usermod" - << "-n" << loginName << "-G" << groups.join( ',' ); -#else - setgroupsCommand << "usermod" - << "-aG" << groups.join( ',' ) << loginName; -#endif - - auto commandResult = Calamares::System::instance()->targetEnvCommand( setgroupsCommand ); - if ( commandResult.getExitCode() ) - { - cError() << "usermod failed" << commandResult.getExitCode(); - return commandResult.explainProcess( setgroupsCommand, std::chrono::seconds( 10 ) /* bogus timeout */ ); - } - return Calamares::JobResult::ok(); -} - -Calamares::JobResult -CreateUserJob::exec() -{ - QDir destDir; - bool reuseHome = false; - - { - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - destDir = QDir( gs->value( "rootMountPoint" ).toString() ); - reuseHome = gs->value( "reuseHome" ).toBool(); - } - - // If we're looking to reuse the contents of an existing /home. - // This GS setting comes from the **partitioning** module. - if ( reuseHome ) - { - m_status = tr( "Preserving home directory…", "@status" ); - emit progress( 0.2 ); - QString shellFriendlyHome = "/home/" + m_config->loginName(); - QDir existingHome( destDir.absolutePath() + shellFriendlyHome ); - if ( existingHome.exists() ) - { - QString backupDirName = "dotfiles_backup_" + QDateTime::currentDateTime().toString( "yyyy-MM-dd_HH-mm-ss" ); - existingHome.mkdir( backupDirName ); - - // We need the extra `sh -c` here to ensure that we can expand the shell globs - Calamares::System::instance()->targetEnvCall( - { "sh", "-c", "mv -f " + shellFriendlyHome + "/.* " + shellFriendlyHome + "/" + backupDirName } ); - } - } - - cDebug() << "[CREATEUSER]: creating user"; - - m_status = tr( "Creating user %1…", "@status" ).arg( m_config->loginName() ); - emit progress( 0.5 ); - auto useraddResult = createUser( m_config->loginName(), m_config->fullName(), m_config->userShell() ); - if ( !useraddResult ) - { - return useraddResult; - } - - m_status = tr( "Configuring user %1", "@status" ).arg( m_config->loginName() ); - emit progress( 0.8 ); - auto usergroupsResult = setUserGroups( m_config->loginName(), m_config->groupsForThisUser() ); - if ( !usergroupsResult ) - { - return usergroupsResult; - } - - m_status = tr( "Setting file permissions…", "@status" ); - emit progress( 0.9 ); - QString userGroup = QString( "%1:%2" ).arg( m_config->loginName() ).arg( m_config->loginName() ); - QString homeDir = QString( "/home/%1" ).arg( m_config->loginName() ); - auto commandResult = Calamares::System::instance()->targetEnvCommand( { "chown", "-R", userGroup, homeDir } ); - if ( commandResult.getExitCode() ) - { - cError() << "chown failed" << commandResult.getExitCode(); - return commandResult.explainProcess( "chown", std::chrono::seconds( 10 ) /* bogus timeout */ ); - } - - return Calamares::JobResult::ok(); -} diff --git a/src/modules/users/CreateUserJob.h b/src/modules/users/CreateUserJob.h deleted file mode 100644 index 28a48c8861..0000000000 --- a/src/modules/users/CreateUserJob.h +++ /dev/null @@ -1,32 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef CREATEUSERJOB_H -#define CREATEUSERJOB_H - -#include "Job.h" - -class Config; - -class CreateUserJob : public Calamares::Job -{ - Q_OBJECT -public: - CreateUserJob( const Config* config ); - QString prettyName() const override; - QString prettyDescription() const override; - QString prettyStatusMessage() const override; - Calamares::JobResult exec() override; - -private: - const Config* m_config; - QString m_status; -}; - -#endif /* CREATEUSERJOB_H */ diff --git a/src/modules/users/MiscJobs.cpp b/src/modules/users/MiscJobs.cpp deleted file mode 100644 index 75aba41d7f..0000000000 --- a/src/modules/users/MiscJobs.cpp +++ /dev/null @@ -1,210 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "MiscJobs.h" - -#include "Config.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "utils/Logger.h" -#include "utils/Permissions.h" -#include "utils/System.h" - -#include -#include -#include - -SetupSudoJob::SetupSudoJob( const QString& group, Config::SudoStyle style ) - : m_sudoGroup( group ) - , m_sudoStyle( style ) -{ -} - -QString -SetupSudoJob::prettyName() const -{ - return tr( "Configuring
    sudo
    users…", "@status" ); -} - -static QString -designatorForStyle( Config::SudoStyle style ) -{ - switch ( style ) - { - case Config::SudoStyle::UserOnly: - return QStringLiteral( "(ALL)" ); - case Config::SudoStyle::UserAndGroup: - return QStringLiteral( "(ALL:ALL)" ); - } - __builtin_unreachable(); -} - -Calamares::JobResult -SetupSudoJob::exec() -{ - if ( m_sudoGroup.isEmpty() ) - { - cDebug() << "Skipping sudo 10-installer because the sudoGroup is empty."; - return Calamares::JobResult::ok(); - } - - // One % for the sudo format, keep it outside of the string to avoid accidental replacement - QString sudoersLine - = QChar( '%' ) + QString( "%1 ALL=%2 ALL\n" ).arg( m_sudoGroup, designatorForStyle( m_sudoStyle ) ); - auto fileResult = Calamares::System::instance()->createTargetFile( QStringLiteral( "/etc/sudoers.d/10-installer" ), - sudoersLine.toUtf8().constData(), - Calamares::System::WriteMode::Overwrite ); - - if ( fileResult ) - { - if ( !Calamares::Permissions::apply( fileResult.path(), 0440 ) ) - { - return Calamares::JobResult::error( tr( "Cannot chmod sudoers file." ) ); - } - } - else - { - return Calamares::JobResult::error( tr( "Cannot create sudoers file for writing." ) ); - } - - return Calamares::JobResult::ok(); -} - -STATICTEST QStringList -groupsInTargetSystem() -{ - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - if ( !gs ) - { - return QStringList(); - } - QDir targetRoot( gs->value( "rootMountPoint" ).toString() ); - - QFileInfo groupsFi( targetRoot.absoluteFilePath( "etc/group" ) ); - QFile groupsFile( groupsFi.absoluteFilePath() ); - if ( !groupsFile.open( QIODevice::ReadOnly | QIODevice::Text ) ) - { - return QStringList(); - } - QString groupsData = QString::fromLocal8Bit( groupsFile.readAll() ); - QStringList groupsLines = groupsData.split( '\n' ); - QStringList::iterator it = groupsLines.begin(); - while ( it != groupsLines.end() ) - { - if ( it->startsWith( '#' ) ) - { - it = groupsLines.erase( it ); - continue; - } - int indexOfFirstToDrop = it->indexOf( ':' ); - if ( indexOfFirstToDrop < 1 ) - { - it = groupsLines.erase( it ); - continue; - } - it->truncate( indexOfFirstToDrop ); - ++it; - } - return groupsLines; -} - -/** @brief Create groups in target system as needed - * - * Given a list of groups that already exist, @p availableGroups, - * go through the @p wantedGroups and create each of them. Groups that - * fail, or which should have already been there, are added to - * @p missingGroups by name. - */ -static bool -ensureGroupsExistInTarget( const QList< GroupDescription >& wantedGroups, - const QStringList& availableGroups, - QStringList& missingGroups ) -{ - int failureCount = 0; - - for ( const auto& group : wantedGroups ) - { - if ( group.isValid() && !availableGroups.contains( group.name() ) ) - { - if ( group.mustAlreadyExist() ) - { - // Should have been there already: don't create it - missingGroups.append( group.name() ); - continue; - } - - QStringList cmd; -#ifdef __FreeBSD__ - if ( group.isSystemGroup() ) - { - cWarning() << "Ignoring must-be-a-system group for" << group.name() << "on FreeBSD"; - } - cmd = QStringList { "pw", "groupadd", "-n", group.name() }; -#else - cmd << QStringLiteral( "groupadd" ); - if ( group.isSystemGroup() ) - { - cmd << "--system"; - } - cmd << group.name(); -#endif - if ( Calamares::System::instance()->targetEnvCall( cmd ) ) - { - failureCount++; - missingGroups.append( group.name() + QChar( '*' ) ); - } - } - } - if ( !missingGroups.isEmpty() ) - { - cWarning() << "Missing groups in target system (* for groupadd failure):" << Logger::DebugList( missingGroups ); - } - return failureCount == 0; -} - -SetupGroupsJob::SetupGroupsJob( const Config* config ) - : m_config( config ) -{ -} - -QString -SetupGroupsJob::prettyName() const -{ - return tr( "Preparing groups…", "@status" ); -} - -Calamares::JobResult -SetupGroupsJob::exec() -{ - const auto& defaultGroups = m_config->defaultGroups(); - QStringList availableGroups = groupsInTargetSystem(); - QStringList missingGroups; - - if ( !ensureGroupsExistInTarget( defaultGroups, availableGroups, missingGroups ) ) - { - return Calamares::JobResult::error( tr( "Could not create groups in target system" ) ); - } - if ( !missingGroups.isEmpty() ) - { - return Calamares::JobResult::error( - tr( "Could not create groups in target system" ), - tr( "These groups are missing in the target system: %1" ).arg( missingGroups.join( ',' ) ) ); - } - - if ( m_config->doAutoLogin() && !m_config->autoLoginGroup().isEmpty() ) - { - const QString autoLoginGroup = m_config->autoLoginGroup(); - (void)ensureGroupsExistInTarget( - QList< GroupDescription >() << GroupDescription( autoLoginGroup ), availableGroups, missingGroups ); - } - - return Calamares::JobResult::ok(); -} diff --git a/src/modules/users/MiscJobs.h b/src/modules/users/MiscJobs.h deleted file mode 100644 index 57272aa952..0000000000 --- a/src/modules/users/MiscJobs.h +++ /dev/null @@ -1,50 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -/**@file Various small jobs - * - * This file collects miscellaneous jobs that need to be run to prepare - * the system for the user-creation job. - */ - -#ifndef USERS_MISCJOBS_H -#define USERS_MISCJOBS_H - -#include "Config.h" - -#include "Job.h" - -class SetupSudoJob : public Calamares::Job -{ - Q_OBJECT -public: - SetupSudoJob( const QString& group, Config::SudoStyle style ); - QString prettyName() const override; - Calamares::JobResult exec() override; - -public: - QString m_sudoGroup; - Config::SudoStyle m_sudoStyle; -}; - -class SetupGroupsJob : public Calamares::Job -{ - Q_OBJECT - -public: - SetupGroupsJob( const Config* config ); - QString prettyName() const override; - Calamares::JobResult exec() override; - -public: - const Config* m_config; -}; - -#endif diff --git a/src/modules/users/SetHostNameJob.cpp b/src/modules/users/SetHostNameJob.cpp deleted file mode 100644 index f08c1da2f9..0000000000 --- a/src/modules/users/SetHostNameJob.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Rohan Garg - * SPDX-FileCopyrightText: 2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "SetHostNameJob.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "utils/Logger.h" -#include "utils/System.h" - -#include -#include -#include -#include -#include - -using WriteMode = Calamares::System::WriteMode; - -SetHostNameJob::SetHostNameJob( const Config* c ) - : Calamares::Job() - , m_config( c ) -{ -} - -QString -SetHostNameJob::prettyName() const -{ - return tr( "Set hostname %1" ).arg( m_config->hostname() ); -} - -QString -SetHostNameJob::prettyDescription() const -{ - return tr( "Set hostname %1." ).arg( m_config->hostname() ); -} - -QString -SetHostNameJob::prettyStatusMessage() const -{ - return tr( "Setting hostname %1…", "@status" ).arg( m_config->hostname() ); -} - -STATICTEST bool -setFileHostname( const QString& hostname ) -{ - return Calamares::System::instance()->createTargetFile( - QStringLiteral( "/etc/hostname" ), ( hostname + '\n' ).toUtf8(), WriteMode::Overwrite ); -} - -STATICTEST bool -writeFileEtcHosts( const QString& hostname ) -{ - // The actual hostname gets substituted in at %1 - const QString standard_hosts = QStringLiteral( R"(# Standard host addresses -127.0.0.1 localhost -::1 localhost ip6-localhost ip6-loopback -ff02::1 ip6-allnodes -ff02::2 ip6-allrouters -)" ); - const QString this_host = QStringLiteral( R"(# This host address -127.0.1.1 %1 -)" ); - - const QString etc_hosts = standard_hosts + ( hostname.isEmpty() ? QString() : this_host.arg( hostname ) ); - return Calamares::System::instance()->createTargetFile( - QStringLiteral( "/etc/hosts" ), etc_hosts.toUtf8(), WriteMode::Overwrite ); -} - -STATICTEST bool -setSystemdHostname( const QString& hostname ) -{ - QDBusInterface hostnamed( "org.freedesktop.hostname1", - "/org/freedesktop/hostname1", - "org.freedesktop.hostname1", - QDBusConnection::systemBus() ); - if ( !hostnamed.isValid() ) - { - cWarning() << "Interface" << hostnamed.interface() << "is not valid."; - return false; - } - - bool success = true; - // Static, writes /etc/hostname - { - QDBusReply< void > r = hostnamed.call( "SetStaticHostname", hostname, false ); - if ( !r.isValid() ) - { - cWarning() << "Could not set hostname through org.freedesktop.hostname1.SetStaticHostname." << r.error(); - success = false; - } - } - // Dynamic, updates kernel - { - QDBusReply< void > r = hostnamed.call( "SetHostname", hostname, false ); - if ( !r.isValid() ) - { - cWarning() << "Could not set hostname through org.freedesktop.hostname1.SetHostname." << r.error(); - success = false; - } - } - - return success; -} - -Calamares::JobResult -SetHostNameJob::exec() -{ - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - - if ( !gs || !gs->contains( "rootMountPoint" ) ) - { - cError() << "No rootMountPoint in global storage"; - return Calamares::JobResult::error( tr( "Internal Error" ) ); - } - - QString destDir = gs->value( "rootMountPoint" ).toString(); - if ( !QDir( destDir ).exists() ) - { - cError() << "rootMountPoint points to a dir which does not exist"; - return Calamares::JobResult::error( tr( "Internal Error" ) ); - } - - switch ( m_config->hostnameAction() ) - { - case HostNameAction::None: - break; - case HostNameAction::EtcHostname: - if ( !setFileHostname( m_config->hostname() ) ) - { - cError() << "Can't write to hostname file"; - return Calamares::JobResult::error( tr( "Cannot write hostname to target system" ) ); - } - break; - case HostNameAction::SystemdHostname: - // Does its own logging - setSystemdHostname( m_config->hostname() ); - break; - case HostNameAction::Transient: - Calamares::System::instance()->removeTargetFile( QStringLiteral( "/etc/hostname" ) ); - break; - } - - if ( m_config->writeEtcHosts() ) - { - if ( !writeFileEtcHosts( m_config->hostname() ) ) - { - cError() << "Can't write to hosts file"; - return Calamares::JobResult::error( tr( "Cannot write hostname to target system" ) ); - } - } - - return Calamares::JobResult::ok(); -} diff --git a/src/modules/users/SetHostNameJob.h b/src/modules/users/SetHostNameJob.h deleted file mode 100644 index b32b1d7bbe..0000000000 --- a/src/modules/users/SetHostNameJob.h +++ /dev/null @@ -1,33 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014 Rohan Garg - * SPDX-FileCopyrightText: 2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef SETHOSTNAMEJOB_CPP_H -#define SETHOSTNAMEJOB_CPP_H - -#include "Config.h" - -#include "Job.h" - -class SetHostNameJob : public Calamares::Job -{ - Q_OBJECT -public: - SetHostNameJob( const Config* c ); - QString prettyName() const override; - QString prettyDescription() const override; - QString prettyStatusMessage() const override; - Calamares::JobResult exec() override; - -private: - const Config* m_config; -}; - -#endif // SETHOSTNAMEJOB_CPP_H diff --git a/src/modules/users/SetPasswordJob.cpp b/src/modules/users/SetPasswordJob.cpp deleted file mode 100644 index f0c8b0b715..0000000000 --- a/src/modules/users/SetPasswordJob.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2017 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "SetPasswordJob.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "utils/Entropy.h" -#include "utils/Logger.h" -#include "utils/System.h" - -#include - -#include - -#ifndef NO_CRYPT_H -#include -#endif -#include - -SetPasswordJob::SetPasswordJob( const QString& userName, const QString& newPassword ) - : Calamares::Job() - , m_userName( userName ) - , m_newPassword( newPassword ) -{ -} - -QString -SetPasswordJob::prettyName() const -{ - return tr( "Set password for user %1" ).arg( m_userName ); -} - -QString -SetPasswordJob::prettyStatusMessage() const -{ - return tr( "Setting password for user %1…", "@status" ).arg( m_userName ); -} - -#ifndef HAVE_CRYPT_GENSALT -/// Returns a modular hashing salt for method 6 (SHA512) with a 16 character random salt. -QString -SetPasswordJob::make_salt( int length ) -{ - Q_ASSERT( length >= 8 ); - Q_ASSERT( length <= 128 ); - - QString salt_string; - Calamares::EntropySource source = Calamares::getPrintableEntropy( length, salt_string ); - if ( salt_string.length() != length ) - { - cWarning() << "getPrintableEntropy returned string of length" << salt_string.length() << "expected" << length; - salt_string.truncate( length ); - } - if ( source != Calamares::EntropySource::URandom ) - { - cWarning() << "Entropy data for salt is low-quality."; - } - - salt_string.insert( 0, "$6$" ); - salt_string.append( '$' ); - return salt_string; -} -#endif - -Calamares::JobResult -SetPasswordJob::exec() -{ - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - QDir destDir( gs->value( "rootMountPoint" ).toString() ); - if ( !destDir.exists() ) - { - return Calamares::JobResult::error( tr( "Bad destination system path." ), - tr( "rootMountPoint is %1" ).arg( destDir.absolutePath() ) ); - } - - if ( m_userName == "root" && m_newPassword.isEmpty() ) //special case for disabling root account - { - int ec = Calamares::System::instance()->targetEnvCall( { "usermod", "-p", "!", m_userName } ); - if ( ec ) - { - return Calamares::JobResult::error( tr( "Cannot disable root account." ), - tr( "usermod terminated with error code %1." ).arg( ec ) ); - } - return Calamares::JobResult::ok(); - } - - QString salt; -#ifdef HAVE_CRYPT_GENSALT - salt = crypt_gensalt( NULL, 0, NULL, 0 ); -#else - salt = make_salt( 16 ); -#endif - - QString encrypted = QString::fromLatin1( crypt( m_newPassword.toUtf8(), salt.toUtf8() ) ); - - int ec = Calamares::System::instance()->targetEnvCall( { "usermod", "-p", encrypted, m_userName } ); - if ( ec ) - { - return Calamares::JobResult::error( tr( "Cannot set password for user %1." ).arg( m_userName ), - tr( "usermod terminated with error code %1." ).arg( ec ) ); - } - - return Calamares::JobResult::ok(); -} diff --git a/src/modules/users/SetPasswordJob.h b/src/modules/users/SetPasswordJob.h deleted file mode 100644 index 75647d48c2..0000000000 --- a/src/modules/users/SetPasswordJob.h +++ /dev/null @@ -1,34 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef SETPASSWORDJOB_H -#define SETPASSWORDJOB_H - -#include "Job.h" - - -class SetPasswordJob : public Calamares::Job -{ - Q_OBJECT -public: - SetPasswordJob( const QString& userName, const QString& newPassword ); - QString prettyName() const override; - QString prettyStatusMessage() const override; - Calamares::JobResult exec() override; -#ifndef HAVE_CRYPT_GENSALT - static QString make_salt( int length ); -#endif /* HAVE_CRYPT_GENSALT */ - -private: - QString m_userName; - QString m_newPassword; -}; - -#endif /* SETPASSWORDJOB_H */ diff --git a/src/modules/users/TestGroupInformation.cpp b/src/modules/users/TestGroupInformation.cpp deleted file mode 100644 index d5bd88f2c9..0000000000 --- a/src/modules/users/TestGroupInformation.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "Config.h" -#include "CreateUserJob.h" -#include "MiscJobs.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "utils/Logger.h" -#include "utils/Yaml.h" - -#include -#include - -// Implementation details -extern QStringList groupsInTargetSystem(); // CreateUserJob - -class GroupTests : public QObject -{ - Q_OBJECT -public: - GroupTests(); - ~GroupTests() override {} - -private Q_SLOTS: - void initTestCase(); - - void testReadGroup(); - void testCreateGroup(); - - void testSudoGroup(); - void testJobCreation(); -}; - -GroupTests::GroupTests() {} - -void -GroupTests::initTestCase() -{ - Logger::setupLogLevel( Logger::LOGDEBUG ); - cDebug() << "Users test started."; - if ( !Calamares::JobQueue::instance() ) - { - (void)new Calamares::JobQueue(); - } - Calamares::JobQueue::instance()->globalStorage()->insert( "rootMountPoint", "/" ); -} - -void -GroupTests::testReadGroup() -{ - // Get the groups in the host system - QStringList groups = groupsInTargetSystem(); - QVERIFY( groups.count() > 2 ); -#ifdef __FreeBSD__ - QVERIFY( groups.contains( QStringLiteral( "wheel" ) ) ); -#else - QVERIFY( groups.contains( QStringLiteral( "root" ) ) ); -#endif - QVERIFY( groups.contains( QStringLiteral( "tty" ) ) ); - // openSUSE doesn't have "sys", KaOS doesn't have "nogroup" - QVERIFY( groups.contains( QStringLiteral( "sys" ) ) || groups.contains( QStringLiteral( "nogroup" ) ) ); - - for ( const QString& s : groups ) - { - QVERIFY( !s.isEmpty() ); - QVERIFY( !s.contains( '#' ) ); - } -} - -void -GroupTests::testCreateGroup() -{ - // BUILD_AS_TEST is the source-directory path - QFileInfo fi( QString( "%1/tests/5-issue-1523.conf" ).arg( BUILD_AS_TEST ) ); - QVERIFY( fi.exists() ); - - bool ok = false; - const auto map = Calamares::YAML::load( fi, &ok ); - QVERIFY( ok ); - QVERIFY( map.count() > 0 ); // Just that it loaded, one key *defaultGroups* - - Config c; - c.setConfigurationMap( map ); - - QCOMPARE( c.defaultGroups().count(), 4 ); - QVERIFY( c.defaultGroups().contains( QStringLiteral( "adm" ) ) ); - QVERIFY( c.defaultGroups().contains( QStringLiteral( "bar" ) ) ); - - Calamares::JobQueue::instance()->globalStorage()->insert( "rootMountPoint", "/" ); - - SetupGroupsJob j( &c ); - QVERIFY( !j.exec() ); // running as regular user this should fail -} - -void -GroupTests::testSudoGroup() -{ - // Test programmatic changes - { - Config c; - QSignalSpy spy( &c, &Config::sudoersGroupChanged ); - QCOMPARE( c.sudoersGroup(), QString() ); - c.setSudoersGroup( QStringLiteral( "wheel" ) ); - QCOMPARE( c.sudoersGroup(), QStringLiteral( "wheel" ) ); - QCOMPARE( spy.count(), 1 ); // Changed to wheel - // Do it again, no change - c.setSudoersGroup( QStringLiteral( "wheel" ) ); - QCOMPARE( c.sudoersGroup(), QStringLiteral( "wheel" ) ); - QCOMPARE( spy.count(), 1 ); - c.setSudoersGroup( QStringLiteral( "roue" ) ); - QCOMPARE( c.sudoersGroup(), QStringLiteral( "roue" ) ); - QCOMPARE( spy.count(), 2 ); - } - - // Test config loading - { - Config c; - QSignalSpy spy( &c, &Config::sudoersGroupChanged ); - QCOMPARE( c.sudoersGroup(), QString() ); - - QVariantMap m; - c.setConfigurationMap( m ); - QCOMPARE( c.sudoersGroup(), QString() ); - QCOMPARE( spy.count(), 0 ); // Unchanged - - const auto key = QStringLiteral( "sudoersGroup" ); - const auto v0 = QStringLiteral( "wheel" ); - const auto v1 = QStringLiteral( "roue" ); - m.insert( key, v0 ); - c.setConfigurationMap( m ); - QCOMPARE( c.sudoersGroup(), v0 ); - QCOMPARE( spy.count(), 1 ); - } -} - -/** @brief Are all the expected jobs (and no others) created? - * - * - A sudo job is created only when the sudoers group is set; - * - Groups job - * - User job - * - Password job - * - Root password job - * - Hostname job are always created. - */ -void -GroupTests::testJobCreation() -{ - const int expectedJobs = 5; - Config c; - QVERIFY( !c.isReady() ); - - // Needs some setup - c.setFullName( QStringLiteral( "Goodluck Jonathan" ) ); - c.setLoginName( QStringLiteral( "goodj" ) ); - QVERIFY( c.isReady() ); - - QCOMPARE( c.sudoersGroup(), QString() ); - QCOMPARE( c.createJobs().count(), expectedJobs ); - - c.setSudoersGroup( QStringLiteral( "wheel" ) ); - QCOMPARE( c.sudoersGroup(), QString( "wheel" ) ); - QCOMPARE( c.createJobs().count(), expectedJobs + 1 ); -} - -QTEST_GUILESS_MAIN( GroupTests ) - -#include "utils/moc-warnings.h" - -#include "TestGroupInformation.moc" diff --git a/src/modules/users/TestPasswordJob.cpp b/src/modules/users/TestPasswordJob.cpp deleted file mode 100644 index 1409e37b69..0000000000 --- a/src/modules/users/TestPasswordJob.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2017 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "SetPasswordJob.h" - -#include - -class PasswordTests : public QObject -{ - Q_OBJECT -public: - PasswordTests(); - ~PasswordTests() override; - -private Q_SLOTS: - void initTestCase(); - void testSalt(); -}; - -PasswordTests::PasswordTests() {} - -PasswordTests::~PasswordTests() {} - -void -PasswordTests::initTestCase() -{ -} - -void -PasswordTests::testSalt() -{ - QString s = SetPasswordJob::make_salt( 8 ); - QCOMPARE( s.length(), 4 + 8 ); // 8 salt chars, plus $6$, plus trailing $ - QVERIFY( s.startsWith( "$6$" ) ); - QVERIFY( s.endsWith( '$' ) ); - qDebug() << "Obtained salt" << s; - - s = SetPasswordJob::make_salt( 11 ); - QCOMPARE( s.length(), 4 + 11 ); - QVERIFY( s.startsWith( "$6$" ) ); - QVERIFY( s.endsWith( '$' ) ); - qDebug() << "Obtained salt" << s; -} - -QTEST_GUILESS_MAIN( PasswordTests ) - -#include "utils/moc-warnings.h" - -#include "TestPasswordJob.moc" diff --git a/src/modules/users/TestSetHostNameJob.cpp b/src/modules/users/TestSetHostNameJob.cpp deleted file mode 100644 index 90e44de5fe..0000000000 --- a/src/modules/users/TestSetHostNameJob.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "SetHostNameJob.h" - -// Implementation details -extern bool setFileHostname( const QString& ); -extern bool writeFileEtcHosts( const QString& ); -extern bool setSystemdHostname( const QString& ); - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "utils/Logger.h" -#include "utils/System.h" -#include "utils/Yaml.h" - -#include -#include - -#include - -class UsersTests : public QObject -{ - Q_OBJECT -public: - UsersTests(); - ~UsersTests() override {} - -private Q_SLOTS: - void initTestCase(); - - void testEtcHostname(); - void testEtcHosts(); - void testHostnamed(); - - void cleanup(); - -private: - QTemporaryDir m_dir; - QString m_originalHostName; -}; - -UsersTests::UsersTests() - : m_dir( QStringLiteral( "/tmp/calamares-usertest" ) ) -{ -} - -void -UsersTests::initTestCase() -{ - Logger::setupLogLevel( Logger::LOGDEBUG ); - cDebug() << "Users test started."; - cDebug() << "Test dir" << m_dir.path(); - - // Ensure we have a system object, expect it to be a "bogus" one - Calamares::System* system = Calamares::System::instance(); - QVERIFY( system ); - QVERIFY( system->doChroot() ); - - // Ensure we have a system-wide GlobalStorage with /tmp as root - if ( !Calamares::JobQueue::instance() ) - { - cDebug() << "Creating new JobQueue"; - (void)new Calamares::JobQueue(); - } - Calamares::GlobalStorage* gs - = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; - QVERIFY( gs ); - gs->insert( "rootMountPoint", m_dir.path() ); - - if ( m_originalHostName.isEmpty() ) - { - QFile hostname( QStringLiteral( "/etc/hostname" ) ); - if ( hostname.exists() && hostname.open( QIODevice::ReadOnly | QIODevice::Text ) ) - { - m_originalHostName = hostname.readAll().trimmed(); - } - } -} - -void -UsersTests::testEtcHostname() -{ - cDebug() << "Test dir" << m_dir.path(); - - QVERIFY( QFile::exists( m_dir.path() ) ); - QVERIFY( !QFile::exists( m_dir.filePath( "etc" ) ) ); - - const QString testHostname = QStringLiteral( "tubophone.calamares.io" ); - // Doesn't create intermediate directories - QVERIFY( !setFileHostname( testHostname ) ); - - QVERIFY( Calamares::System::instance()->createTargetDirs( "/etc" ) ); - QVERIFY( QFile::exists( m_dir.filePath( "etc" ) ) ); - - // Does write the file - QVERIFY( setFileHostname( testHostname ) ); - QVERIFY( QFile::exists( m_dir.filePath( "etc/hostname" ) ) ); - - // 22 for the test string, above, and 1 for the newline - QCOMPARE( QFileInfo( m_dir.filePath( "etc/hostname" ) ).size(), testHostname.length() + 1 ); -} - -void -UsersTests::testEtcHosts() -{ - // Assume previous tests did their work - QVERIFY( QFile::exists( m_dir.path() ) ); - QVERIFY( QFile::exists( m_dir.filePath( "etc" ) ) ); - - const QString testHostname = QStringLiteral( "tubophone.calamares.io" ); - QVERIFY( writeFileEtcHosts( testHostname ) ); - QVERIFY( QFile::exists( m_dir.filePath( "etc/hosts" ) ) ); - // The skeleton contains %1 which has the hostname substituted in, so we lose two, - // and the rest of the blabla is 145 (the "standard" part) and 34 (the "for this host" part) - QCOMPARE( QFileInfo( m_dir.filePath( "etc/hosts" ) ).size(), 145 + 34 + testHostname.length() - 2 ); -} - -void -UsersTests::testHostnamed() -{ - // Since the service might not be running (e.g. non-systemd systems, - // FreeBSD, docker, ..) we're not going to fail a test here. - // There's also the permissions problem to think of. But if we're - // root, assume it will succeed. - if ( geteuid() != 0 ) - { - if ( !setSystemdHostname( QStringLiteral( "tubophone.calamares.io" ) ) ) - { - QEXPECT_FAIL( "", "Hostname changes are access-controlled", Continue ); - } - } - QVERIFY( setSystemdHostname( QStringLiteral( "tubophone.calamares.io" ) ) ); - if ( !m_originalHostName.isEmpty() ) - { - // If the previous test succeeded (to change the hostname to something bogus) - // then this one should, also; or, if the previous one failed, then this - // changes to whatever-the-hostname-is, and systemd dbus seems to call that - // a success, as well (since nothing changes). So no failure-expectation here. - setSystemdHostname( m_originalHostName ); - } -} - -void -UsersTests::cleanup() -{ - if ( QTest::currentTestFailed() ) - { - m_dir.setAutoRemove( false ); - } -} - -QTEST_GUILESS_MAIN( UsersTests ) - -#include "utils/moc-warnings.h" - -#include "TestSetHostNameJob.moc" diff --git a/src/modules/users/Tests.cpp b/src/modules/users/Tests.cpp deleted file mode 100644 index 1f9efc35ef..0000000000 --- a/src/modules/users/Tests.cpp +++ /dev/null @@ -1,518 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "Config.h" - -#include "JobQueue.h" -#include "utils/Logger.h" -#include "utils/Yaml.h" - -#include - -// Implementation details -extern void setConfigurationDefaultGroups( const QVariantMap& map, QList< GroupDescription >& defaultGroups ); -extern HostNameAction getHostNameAction( const QVariantMap& configurationMap ); -extern bool addPasswordCheck( const QString& key, const QVariant& value, PasswordCheckList& passwordChecks ); -extern QString -makeHostnameSuggestion( const QString& templateString, const QStringList& fullNameParts, const QString& loginName ); - -/** @brief Test Config object methods and internals - * - */ -class UserTests : public QObject -{ - Q_OBJECT -public: - UserTests(); - ~UserTests() override {} - -private Q_SLOTS: - void initTestCase(); - - // Derpy test for getting and setting regular values - void testGetSet(); - - void testDefaultGroups(); - void testDefaultGroupsYAML_data(); - void testDefaultGroupsYAML(); - - void testHostActions_data(); - void testHostActions(); - void testHostActions2(); - void testHostSuggestions_data(); - void testHostSuggestions(); - - void testPasswordChecks(); - void testUserPassword(); - - void testAutoLogin_data(); - void testAutoLogin(); - - void testUserYAML_data(); - void testUserYAML(); -}; - -UserTests::UserTests() {} - -void -UserTests::initTestCase() -{ - Logger::setupLogLevel( Logger::LOGDEBUG ); - cDebug() << "Users test started."; - - if ( !Calamares::JobQueue::instance() ) - { - (void)new Calamares::JobQueue(); - } -} - -void -UserTests::testGetSet() -{ - Config c; - - { - const QString sh( "/bin/sh" ); - QCOMPARE( c.userShell(), QString() ); - c.setUserShell( sh ); - QCOMPARE( c.userShell(), sh ); - c.setUserShell( sh + sh ); - QCOMPARE( c.userShell(), sh + sh ); - - const QString badsh( "bash" ); // Not absolute, that's bad - c.setUserShell( badsh ); // .. so unchanged - QCOMPARE( c.userShell(), sh + sh ); // what was set previously - - // Explicit set to empty is ok - c.setUserShell( QString() ); - QCOMPARE( c.userShell(), QString() ); - } - { - const QString al( "autolg" ); - QCOMPARE( c.autoLoginGroup(), QString() ); - c.setAutoLoginGroup( al ); - QCOMPARE( c.autoLoginGroup(), al ); - QVERIFY( !c.doAutoLogin() ); - c.setAutoLogin( true ); - QVERIFY( c.doAutoLogin() ); - QCOMPARE( c.autoLoginGroup(), al ); - } - { - const QString su( "sudogrp" ); - QCOMPARE( c.sudoersGroup(), QString() ); - c.setSudoersGroup( su ); - QCOMPARE( c.sudoersGroup(), su ); - } - { - const QString ful( "Jan-Jaap Karel Kees" ); - const QString lg( "jjkk" ); - QCOMPARE( c.fullName(), QString() ); - QCOMPARE( c.loginName(), QString() ); - QVERIFY( c.loginNameStatus().isEmpty() ); // empty login name is ok - c.setLoginName( lg ); - c.setFullName( ful ); - 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 - } -} - -void -UserTests::testDefaultGroups() -{ - { - QList< GroupDescription > groups; - QVariantMap hweelGroup; - QVERIFY( groups.isEmpty() ); - hweelGroup.insert( "defaultGroups", QStringList { "hweel" } ); - setConfigurationDefaultGroups( hweelGroup, groups ); - QCOMPARE( groups.count(), 1 ); - QVERIFY( groups.contains( GroupDescription( "hweel" ) ) ); - } - - { - QStringList desired { "wheel", "root", "operator" }; - QList< GroupDescription > groups; - QVariantMap threeGroup; - QVERIFY( groups.isEmpty() ); - threeGroup.insert( "defaultGroups", desired ); - setConfigurationDefaultGroups( threeGroup, groups ); - QCOMPARE( groups.count(), 3 ); - QVERIFY( !groups.contains( GroupDescription( "hweel" ) ) ); - for ( const auto& s : desired ) - { - QVERIFY( groups.contains( GroupDescription( s ) ) ); - } - } - - { - QList< GroupDescription > groups; - QVariantMap explicitEmpty; - QVERIFY( groups.isEmpty() ); - explicitEmpty.insert( "defaultGroups", QStringList() ); - setConfigurationDefaultGroups( explicitEmpty, groups ); - QCOMPARE( groups.count(), 0 ); - } - - { - QList< GroupDescription > groups; - QVariantMap missing; - QVERIFY( groups.isEmpty() ); - setConfigurationDefaultGroups( missing, groups ); - QCOMPARE( groups.count(), 6 ); // because of fallback! - QVERIFY( groups.contains( GroupDescription( "lp", false, GroupDescription::SystemGroup {} ) ) ); - } - - { - QList< GroupDescription > groups; - QVariantMap typeMismatch; - QVERIFY( groups.isEmpty() ); - typeMismatch.insert( "defaultGroups", 1 ); - setConfigurationDefaultGroups( typeMismatch, groups ); - QCOMPARE( groups.count(), 6 ); // because of fallback! - QVERIFY( groups.contains( GroupDescription( "lp", false, GroupDescription::SystemGroup {} ) ) ); - } -} - -void -UserTests::testDefaultGroupsYAML_data() -{ - QTest::addColumn< QString >( "filename" ); - QTest::addColumn< int >( "count" ); - QTest::addColumn< QString >( "group" ); - - QTest::newRow( "users.conf" ) << "users.conf" << 7 << "video"; - QTest::newRow( "dashed list" ) << "tests/4-audio.conf" << 4 << "audio"; - QTest::newRow( "blocked list" ) << "tests/3-wing.conf" << 3 << "wing"; - QTest::newRow( "issue 1523" ) << "tests/5-issue-1523.conf" << 4 << "foobar"; -} - -void -UserTests::testDefaultGroupsYAML() -{ - if ( !Calamares::JobQueue::instance() ) - { - (void)new Calamares::JobQueue(); - } - - QFETCH( QString, filename ); - QFETCH( int, count ); - QFETCH( QString, group ); - - // BUILD_AS_TEST is the source-directory path - QFileInfo fi( QString( "%1/%2" ).arg( BUILD_AS_TEST, filename ) ); - QVERIFY( fi.exists() ); - - bool ok = false; - const auto map = Calamares::YAML::load( fi, &ok ); - QVERIFY( ok ); - QVERIFY( map.count() > 0 ); - - Config c; - c.setConfigurationMap( map ); - - QCOMPARE( c.defaultGroups().count(), count ); - QVERIFY( c.defaultGroups().contains( group ) ); -} - -void -UserTests::testHostActions_data() -{ - QTest::addColumn< bool >( "set" ); - QTest::addColumn< QString >( "string" ); - QTest::addColumn< int >( "result" ); - - QTest::newRow( "unset " ) << false << QString() << int( HostNameAction::EtcHostname ); - QTest::newRow( "empty " ) << true << QString() << int( HostNameAction::EtcHostname ); - QTest::newRow( "bad " ) << true << QString( "derp" ) << int( HostNameAction::EtcHostname ); - QTest::newRow( "none " ) << true << QString( "none" ) << int( HostNameAction::None ); - QTest::newRow( "systemd" ) << true << QString( "Hostnamed" ) << int( HostNameAction::SystemdHostname ); - QTest::newRow( "etc(1) " ) << true << QString( "etcfile" ) << int( HostNameAction::EtcHostname ); - QTest::newRow( "etc(2) " ) << true << QString( "etc" ) << int( HostNameAction::EtcHostname ); - QTest::newRow( "etc-bad" ) - << true << QString( "etchost" ) - << int( HostNameAction::EtcHostname ); // This isn't a valid name, but defaults to EtcHostname - QTest::newRow( "ci-sysd" ) << true << QString( "hOsTnaMed" ) - << int( HostNameAction::SystemdHostname ); // Case-insensitive - QTest::newRow( "trbs " ) << true << QString( "transient" ) << int( HostNameAction::Transient ); - QTest::newRow( "ci-trns" ) << true << QString( "trANSient" ) << int( HostNameAction::Transient ); -} - -void -UserTests::testHostActions() -{ - QFETCH( bool, set ); - QFETCH( QString, string ); - QFETCH( int, result ); - - QVariantMap m; - if ( set ) - { - m.insert( "location", string ); - } - // action is independent of writeHostsFile - QCOMPARE( getHostNameAction( m ), HostNameAction( result ) ); - m.insert( "writeHostsFile", false ); - QCOMPARE( getHostNameAction( m ), HostNameAction( result ) ); - m.insert( "writeHostsFile", true ); - QCOMPARE( getHostNameAction( m ), HostNameAction( result ) ); -} - -void -UserTests::testHostActions2() -{ - Config c; - QVariantMap legacy; - - // Test defaults - c.setConfigurationMap( legacy ); - QCOMPARE( c.hostnameAction(), HostNameAction::EtcHostname ); - QCOMPARE( c.writeEtcHosts(), true ); - - QVariantMap hostSettings; - hostSettings.insert( "writeHostsFile", false ); - hostSettings.insert( "location", "Hostnamed" ); - legacy.insert( "hostname", hostSettings ); - c.setConfigurationMap( legacy ); - QCOMPARE( c.hostnameAction(), HostNameAction::SystemdHostname ); - QCOMPARE( c.writeEtcHosts(), false ); -} - -void -UserTests::testHostSuggestions_data() -{ - QTest::addColumn< QString >( "templateString" ); - QTest::addColumn< QString >( "result" ); - - QTest::newRow( "unset " ) << QString() << QString(); - QTest::newRow( "const " ) << QStringLiteral( "derp" ) << QStringLiteral( "derp" ); - QTest::newRow( "escaped" ) << QStringLiteral( "$$" ) << QString(); // Because invalid - QTest::newRow( "default" ) << QStringLiteral( "${first}-pc" ) - << QStringLiteral( "chuck-pc" ); // Avoid ${product} because it's DMI-based - 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 - // 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(); - QTest::newRow( "@prod2 " ) << QStringLiteral( "X${product2}X" ) << QString(); - QTest::newRow( "@host " ) << QStringLiteral( "X${host}X" ) << QString(); -} - -void -UserTests::testHostSuggestions() -{ - const QStringList fullName { "Chuck", "Yeager" }; - const QString login { "bill" }; - - QFETCH( QString, templateString ); - QFETCH( QString, result ); - - 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 ); - } - QCOMPARE( makeHostnameSuggestion( templateString, fullName, login ), result ); -} - -void -UserTests::testPasswordChecks() -{ - { - PasswordCheckList l; - QCOMPARE( l.length(), 0 ); - QVERIFY( !addPasswordCheck( "nonempty", QVariant( false ), l ) ); // legacy option, now ignored - QCOMPARE( l.length(), 0 ); - QVERIFY( !addPasswordCheck( "nonempty", QVariant( true ), l ) ); // still ignored - QCOMPARE( l.length(), 0 ); - } -} - -void -UserTests::testUserPassword() -{ - if ( !Calamares::JobQueue::instance() ) - { - (void)new Calamares::JobQueue( nullptr ); - } - - { - Config c; - - QVERIFY( c.userPassword().isEmpty() ); - QVERIFY( c.userPasswordSecondary().isEmpty() ); - // There are no validity checks, so no check for nonempty - QCOMPARE( c.userPasswordValidity(), Config::PasswordValidity::Valid ); - - c.setUserPassword( "bogus" ); - QCOMPARE( c.userPasswordValidity(), Config::PasswordValidity::Invalid ); - QCOMPARE( c.userPassword(), "bogus" ); - c.setUserPasswordSecondary( "bogus" ); - QCOMPARE( c.userPasswordValidity(), Config::PasswordValidity::Valid ); - } - - { - Config c; - - QVariantMap m; - m.insert( "allowWeakPasswords", true ); - m.insert( "allowWeakPasswordsDefault", true ); - m.insert( "defaultGroups", QStringList { "wheel" } ); - - QVariantMap pwreq; - pwreq.insert( "nonempty", true ); - pwreq.insert( "minLength", 6 ); - m.insert( "passwordRequirements", pwreq ); - - c.setConfigurationMap( m ); - - QVERIFY( c.userPassword().isEmpty() ); - QVERIFY( c.userPasswordSecondary().isEmpty() ); - // There is now a nonempty check, but weak passwords are ok - QCOMPARE( c.userPasswordValidity(), int( Config::PasswordValidity::Weak ) ); - - c.setUserPassword( "bogus" ); - QCOMPARE( c.userPasswordValidity(), int( Config::PasswordValidity::Invalid ) ); - c.setUserPasswordSecondary( "bogus" ); - QCOMPARE( c.userPasswordValidity(), int( Config::PasswordValidity::Weak ) ); - - QVERIFY( !c.requireStrongPasswords() ); - c.setRequireStrongPasswords( true ); - QVERIFY( c.requireStrongPasswords() ); - // Now changed requirements make the password invalid - QCOMPARE( c.userPassword(), "bogus" ); - QCOMPARE( c.userPasswordValidity(), int( Config::PasswordValidity::Invalid ) ); - } - - { - Config c; - QVERIFY( c.userPassword().isEmpty() ); - QCOMPARE( c.userPasswordValidity(), Config::PasswordValidity::Valid ); - - QSignalSpy spy_pwChanged( &c, &Config::userPasswordChanged ); - QSignalSpy spy_pwSecondaryChanged( &c, &Config::userPasswordSecondaryChanged ); - QSignalSpy spy_pwStatusChanged( &c, &Config::userPasswordStatusChanged ); - - c.setUserPassword( "bogus" ); - c.setUserPassword( "bogus" ); - QCOMPARE( spy_pwChanged.count(), 1 ); - QCOMPARE( spy_pwStatusChanged.count(), 1 ); - QCOMPARE( c.userPasswordValidity(), Config::PasswordValidity::Invalid ); - c.setUserPassword( "sugob" ); - c.setUserPasswordSecondary( "sugob" ); - QCOMPARE( spy_pwChanged.count(), 2 ); - QCOMPARE( spy_pwSecondaryChanged.count(), 1 ); - QCOMPARE( spy_pwStatusChanged.count(), 3 ); - QCOMPARE( c.userPasswordValidity(), Config::PasswordValidity::Valid ); - } -} - -void -UserTests::testAutoLogin_data() -{ - QTest::addColumn< QString >( "filename" ); - QTest::addColumn< bool >( "autoLoginIsSet" ); - QTest::addColumn< QString >( "autoLoginGroupName" ); - - QTest::newRow( "old, old" ) << "tests/6a-issue-1672.conf" << true << "derp"; - QTest::newRow( "old, new" ) << "tests/6b-issue-1672.conf" << true << "derp"; - QTest::newRow( "new, old" ) << "tests/6c-issue-1672.conf" << true << "derp"; - QTest::newRow( "new, new" ) << "tests/6d-issue-1672.conf" << true << "derp"; - QTest::newRow( "default" ) << "tests/6e-issue-1672.conf" << false << QString(); -} - -void -UserTests::testAutoLogin() -{ - QFETCH( QString, filename ); - QFETCH( bool, autoLoginIsSet ); - QFETCH( QString, autoLoginGroupName ); - - // BUILD_AS_TEST is the source-directory path - QFileInfo fi( QString( "%1/%2" ).arg( BUILD_AS_TEST, filename ) ); - QVERIFY( fi.exists() ); - - bool ok = false; - const auto map = Calamares::YAML::load( fi, &ok ); - QVERIFY( ok ); - QVERIFY( map.count() > 0 ); - - Config c; - c.setConfigurationMap( map ); - - QCOMPARE( c.doAutoLogin(), autoLoginIsSet ); - QCOMPARE( c.autoLoginGroup(), autoLoginGroupName ); -} - -void -UserTests::testUserYAML_data() -{ - QTest::addColumn< QString >( "filename" ); - QTest::addColumn< QString >( "shell" ); - - const QString bash = QStringLiteral( "/bin/bash" ); - - // All the old settings are ignored - QTest::newRow( "old, unset " ) << "tests/7ao-shell.conf" << bash; - QTest::newRow( "old, empty " ) << "tests/7bo-shell.conf" << bash; - QTest::newRow( "old, relative" ) << "tests/7co-shell.conf" << bash; - QTest::newRow( "old, invalid " ) << "tests/7do-shell.conf" << bash; - QTest::newRow( "old, absolute" ) << "tests/7eo-shell.conf" << bash; - - 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 - QFileInfo fi( QString( "%1/%2" ).arg( BUILD_AS_TEST, filename ) ); - QVERIFY( fi.exists() ); - - bool ok = false; - const auto map = Calamares::YAML::load( 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 ) - -#include "utils/moc-warnings.h" - -#include "Tests.moc" diff --git a/src/modules/users/UsersPage.cpp b/src/modules/users/UsersPage.cpp deleted file mode 100644 index bac30f3500..0000000000 --- a/src/modules/users/UsersPage.cpp +++ /dev/null @@ -1,285 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2017 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017-2018 Adriaan de Groot - * SPDX-FileCopyrightText: 2019 Collabora Ltd - * SPDX-FileCopyrightText: 2020 Gabriel Craciunescu - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Portions from the Manjaro Installation Framework - * by Roland Singer - * Copyright (C) 2007 Free Software Foundation, Inc. - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "UsersPage.h" - -#include "Config.h" -#include "ui_page_usersetup.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "Settings.h" -#include "utils/Gui.h" -#include "utils/Logger.h" -#include "utils/Retranslator.h" -#include "utils/String.h" - -#include -#include -#include -#include - -/** @brief Add an error message and pixmap to a label. */ -static inline void -labelError( QLabel* pix, QLabel* label, Calamares::ImageType icon, const QString& message ) -{ - label->setText( message ); - pix->setPixmap( Calamares::defaultPixmap( icon, Calamares::Original, label->size() ) ); -} - -/** @brief Clear error, set happy pixmap on a label to indicate "ok". */ -static inline void -labelOk( QLabel* pix, QLabel* label ) -{ - label->clear(); - pix->setPixmap( Calamares::defaultPixmap( Calamares::StatusOk, Calamares::Original, label->size() ) ); -} - -/** @brief Sets error or ok on a label depending on @p status and @p value - * - * - An **empty** @p value gets no message and no icon. - * - A non-empty @p value, with an **empty** @p status gets an "ok". - * - A non-empty @p value with a non-empty @p status gets an error indicator. - */ -static inline void -labelStatus( QLabel* pix, QLabel* label, const QString& value, const QString& status ) -{ - if ( status.isEmpty() ) - { - if ( value.isEmpty() ) - { - // This is different from labelOK() because no checkmark is shown - label->clear(); - pix->clear(); - } - else - { - labelOk( pix, label ); - } - } - else - { - labelError( pix, label, Calamares::ImageType::StatusError, status ); - } -} - -UsersPage::UsersPage( Config* config, QWidget* parent ) - : QWidget( parent ) - , ui( new Ui::Page_UserSetup ) - , m_config( config ) -{ - ui->setupUi( this ); - - // Connect signals and slots - ui->textBoxUserPassword->setText( config->userPassword() ); - connect( ui->textBoxUserPassword, &QLineEdit::textChanged, config, &Config::setUserPassword ); - connect( config, &Config::userPasswordChanged, ui->textBoxUserPassword, &QLineEdit::setText ); - ui->textBoxUserVerifiedPassword->setText( config->userPasswordSecondary() ); - connect( ui->textBoxUserVerifiedPassword, &QLineEdit::textChanged, config, &Config::setUserPasswordSecondary ); - connect( config, &Config::userPasswordSecondaryChanged, ui->textBoxUserVerifiedPassword, &QLineEdit::setText ); - connect( config, &Config::userPasswordStatusChanged, this, &UsersPage::reportUserPasswordStatus ); - - ui->textBoxRootPassword->setText( config->rootPassword() ); - connect( ui->textBoxRootPassword, &QLineEdit::textChanged, config, &Config::setRootPassword ); - connect( config, &Config::rootPasswordChanged, ui->textBoxRootPassword, &QLineEdit::setText ); - ui->textBoxVerifiedRootPassword->setText( config->rootPasswordSecondary() ); - connect( ui->textBoxVerifiedRootPassword, &QLineEdit::textChanged, config, &Config::setRootPasswordSecondary ); - connect( config, &Config::rootPasswordSecondaryChanged, ui->textBoxVerifiedRootPassword, &QLineEdit::setText ); - connect( config, &Config::rootPasswordStatusChanged, this, &UsersPage::reportRootPasswordStatus ); - - ui->textBoxFullName->setText( config->fullName() ); - connect( ui->textBoxFullName, &QLineEdit::textEdited, config, &Config::setFullName ); - connect( config, &Config::fullNameChanged, this, &UsersPage::onFullNameTextEdited ); - - // If the hostname is going to be written out, then show the field - if ( ( m_config->hostnameAction() == HostNameAction::EtcHostname ) - || ( m_config->hostnameAction() == HostNameAction::SystemdHostname ) ) - { - ui->textBoxHostname->setText( config->hostname() ); - connect( ui->textBoxHostname, &QLineEdit::textEdited, config, &Config::setHostName ); - connect( config, - &Config::hostnameChanged, - [ this ]( const QString& name ) - { - if ( !ui->textBoxHostname->hasFocus() ) - { - ui->textBoxHostname->setText( name ); - } - } ); - connect( config, &Config::hostnameStatusChanged, this, &UsersPage::reportHostNameStatus ); - } - else - { - // Need to hide the hostname parts individually because there's no widget-group - ui->hostnameLabel->hide(); - ui->labelHostname->hide(); - ui->textBoxHostname->hide(); - ui->labelHostnameError->hide(); - } - - ui->textBoxLoginName->setText( config->loginName() ); - connect( ui->textBoxLoginName, &QLineEdit::textEdited, config, &Config::setLoginName ); - connect( config, &Config::loginNameChanged, ui->textBoxLoginName, &QLineEdit::setText ); - connect( config, &Config::loginNameStatusChanged, this, &UsersPage::reportLoginNameStatus ); - - ui->checkBoxDoAutoLogin->setChecked( m_config->doAutoLogin() ); - connect( ui->checkBoxDoAutoLogin, - &QCheckBox::stateChanged, - this, - [ this ]( int checked ) { m_config->setAutoLogin( checked != Qt::Unchecked ); } ); - connect( config, &Config::autoLoginChanged, ui->checkBoxDoAutoLogin, &QCheckBox::setChecked ); - - ui->checkBoxReusePassword->setVisible( m_config->writeRootPassword() ); - ui->checkBoxReusePassword->setChecked( m_config->reuseUserPasswordForRoot() ); - if ( m_config->writeRootPassword() ) - { - connect( config, &Config::reuseUserPasswordForRootChanged, ui->checkBoxReusePassword, &QCheckBox::setChecked ); - connect( ui->checkBoxReusePassword, &QCheckBox::stateChanged, this, &UsersPage::onReuseUserPasswordChanged ); - } - - ui->checkBoxRequireStrongPassword->setVisible( m_config->permitWeakPasswords() ); - ui->checkBoxRequireStrongPassword->setChecked( m_config->requireStrongPasswords() ); - if ( m_config->permitWeakPasswords() ) - { - connect( ui->checkBoxRequireStrongPassword, - &QCheckBox::stateChanged, - this, - [ this ]( int checked ) { m_config->setRequireStrongPasswords( checked != Qt::Unchecked ); } ); - connect( - config, &Config::requireStrongPasswordsChanged, ui->checkBoxRequireStrongPassword, &QCheckBox::setChecked ); - } - - CALAMARES_RETRANSLATE_SLOT( &UsersPage::retranslate ); - - onReuseUserPasswordChanged( m_config->reuseUserPasswordForRoot() ); - onFullNameTextEdited( m_config->fullName() ); - reportLoginNameStatus( m_config->loginNameStatus() ); - reportHostNameStatus( m_config->hostnameStatus() ); - - ui->textBoxLoginName->setEnabled( m_config->isEditable( "loginName" ) ); - ui->textBoxFullName->setEnabled( m_config->isEditable( "fullName" ) ); - - retranslate(); -} - -UsersPage::~UsersPage() -{ - delete ui; -} - -void -UsersPage::retranslate() -{ - ui->retranslateUi( this ); - if ( Calamares::Settings::instance()->isSetupMode() ) - { - ui->textBoxLoginName->setToolTip( tr( "If more than one person will " - "use this computer, you can create multiple " - "accounts after setup." ) ); - } - else - { - ui->textBoxLoginName->setToolTip( tr( "If more than one person will " - "use this computer, you can create multiple " - "accounts after installation." ) ); - } - - const auto up = m_config->userPasswordStatus(); - reportUserPasswordStatus( up.first, up.second ); - const auto rp = m_config->rootPasswordStatus(); - reportRootPasswordStatus( rp.first, rp.second ); -} - -void -UsersPage::onActivate() -{ - ui->textBoxFullName->setFocus(); - const auto up = m_config->userPasswordStatus(); - reportUserPasswordStatus( up.first, up.second ); - const auto rp = m_config->rootPasswordStatus(); - reportRootPasswordStatus( rp.first, rp.second ); -} - -void -UsersPage::onFullNameTextEdited( const QString& fullName ) -{ - labelStatus( ui->labelFullName, ui->labelFullNameError, fullName, QString() ); -} - -void -UsersPage::reportLoginNameStatus( const QString& status ) -{ - labelStatus( ui->labelUsername, ui->labelUsernameError, m_config->loginName(), status ); -} - -void -UsersPage::reportHostNameStatus( const QString& status ) -{ - labelStatus( ui->labelHostname, ui->labelHostnameError, m_config->hostname(), status ); -} - -static inline void -passwordStatus( QLabel* iconLabel, QLabel* messageLabel, int validity, const QString& message ) -{ - switch ( validity ) - { - case Config::PasswordValidity::Valid: - labelOk( iconLabel, messageLabel ); - break; - case Config::PasswordValidity::Weak: - labelError( iconLabel, messageLabel, Calamares::StatusWarning, message ); - break; - case Config::PasswordValidity::Invalid: - default: - labelError( iconLabel, messageLabel, Calamares::StatusError, message ); - break; - } -} - -void -UsersPage::reportRootPasswordStatus( int validity, const QString& message ) -{ - passwordStatus( ui->labelRootPassword, ui->labelRootPasswordError, validity, message ); -} - -void -UsersPage::reportUserPasswordStatus( int validity, const QString& message ) -{ - passwordStatus( ui->labelUserPassword, ui->labelUserPasswordError, validity, message ); -} - -void -UsersPage::onReuseUserPasswordChanged( const int checked ) -{ - // Pass the change on to config - m_config->setReuseUserPasswordForRoot( checked != Qt::Unchecked ); - /* When "reuse" is checked, hide the fields for explicitly - * entering the root password. However, if we're going to - * disable the root password anyway, hide them all regardless of - * the checkbox -- so when writeRoot is false, visible needs - * to be false, to hide them all. - * - * In principle this is only connected when writeRootPassword is @c true, - * but it is **always** called at least once in the constructor - * to set up initial visibility. - */ - const bool visible = m_config->writeRootPassword() ? !checked : false; - ui->labelChooseRootPassword->setVisible( visible ); - ui->labelRootPassword->setVisible( visible ); - ui->labelRootPasswordError->setVisible( visible ); - ui->textBoxRootPassword->setVisible( visible ); - ui->textBoxVerifiedRootPassword->setVisible( visible ); -} diff --git a/src/modules/users/UsersPage.h b/src/modules/users/UsersPage.h deleted file mode 100644 index 2d48f1fa39..0000000000 --- a/src/modules/users/UsersPage.h +++ /dev/null @@ -1,54 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2007 Free Software Foundation, Inc. - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017-2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Portions from the Manjaro Installation Framework - * by Roland Singer - * Copyright (C) 2007 Free Software Foundation, Inc. - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef USERSPAGE_H -#define USERSPAGE_H - -#include - -class Config; - -class QLabel; - -namespace Ui -{ -class Page_UserSetup; -} // namespace Ui - -class UsersPage : public QWidget -{ - Q_OBJECT -public: - explicit UsersPage( Config* config, QWidget* parent = nullptr ); - ~UsersPage() override; - - void onActivate(); - -protected slots: - void onFullNameTextEdited( const QString& ); - void reportLoginNameStatus( const QString& ); - void reportHostNameStatus( const QString& ); - void onReuseUserPasswordChanged( const int ); - void reportUserPasswordStatus( int, const QString& ); - void reportRootPasswordStatus( int, const QString& ); - -private: - void retranslate(); - - Ui::Page_UserSetup* ui; - Config* m_config; -}; - -#endif // USERSPAGE_H diff --git a/src/modules/users/UsersViewStep.cpp b/src/modules/users/UsersViewStep.cpp deleted file mode 100644 index 6836734594..0000000000 --- a/src/modules/users/UsersViewStep.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017-2018 Adriaan de Groot - * SPDX-FileCopyrightText: 2017 Gabriel Craciunescu - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "UsersViewStep.h" - -#include "Config.h" -#include "UsersPage.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "utils/Logger.h" -#include "utils/NamedEnum.h" -#include "utils/Variant.h" - -CALAMARES_PLUGIN_FACTORY_DEFINITION( UsersViewStepFactory, registerPlugin< UsersViewStep >(); ) - -UsersViewStep::UsersViewStep( QObject* parent ) - : Calamares::ViewStep( parent ) - , m_widget( nullptr ) - , m_config( new Config( this ) ) -{ - connect( m_config, &Config::readyChanged, this, &UsersViewStep::nextStatusChanged ); - - emit nextStatusChanged( m_config->isReady() ); -} - - -UsersViewStep::~UsersViewStep() -{ - if ( m_widget && m_widget->parent() == nullptr ) - { - m_widget->deleteLater(); - } -} - - -QString -UsersViewStep::prettyName() const -{ - return tr( "Users" ); -} - - -QWidget* -UsersViewStep::widget() -{ - if ( !m_widget ) - { - m_widget = new UsersPage( m_config ); - } - return m_widget; -} - - -bool -UsersViewStep::isNextEnabled() const -{ - return m_config->isReady(); -} - - -bool -UsersViewStep::isBackEnabled() const -{ - return true; -} - - -bool -UsersViewStep::isAtBeginning() const -{ - return true; -} - - -bool -UsersViewStep::isAtEnd() const -{ - return true; -} - - -Calamares::JobList -UsersViewStep::jobs() const -{ - return m_config->createJobs(); -} - - -void -UsersViewStep::onActivate() -{ - if ( m_widget ) - { - m_widget->onActivate(); - } -} - - -void -UsersViewStep::onLeave() -{ - m_config->finalizeGlobalStorage(); -} - - -void -UsersViewStep::setConfigurationMap( const QVariantMap& configurationMap ) -{ - m_config->setConfigurationMap( configurationMap ); -} diff --git a/src/modules/users/UsersViewStep.h b/src/modules/users/UsersViewStep.h deleted file mode 100644 index 8d5abe48ff..0000000000 --- a/src/modules/users/UsersViewStep.h +++ /dev/null @@ -1,56 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef USERSPAGEPLUGIN_H -#define USERSPAGEPLUGIN_H - -#include "DllMacro.h" -#include "utils/PluginFactory.h" -#include "viewpages/ViewStep.h" - -#include -#include - -class Config; -class UsersPage; - -class PLUGINDLLEXPORT UsersViewStep : public Calamares::ViewStep -{ - Q_OBJECT - -public: - explicit UsersViewStep( QObject* parent = nullptr ); - ~UsersViewStep() override; - - QString prettyName() const override; - - QWidget* widget() 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; - -private: - UsersPage* m_widget; - Config* m_config; -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( UsersViewStepFactory ) - -#endif // USERSPAGEPLUGIN_H diff --git a/src/modules/users/images/invalid.png b/src/modules/users/images/invalid.png deleted file mode 100644 index 2cb032501794f419f9f2a052d9d4218c91b289fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7822 zcmV;99&zD`P)WFU8GbZ8()Nlj2>E@cM*03Gs4L_t(|+U=cra9qcI z=fB>o1&LNJaQU;v1s zx~gk{sW<()`}2Ok{`Iea-4FOQeVRT^pQdXfkxxoP9&Kza_B2g5l``SFsX-oif7jFN zdvyugJx`<=6AI{~OqAx$Ga(Aa2J>)Le;Sf^|HtzpJCmKjEE$TA}pmW>k2M8vdU zglrH(p=lZ@075CGln_!v3J$?JT-U>p>!9ED(C;|P3H)fE=XY``f8_?juLUKCzjeCf z%%_lYNWTlPRf`tgU}@}&VNJiQ+_IL|Mk1kk#l~g z7A=}@F!}|XX@5{@+iMq=mWCRut58x|38SPGBpilf43cxGAb@gRNY{b#Jb()TfRZv@ zm`ZCfLI{w}8UxWZ5M2k+bPz&7CKY&th734lG6^{}2$@Vl`F>g|hHIZ^ z^_5EhhSD@N%LFkkP{u%%f^t$w4h-UQEQ;g3QFSSqJm~V^iAWH<{=nID-Zcg3zb#u< zLk0hOv0?tvvhwnpmb&>UZ)^gqu7U)>`}!gKVrei!0EDC~N(xwArJ%AMz!->Sf?5`+ zri1VR{!kp3dV6uCyBl5c_^(|a{P2-89j_2R`^LtsLVA=yGnXv6C!*gGeF9QYT`LktW8Qe1&Emq{srF;LqA zvu#i*;SCJp^rbEwx_r66-*q1&uKV8~Ie%gB69Z{SOUr%bhW@>EH8o|;OO_zCbSZ=o z@Xwrq=<9=03WTzco$0HT1fdKhWP@22Xb@m98pV-|7jdGm|6oFj`@ear{n%9v=?4oJ zR&rhYeq*HQKis^qiB_+?4y3XI{`m{=FJ1tI04V+V&nA@uG#xAw24f5&kwiz=Mf~5c zOFe^u|Ijy1weOqB+t1kJ`@QDHs|?e8;fAWpyKh>)f|Rdc2gw+mBS*obz3Gdt20&SZ zMG8pQg;D^Ggi#TWV4h`#haBe%8;grdeyhIz*9R|m2UiWG9ZQ;jr&u?B`q>3_%U7*g zgV1#=;dS@GZ9ADZ3a%D7V+mCdK>7h-TL>3L&=?L;!TC-7gM(}DDlXao*1$mOV-IP^ zlIDM3VVKW;uCbx4dF?vrjg3gPwIMiv?vvxql@iMHpeTbL31gmRK~q?A$@6Z!y`p0O z+p$>UV+-kfOPc?%G8EeRubLKG_3PGyRFos}{s$0!ed!tgCn+ff<@;&%R}?{wWy4Ua z=~6Oz^UW0%ZyYQjsDeTI-qIyss<7>y|GH_RRkwaUNFj2Y4;?N;T&;3LL8aYmZ za}e7`m1TnPpsCCAR^M4u^YgcQdxJTLw43W~MF(?;%f^$GAuuvFPhJmE#-*7QLlswSa_rK>1(jAqRk6l+@{yVEyu7Fv$0P&+o zARHH<1PZw3@-Qd>dMJ!?#?b3Hw|u6g^vFB0Slg^a`ff|hAJv8IZ*N?@n3gPULGtuz z`27RviQlzIXhfC)2Xq~lWuX|*F2>^qU!NN(|$r&(_t2Yp+`c zr>7gv#jf;1TV|#7TF=t=K}-`7T?gSod9Ul#-_qCj%E2kbRpbrn(Uuk?q-oErttel! zc*P1RO+&o1Gd*|`a;*!|m8=w`6kv7;#gw5hm0Io;7oRu~>pM2%kTz9T-cuI}edC6O zO$gUFV5t2Rgy+ru^1{c`;uBDmz_2WYl_Fh<4kc#{(vIfE6_&0)b7M_) zb?vg{aC&>;#-i7xC6}vLLUI9Onh0weeBZC=6EZjujs7y9Vzj(2X4;=F3WrzL&YKUV z6cU#%rRyTa^xKnlIL~#z7P=l>AV?%(M8a5DQi8L|NF9 z!+7fY>Z+oOrY0o1E+R-Krmf}zrI2tv#GMpUu8Tk_5K6&jS$+CaBH?;Sq*6%vKDbn% zjG_=aLUInG>o7G9()U9>L7)yqqrWIPq&sSBA8d|9?rv^s0x@(9UAzcP(@=1vM1L{~ zRyQ9dH*SR8(gHsSFx1@*!Wgt!GDMO>U?7=<-qeJW&)fv7X(3$C#ZWW~rfFc)tVcR7 zP(iaTm{OuUkz8_XQPJPO-QOQ8n7VtkrKQ|t?8^&EOJJ6jV(8K(NGa1M_Y{*SB?eO| zRQ%ShSoHO;!>p-EOI9p~4+VM9V~-*B55Gc5CHlKJiQ777;qevZrq5Lzxpc}oAu!}Pn74Tg znp<0;m6Tk0dLt2(ZQO{&=?)B?IRi`Ar#((dsi4~y80WZ@N;Td(uXgV{-94#kLwfYq zTQw`?Jhq~=q^Y*P9?AZGc**3HRb5v9y9!wP$TtvbZ2HY7T-Q;yVFSFL9>k6x1ECCB zfn7~0E)Y+pP`ha}np;~zL!sZO2Q^KY)z!GXe?K%rrmglQ=b(lGgHQ}PPVs>2zJDMV zJ34K3r+0T>S7hiLD~d}1Lf{MzW~|GpD_~ADQt>zf&xZscm6~!^NXKsT_{6R(77C$x+cwl}-hx5bL6VDU-B&7wBo`QT z9n@^zg63`8z{ZfEk66(0czQFyG}|ndf}{k2=R#3}V%tW9vGtEOFJ3w=NRJX|8fBX+ zZ5x_pBQ-dbuB=qk$_#+=J#@YD%12|n$C0Qdt*w~9c?%M*gA^A~GHos8dcW-Tsf+~8 z-@FA&CXt}bAcC$}UV-vGumZGO%Jk%xa{<#ZQDs@BHl_b&T4U1Zo0?k6Z0pY#mz7y| zID(;QblR5IaQro;h#fx$#RHVBTQ}i+i|RVcZ@dv+Z!cmej)PE^*E}j~?k7AK^R{e7 zOAZnQDbcy}DV%%pMcBFleY&b{*a@MapkNp#e9y&Y&-dSoMqipTq&sSAw$3-Ldm1V$ zp$L#18X9i&baS@Ry@w6~LZEEz#Gr_-qkO{#_|a$v6v=5G1puxTNctY;Z`q2at*to& z`f&Gd*qR2Lvck^Iq=I3ZkU@ZM#|dqWMD`w>ARb~uNOx6M-rpDwt*xo5LNcC!@3{a9 zXJu)bxbL3#-UB#Cd9D)G(~Icw6CiYQi_4V)3D3v;EnCsDeS1!TI-YtGozFfCThm|_ z8c=3z(=7{tLexox9VOp*C)Rf^Z%8|@U!w~tzta?nRF{^NAU-q*k=ce)$dm;&QldyM zprTR4+D?M9@m)xsl1K&t>b7jfvK&;L%1BV>v(LiH0Gf#;r2y45Xp|!9daR%G_ur02 z|0!=1yvOw#Dk!b73!@#p7{wZU4xnF%$aeHD{$Y3Zif(J6bx8D zrFjySqRG^?3SHB{0}d|4m6g{SNCqL0x`xxwJ_|)Dn!obZi9y*mmT%t<5P}P@y@rsX z!^i>xkn#g8xchD_-?l9`Ks%qp>D{|w=~}ujYG(I}1zf-eU@`_u$jX-~*zZY*ywu%Y zl~uP@o7NX8COXhkWQmW{yo(d)XRx2$~Mc;U&~1drE3oe)q; z;rZUQJPi4);}`%GV>rEgHxz&+U;UFwC2Ga??NEf^;%lz~0P41G#flsy=yXPcOvYej z2KCuUA~V6Ilz{=I5~u-iIX`trS))z}2qEzO08*)0TaeQ;W7O$qegfnIDip%XZQIh3 zqySdtXe6{h^(0O|^AngFgRT@LW-lqFAO#1b6b7SV75G(ok4Xfm%34hUpIu1ViYbku zefMri&e8Ix_fHCH)i=L6>=>O)#kKwD33Tk;3sYmzW*JZxl8_RN5*U;cP*#$^gO!j9 z#wcW_FbROD+1q$cGL@5*;`E-qP*P#p{r7{g@y+5%;Q&xV;N%lepkv=Y7>q(wD&qy1 zWk@pJuO#DLXFx?>kY1)>7Xgz1=_6p~q7j+FRZ|Lz5}e+*4+_AF2OgMujJcFJ@#7z* z0Z{@i^YG0@%KAVVCE4S4B6&gjRehtj2%su6S5TSd-?=(1i9tbU6dn80TT_=$B2nXw zK_?!693A`iL8k;v%pIWNF-c0W%!FAfW#t7)cT$wtHpv#0b+ylBqFjJ6iuS#Gp#UuZ z+Sfo0BR2u^eVlmeNu1uh7dj=NT+At;VMtk3s}!hGG_R$KL~k!wgvgIuR45Y?Ok-%@ zvj<)89LTvty52c}_Gh01(-@eLADi}&k@HSMyu2XoRNzpG3n7OG)sfWaDszp23yFri z??&~_H|Gqg`sSO_aQEHdLV{~-&fAgAgb+xTj`>hZrSi4zlq6&@$gD^L>4N4ma8WV_ zE*0uGZ^r6v+n`P6Nf_yJDk;V4ZQG!f!udDefMN_(h`CjF8A-|-W&rx~_uVNK6`7ea z2uXV!<|y7<=^8kIhRs{B`r(K30yNyvPzY!s^!6DFGU8Y&eY7t*uZ>;oO_QfTqtOsEo_a zmjb?&9#N`4e@KL!;YxuE0Y)j5k^p8mFkcxu1R-eHv>9ur323xLfe@Vg#T#I{2I9~D zxr3Ba5CDM?5Wt|+^q#yS38mUyDd7taL(^w}GMg_TDRK14|B?3HO|l-Pg+f@<+6o1v zK^gk2f=aJS6Hr3n1sojc>xo4#DguFa{~5 zaD3NJv}Y!}gfXo6%2y{`=FmbRT;JL{EKzh8K`AA{wDcU$6&woaoalJ$aUro(@h`&aAnmq*kh3raG;}CR(QwzMoB%;e9NV=M?R)lsWa@Y7x#yq&TzB7BCUhZbp%AWr z_+cP3MiD~?W&xA}U>PPn&f%x0IPXpDaTzBa7#i~KsH(axL`h4;G!aOFK=2uz-VxJ) zWDJd22?~dElAu$2_JDAnKJSNf5K0j{dK8j#ROPU6SiOEdoM;pSogE;QK=GMvr&J16 zCB;a2J}xIyaDX4Y-P_xiHzWYKy}G*IBII^Ev;D&jf*CWziD?c?&<(AvlLN{~(5XFp zfDE9Kp6)B40#vPCJ25E3K=p-G6k?l=&O z^-T>@c{x$Qm%>bAmafAIf|&!PX=uD_6K=>wf~3Upr+1-k?><0$6wpXeU<`dnkL3nR z*HM#|s1G|qD4h{dN-2a)10|slx&{U?#QA$o?QM^}Jc0ju;t1CI1w(|3dqRwrhch~~ z(2iDWSx}mWhCA=V+8kBf(Oo;!fOr6ziM<%}+8_WJMeOJ?2p*t12Z^fLumP!_UJQQN znU*MC*m;x$P*qe6p(MJKNhE~ab6;=tohgk;0C3=Pw|7TX)hdHvT}ameLf{p!($uyA z#?WxrCaitvp-BNjskDmQ_dHY<&}2_8=OB!t@7Qt3z(;is0hl%G*CQ2;Vz4u#`U<2$ z6aY#H=9iVBHy%fi>je_{_Wo$}?35t^!0nZlQYqYPQAR9X8&-MK_5fQJpc`no^G>YG zQN?8?Nbvx|aq`+1lpdpwK?Hto619Fkl0Cf`{O}AwN&0kuO#f_$BFjRlZR31@KL&!} zNZ2yJ^XeqWf=&wQHrwhUy8inHL3zkD5eNycre}&1LO|^h=HGG))<5zH^c*DU$gZ6@ z_52Hvfe+#2|Hd7em8jzi3iqCeu(A z4x?*u5J@2grSwO+zV{+`x3*GGr?_wvfe&3{Y0vmno+?711PAwhw7vW?gzt}OW*>ff z*RYBUQmKN^`-4>Kit2lM*O(Ey!uQekv!6luK9t~7KHy3Km{(kkRN$k}aS$l=4_Y$u zzjE#RoI`Hjibl`fR#CB1Bjh@rG8noBXNu;yk`f>k@e3E=4h*1r^=hz8Pzm?Ew2I4) zL8*ctvwdYC4+4M^^c_C|?zyO3wHj1QyEB7C0*8M5W1M;OO>oyuKTK2bwkV}w>joBA zR-!!`L!ajfq12x}*wJw!XAea__alsbKPBWQ-S&2 z40Lp$WYHo}#xQvH45EjRfX^_XY|2V$+evO7!> zg6679#GDlRT?f8WZ$~V1e_q{{?@fQOY}pTs82htg!+>q*=y#lH1@kk*1l6^VG)e^= z!gFVJ{fe0uh^~DkN>>IP!k_xPt)x<@DJnv9c?JIY;sx}3e!>UtXgzV_-MoB#`QBLg z{`Zrn`P+;K3k^+!t?5Vv{*;4MxaR^s`HgweY{ye@*8#l3)k6W$8AEe<1wQQWLo(n9 zlzOW5(QT|&w~cZ5_!z6ZiY+42J>0RwdP7A3}9tvS;MFo!b zbf?vvls|mv#ECbiJYG)qhx=nOXH!+xQK9g=Qc25V>D|;G=hrMHAr-=gj`j2Bqocnc z=LZMjNV#7G!GC$Xzu%vANC5C=G~l+Bc_RQaJ#@u9X;ZPP8kAg4*(Tv73B2GkN@T_6P_hMC@LdksjGR0?(mP~7+MUUxS< zAqRvI_dIm!)VqbaM?oMRjK##iGmW^1;!qk;N=o^k9%^fQy zfg0Z8adiXAcp;XQmtj>^6;AcV(B9VvU#Whs)P1c5285Z^LXRz5_An*nZ*)pcTVn|6 z29kk~)EsU%DTI2nHHPb}t6}RpKIrMifa^jibvO|GE3K#6|7k}2iZj)q{n6;Vw^vmi zRZ4wUDwOz2BBC3xG!4FzSC#scnO%7cii>bVO%0NMfcLt)k??(R;O~81`-5%APn?{o z`_K4z{@v!qO{Q-A*r0S10T4C}n2f>Y0TO;N=Q{`|gp*NkrKW-9m6fmCA}-|<-)d{~XR;oofWI5BEcv%9R)nci4-rBh)(I(Ll%Uu!K?y-3@ZkjfV`Twm z17<>oj;7)g%nOIml}Ms$5;A9M4M4=uv7o3J)gc>0o{!GK0VMnY zT&X@^@W3cwRQ>y-S6DkL)~F$#c5DM~F1b&&|dhK>Q(!-Yf~2|s{P%5$ZB zvojvwv9qh|2-1g%(Fwqe1R=-CDp%8^Ynr&sSA# zEwijI8HB9X2!X~ZLYfYfF-WE02@XdH1VX0wMvag#G6f(Qar_P;1g6GNr0J-zEtD8$ z`ruwCg{b4e;R0OBl&jP`XA_C%p1OGPU8G}5^fB5qp7hAfZzKSo`J0adRZvK51ROo{ zsf~a(5+rg}f%6$F{o=gZ+ZKc)_ZpP0(g-mrAut$)odK3!M3e9Yho9L}&xIU5Gj6h^ zQ3{<=Xq3Wc8bZ2;BHe(&(q}ph_#XOQ7pZ`QONl_rXd(!Hc`Ols>E)i@!z193NmLs~ z0mwqh=3oRYF%yvJ2q^l9tc?ITS_RTE#<0=%RR97?Na(jqOO~xDE&F__VSG-fv_a48 z($g7*PAN>L!K4(F(P62`79^w^o@_Ek)9;p`>GvN|%F>^NfJ*^K2qgUg4iDh+wA(6> zGU-Th{8B2l|IonTKmMOYB73^9KFL^v5l}{|Gcf{EFe392(xhfm-D#sBjaGr9)gT?m z*dU|ozyYWl#>#FjD_hwV4&P8}=xYq7)f>8ozmt$oNfUN5# zJqeWvgg_uOCy@Z~q?BB#OO6z$ds5E7w8i5e{Bmfh6M#G7p&M`TAF0kptF_UpjgJGU zppZs`Vxv^wXh@^Ss)>M&2Tx@hLjdUOY-|3KaAeWEaCm7EWA&EC>L{Tl3@BlQm>Q*H z+Jii;4ut>`QmG+dikQpAg@M5DJfBRq|MO7%%w-|^apk}lZ4ww0ff+gW@G(@K7?E=Z zG*uIvjOzUHGM(UaG_c7eE!(i{b^0P*FKx7}%3{L^*^GuMp)|}`F(pLzg-G~-<8vN3 zf;-)=J9yIdVsWM7BRUnh5-pXBq^L1~jP*HQ9xXiuHNnR-$47Va=*-5DqS1eoG0b=} zfwf3R86Kk>OvW&4N0&L?oJEaM=4c~eqy(vPK#gT;%Q5abD{i5QCbo2v&+*`l{vMM| zn#lxhQ8~%AR)m|K -SPDX-License-Identifier: GPL-3.0-or-later diff --git a/src/modules/users/images/valid.png b/src/modules/users/images/valid.png deleted file mode 100644 index 3ccfc5596894dc3b535de01ce6422064d0b144e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7284 zcmV-)9E;WFU8GbZ8()Nlj2>E@cM*02|mzL_t(|+U=crv|Ux1 z;D39c>CSJ;JSRYAP{1l6?O0{k5-b%>1P7exMYUamI92QFYD>@(k);F>Y{jms#$XvJ z3|Ou%nN-?B!5|JmfDB}w^QQambcQ|jANM6ZUcKSomzUv%?5w@+%U$>EbI$(lZ`j}7 z=R0t^oGz!!>2kW9E~m@s(qIv%%8gued%94RiC0JmLAj`^WgA8JeVW>7NXN1K_5aG} zOu$*lWTx-S`BJ!xq>yJ?VW&$eWZ=uR5IC;mc!^Sx(WqFN$XcpcyGt9p(JH+uG3+*p z+HvPq@m9c|hICYtL7)oR<&MMouH(Eh6}T7V^Zv9<%FneFQslD%nIJ{l4-g1k*Fyk~ zlxU;T#$vQWSxqgDDAj6|N(p_X(1uamS?r6pDr0{c$NF(=)idAuNVNSlqz1~W`*1o+ z*>gQlu1u%hx3w06g_AmRnaS-rCgs}5r!oXi3Qu@QTpV0Xzc5%V7LCQeEFb-MXEA82 zF+!2(h?I-s=DT*40F>DoEG3dtDXQkOc}FKM0(aD;;unrc#EZ%-$iwjShAcjfV@YHqpx zLw)NI$KTmFu8^+39=G$%?B$t^_qPk?wl6tz)(mDBW|0%E#3rU!bx}2CbiWD{CtwUo zB)$yrWPlKss;;oFr;``9>^BDvRvrkW&mb#W=u8gLopfTXJ}Kc0g-Z&T zluY4DNzH_8-M63TU)*=FT!}vOtq)dyFd-pbeOJrbL6$quT+ngh@_F-FkX?W_nqARO zLQ_MY6l$&c;tQWZrqDvMzps;LHtg12-L+fW3ho!b^!D!Rgn@MRU4=_?1^3&_mrkF) zeCC-<_h-@-cX1%zhp}dYNYC&p(7_??q!AMOqCPfk-ObjQdVcCk_ru?OUw7w859yP4 z7d}*I@$P)h@|mgSQy0-D+u0rMqC4qDic=<@i$D;_6uxvR>k6B8>}BJo&c~wAy#L!D zDeWK6b2;PcAp9Wn;nueFo#&lBJ9W;~B@|?yE!CIkQ+Vdd?(n->_|D3s^P{@AoymMx!UOQz89s!%nTZl}I5Ry~1SPOyl zNjW~D4cWYFA1}Ok@G)tf_l}q98y88sW=-a;g_hJ^uRVKq_S~sU@$q?~w3)~z6WabX zT9nmjYe_pP^7#}->UoE{%jdk|($oXLUKb@N9MU!aC%rUN2-YoMHfz#((-spD@O)`A zu~qdTX1}pLl`DWkW2_-9Q{)Oh%Eo7Q_eRssd0X_;r+QCx5^EPPnY#46 zSqsU_92-hoNX)AT&?`V0jj@`HlO|UPsKw#A)f$!c>*8OXFi0!j>#m-=p!L#o=bp** zU@|Y1wh`*MuHs%zga(jORwID4nQWovmiy-5in)i_8pei|<$+^){PKRNGW_ebl0oRp3mq-%eWU6e|B z_byvDEBo3>XKD|MR#tUc^CKwT+iY7+ zPhh&^J*(O~Qg2@{eJbs4j?JaLB-UX1FYI)!R|AA5p{62oUYfb{+oc~kU-|fVohipu z-F@N#x5F3de>`j9lqqLVn#aMg$ib-is`KO;woeuks|ciz@B73y>Znw7@|$(>&ySfT zxz)@krp?GLo7*-SjA3`R3#`Bz`|7B+`QK|}sU#68;V^YlE19hKU$6bA?4o00ldk#a z^sH1MKR$JGD>G6p?5G?fHVP@k#MohY6oFKW#b~hBBBek`F(4*BdI?QLU>pjW3{z(0 zJ9bp{CxB0mJ0yvBWykc~^w}+KL^|P6SjHkSr!pZx#fEAnB1tp?iA9qNd@^~TMnjSo zD8~^kL7I;C0*5lC4_^C&>>am$u(EO7Abt8Dy>`cyS59irGdak!z1)p521m%Fi+7x~ z(o-*SXegCxv;}9de9kJ;UI+V2&+_7-2PpPb$+rebM_}#f?L}4*YfV0tqGNity|Pt* z4EVyhISvAIsLIkv!;`hF5AmJ{l@WB{RdHK=qr|)S-60=FS?!iEpK6RW(o6K z-^}FP61H{yifUNG3*3f!!T`ovvaU}e482{|x#wS!x_kWtVfCmXUH|`ZlWJ=9jJd7z z7PU{|V68+kuAR~zT^wpkr82YfD|q`^w@~nByrNH9Q}bxc%wyA`M}Y*#la0mptRdyN zNLNw`!$PH6`@{Nm$#X~T-SuqGFZa{#1s%B@j)g-}4UkyFsaI`X#q|}dbwG=5A?HsW zvR@XozJ=-e^9iE_V;gJV7^o%*Y3bA2o)xZiuN)VfWPL6vbfnXh(>Z$L8nqVPge>lSj})Di5AL)vX8(F$W4x6HLfk@b8s=@jXV`?^oun_YOvWtB~1hIIY) zxJ5@^lFz5edk)+C`molXlFmXB*8$CLS;0FN-b&6NIWVAYOflSzloDebAF`T+SS4h9 zmt4EwTHBTU88CK8J!fRjN~hfAg>(vIEPZhZ{RZ%qamGR z2&Gb$+4&W`bJ4fR`_o1TbYLw%-*zLeCy<_K`n;i12p|Z2T+ccGvuoQYjaia}CtsgR z`{X^3L)B_M)FDnS396K9%qgtkor`ZJ--rYqSj)p(zJzo&e#QZ7X;!hs+Mtak?Rf-g zZ$_n7TLS!h(~$n^dw5ca3sQlH3l!t1?!}xUE`v^>QVN;dx`KBtzLmT`b<|^if8d8a zy!m>Br|~ngDK+;Bm1iwsqVOF_I_G$$UU}}AAO%5Tj_b>*8Q&u|hDd3wwVVo!bOO~% z#GJxKT)Oy{#sKYK%R`&5L%0e*C6B5vEKpMktw9Rcb8)43-I#2WaK${wb2?IvOQH?2 zHb+(+CvsH@R4Ng(3oCf{(%TxcLBHR>mIt?753a^fORPBh>xi{M3UGZ73(HpBH+*1W zSV@wW`9a2!z9Xq55!z_v1mEOn5<#sRF{fn(?_ScFiu>KZwLG}x??7t&puTf;Jmw&= zwHRaY9EszJDf5k-3}$~*kc4EubR9e?D8-72uIUZ~n%lC1l}m4H4AB0yJh=Hfa5R3J zy3;gHouF;qy1POkrD(0za#NwNNl1dZ!V!2v5GD$1( zW^(@IQIA=__xn7&`K#c>c&Yvv_c*H&V=YQ+90{K9h^jO#O+ylh4o66|F(_k?tl3XE zK(&MgZExn?jRM-UhKII%6(M6BzwRy{i()M(V{rrsMsH-a>WUeVl)A!>t z6)CL68iO`wLQP_=a*0D#2ej_rXaZq(tr2@BfZz{+K-$u|OM_xE{d^9@)h#_=@A<5uf^YU;bKtYxH!h=+t! z$)R$#9_&8s)g1MOTY=TGK6(&H*McS&!|@u6buRs@ z+ZM1QYAWJz=T#`M%Jff;#9`4NYgG<9bn#3JlT%B{yR*=di;cbUTl3Zqsvpp*Wvj_I z;3WKJ_ZlAFd;?ZQNKbQQGI*S-6#bi6j71n-ZPvT9V2fJoms6FEb%+@k9SfFDxtKT4 zzna$6Od?(75Bt{f%k8(JV}tNieIzt{io?ek2Nhf9wO+)^W#1$hOllC&S1}?&c!N@~ zaeUOBCm}WlYb`>`?&e)^OQ+TrV=Rv74^}nn-dP75JDfA^oxEf5SMZ%|J$UQpdE>nQ zM%HWR-!^?2lY|I2X`Yg;pF_tmujL|EEx(0)(0~N(TEin-Zp4TL;p%!r$9WQHE%;JW zO%y6NXlZ(zpUeue*J?|w44#l<)72WR zy68kOxAj6+EniI`7(J4(e)ruxyyXV0h`~utSY%%!aD^aI29?-IE7j9HBxAQ*V~MoJ zmGxP7vw~!_VOn;{h>L0G&$tY*{B+}2&9}zd?QxGSSRL0 z&CZX+?1UvY3TsT!75ZTF>Q0EwI?_bSka3+c-H$*V$?P~%Ie*6GfZ)N6Uq&lN?Lc8Y zjFQZ2y?~X?NYLgRF@#td!-;DnF)4e-D4;F_Yk6?f-=np_$Z&W-S~9og!hS%bFL~E(&`oHf6A!5F%n>+s z$GRT8X6x$9hEI<@>;$UnCEGCeK&&)EfGg?=XPeq>C^Y40KR1k&k8b%oh8l%3;O|$EJ0+*Ai7LQa+~ zofZfjhm_~g7bPU2>9)!|KW0eQ@aw3m<7%QwNjc`ogRu$7gq=N4aQ}0kqptypI)CPS zdE27@i7T>LE$R}q{N@HFs2`B2p$Yp{3@1gk2C}|`BP8Wog0<#_UH6x^jdVXFK2>qf z`$eCxoy(m-w&w$nYGP2vjBy0jZCkOnkA0;VSSY|9qn^T%0?Iwv!nM(9@y}C`l5rQ&bB-!-2k9_d3e(e zB&Le8)%sEZCs`5>YiUb+NGa&4#+bxzXwA!~jv7+68a|#xW?L;v5W*6;5^Ijmwb3TT z5V51@3GRRPa}7z3SKn@6Q9);>N5ynRB?0u34p8Gs~;lVKhdV2RgJi75~#JWOa$|t3Y zJM1vze22EI!`@;@RMlkz4P{4ZXt$#k^6s!=di!b#u9WzW9GAhROoX-(JA0qt{^$Ot zX^Hyn?t6G-^Nl2?N@B|WtDPsM5MiukPFse)&`_+#V0i52D|(+FH%PZ!*7JhV_9sef zDzPRXxZ@UCQ6@s!h#fso^5f^e(6B^3z2{yY-E9X9B4rxzPjmK{e zVyvzwr3eqOzi$)sJ5~_5*&%Guy*#@4Mq<@3K_~exCSxHVxGbNQX4 z`*jtk%EY?#@`Bw-T!n?#%*wN`7}HY;F^PSoT%7k%b4xx=mQSy3xh0)eNvCQsBarVp{zj(2mQYkKL zrT^lV_w_x|Ogl{{B}|06NmhBMfcYt3kP8IGs$o2HvnM)4>4?PC*xvOx+o|5|&B*ZlzB08q24lb5ETCr99RRmqUfF9D|09l!Emk!d-y!AImodh5USTat zRS1(JQPM}O$|zNx5Gt-70yDgJPJwc0*ws}<)y#82l=WqB>XV+NT8&jg(#~#C8czOPp zI?;cQv@={skO?HU$Z(2hRvR6VHB8O>{ON)MPrg*5SdGyU-?;hm-tUapP;I!ZUUjHj z8uQ5{(#5`Ng0N6X%l)<~-6A-5Laa5UhLDtY^_?~8U{ z@b2IcmcL94BA0TIqP_!0h*y^cX#<(S;VnyB+1C@ZVNZ!9G%q5e%f4|%_0S1}1n}gK zqTgTmp1^lJ-WVm2PdOkUPVB1)P+i^s+46R}%bMS9>qEtQuZ_&gn?F$5c(m=0izRMx zi(igv`g_V~x+{uI;E+qZr(~k2|L7zL(t+SD%iAed6i>a>OA@PIW5pFWf2j2P@i@o0 zDW&W0nvp7|Yiom)c$Y-bn)Qg4rLUTt!hoP9tE_cC8mnvW8ZjR@4e%7 zo^iDtpZc-i>O`5_{6Kt2AZg9I7z@4S1a09|dDWGnp2%r>yUzt@<=J&8;+dUgVr8l} zvHxZD`-^MG^L*oO-miIZPT&=b-*7y6wIc-t}BAH=aNfH$~8?X)W`P3$2b<330z)x zW{zyi;kR2#bXQ}nHqW5=t8ZLh{LQgA@3DOu@V^u;6*#xKo|x?lK}*)d7)!CLh$oO# znf|98=T1qpWLAdma>6s)ON5ERXnq{q_^)rjyt4OLo&T73)2Hrfo#zO??FHguVFbC9 zOUf5iBSX2S(dOiZb$Gu`Th3+q+ze^oW#gU-dwXM4Y(k6q+ZH+P_Ajm46d%j$5aW2< zaBZ0@?rzCW@$6@Wke~H@(c&N|WL+E~DAg2|sJ=)0WPx>fPeMNBFn?N_866&bx)QeR ztCARlQ9Owf*M0N-Jr9jAm9Y(eH?EMxfZvND>QL>80S-}o3ln|S^i^+@TM{qi6(v{`bW%Abtq6nwHRL+V0Bs;h z8dZUl=F$4rE7N~IdA|QXKPAp~T@gqj2&5pBa_~I~{mGJ|*b*y^(sg%OY1^L{_LV0Y zm~uu4@En2b2s~Gk_66CrLq6@|yY)N@y_JOSvZ5Snl(DGDbk<7d=UabUyZ4drsb>bj z5u>O!1_3w><#0^~z|zM8k{kfV8&KT=00*l;IfM;kh(1lECo*sNfV=pNbN#pGCb@5N zeKE)P>#suf9f{{kQog`<>(83j^Dc-Z_DlC?60;UuM<9j3b3q7+BP~)$q^K{*RYOBH zGE^d6ccTFnnMzbK&mY>QAKLV*@X0?uVs`dlpEruFVE~kY>P!!Slnkh9fHc`-sqWlC zkOr&3!D>(r<7|jQ*PsAfm`U58zTI0kW1)9$uHAi2kdm{VfHude=aY~ETq$s+KuQou zTnB^@II{kDiKV`LP>-=05^YJeMO#~6P6>@M%I*s*c1!nO_4Kws#D9GHU-ecX95CpH zGyVhB*>w>>N>8*1DO#kof$s}3ly{+&MQf|Arff8QDz;rwMeixKC!q5Rx^VYwipoMT7qqL%8u`1aDCcay$m#@K7(?8{Fn_a~3;9n}eNzff8hg z0X3AXZH74KaS02JG_jSVd=3X^@b`=|X%-{gi)~;IGq~f18tp@UZ$|kXuKg1lyAvaP z4(?z%0^EVW5yM0}XaLYipcrQ6ZwIKskzOcfMgh%ufH~FyRx!f=#VFq$R!5@2c4$zN zMuRr6)5Qo9U>j^_Vnx9lJdYTMuoVqRQ?tLZ -SPDX-License-Identifier: GPL-3.0-or-later diff --git a/src/modules/users/page_usersetup.ui b/src/modules/users/page_usersetup.ui deleted file mode 100644 index c21907415e..0000000000 --- a/src/modules/users/page_usersetup.ui +++ /dev/null @@ -1,623 +0,0 @@ - - - -SPDX-FileCopyrightText: 2014 Teo Mrnjavac <teo@kde.org> -SPDX-License-Identifier: GPL-3.0-or-later - - Page_UserSetup - - - - 0 - 0 - 862 - 683 - - - - Form - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 6 - - - - - - - - What is your name? - - - - - - - - - - 200 - 0 - - - - Your Full Name - - - - - - - - 0 - 0 - - - - - 24 - 24 - - - - - 24 - 24 - - - - - - - true - - - - - - - - 1 - 0 - - - - - - - true - - - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 6 - - - - - - - - What name do you want to use to log in? - - - false - - - - - - - - - - 0 - 0 - - - - - 200 - 0 - - - - login - - - - - - - - 0 - 0 - - - - - 24 - 24 - - - - - 24 - 24 - - - - true - - - - - - - - 1 - 0 - - - - - 200 - 0 - - - - - - - Qt::AlignVCenter - - - true - - - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 6 - - - - - - - - What is the name of this computer? - - - false - - - - - - - - - - 0 - 0 - - - - - 200 - 0 - - - - <small>This name will be used if you make the computer visible to others on a network.</small> - - - Computer Name - - - - - - - - 0 - 0 - - - - - 24 - 24 - - - - - 24 - 24 - - - - true - - - - - - - - 1 - 0 - - - - - 200 - 0 - - - - - - - Qt::AlignVCenter - - - true - - - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 6 - - - - - - - - Choose a password to keep your account safe. - - - false - - - - - - - - - - 0 - 0 - - - - - 200 - 0 - - - - <small>Enter the same password twice, so that it can be checked for typing errors. A good password will contain a mixture of letters, numbers and punctuation, should be at least eight characters long, and should be changed at regular intervals.</small> - - - QLineEdit::Password - - - Password - - - - - - - - 0 - 0 - - - - - 200 - 0 - - - - <small>Enter the same password twice, so that it can be checked for typing errors. A good password will contain a mixture of letters, numbers and punctuation, should be at least eight characters long, and should be changed at regular intervals.</small> - - - QLineEdit::Password - - - Repeat Password - - - - - - - - 0 - 0 - - - - - 24 - 24 - - - - - 24 - 24 - - - - true - - - - - - - - 1 - 0 - - - - - 100 - 0 - - - - - - - Qt::AlignVCenter - - - true - - - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 6 - - - - - - - - When this box is checked, password-strength checking is done and you will not be able to use a weak password. - - - Require strong passwords. - - - - - - - Log in automatically without asking for the password. - - - - - - - Use the same password for the administrator account. - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 6 - - - - - - - - Choose a password for the administrator account. - - - false - - - - - - - - - - 0 - 0 - - - - - 200 - 0 - - - - <small>Enter the same password twice, so that it can be checked for typing errors.</small> - - - QLineEdit::Password - - - Password - - - - - - - - 0 - 0 - - - - - 200 - 0 - - - - <small>Enter the same password twice, so that it can be checked for typing errors.</small> - - - QLineEdit::Password - - - Repeat Password - - - - - - - - 0 - 0 - - - - - 24 - 24 - - - - - 24 - 24 - - - - true - - - - - - - - 1 - 0 - - - - - 100 - 0 - - - - - - - Qt::AlignVCenter - - - true - - - - - - - - - Qt::Vertical - - - - 20 - 1 - - - - - - - - - diff --git a/src/modules/users/tests/3-wing.conf b/src/modules/users/tests/3-wing.conf deleted file mode 100644 index 4fc760fa8c..0000000000 --- a/src/modules/users/tests/3-wing.conf +++ /dev/null @@ -1,5 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# ---- -defaultGroups: [ wing, wheel, users ] diff --git a/src/modules/users/tests/4-audio.conf b/src/modules/users/tests/4-audio.conf deleted file mode 100644 index 1280bc207d..0000000000 --- a/src/modules/users/tests/4-audio.conf +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# ---- -defaultGroups: - - users - - lp - - wheel - - audio diff --git a/src/modules/users/tests/5-issue-1523.conf b/src/modules/users/tests/5-issue-1523.conf deleted file mode 100644 index a0c5e49baa..0000000000 --- a/src/modules/users/tests/5-issue-1523.conf +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# ---- -defaultGroups: - - adm - - name: foo - must_exist: false - system: true - - name: bar - must_exist: true - - name: foobar - must_exist: false - system: false diff --git a/src/modules/users/tests/6a-issue-1672.conf b/src/modules/users/tests/6a-issue-1672.conf deleted file mode 100644 index b8ba24266d..0000000000 --- a/src/modules/users/tests/6a-issue-1672.conf +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# ---- -autologinGroup: derp -doAutologin: true - diff --git a/src/modules/users/tests/6b-issue-1672.conf b/src/modules/users/tests/6b-issue-1672.conf deleted file mode 100644 index a54e71e010..0000000000 --- a/src/modules/users/tests/6b-issue-1672.conf +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# ---- -autologinGroup: derp -doAutoLogin: true - diff --git a/src/modules/users/tests/6c-issue-1672.conf b/src/modules/users/tests/6c-issue-1672.conf deleted file mode 100644 index 5d12bd71e3..0000000000 --- a/src/modules/users/tests/6c-issue-1672.conf +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# ---- -autoLoginGroup: derp -doAutologin: true - diff --git a/src/modules/users/tests/6d-issue-1672.conf b/src/modules/users/tests/6d-issue-1672.conf deleted file mode 100644 index 80976bf64d..0000000000 --- a/src/modules/users/tests/6d-issue-1672.conf +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# ---- -autoLoginGroup: derp -doAutoLogin: true - diff --git a/src/modules/users/tests/6e-issue-1672.conf b/src/modules/users/tests/6e-issue-1672.conf deleted file mode 100644 index df299b4801..0000000000 --- a/src/modules/users/tests/6e-issue-1672.conf +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# ---- -doautologin: true -autologingroup: wheel - diff --git a/src/modules/users/tests/7an-shell.conf b/src/modules/users/tests/7an-shell.conf deleted file mode 100644 index 772ea52368..0000000000 --- a/src/modules/users/tests/7an-shell.conf +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# ---- -# Unset (bogus needed to keep it valid YAML) -user: - # shell: /usr/bin/dash - bogus: true diff --git a/src/modules/users/tests/7ao-shell.conf b/src/modules/users/tests/7ao-shell.conf deleted file mode 100644 index e2b49dc79b..0000000000 --- a/src/modules/users/tests/7ao-shell.conf +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# ---- -# Unset (bogus needed to keep it valid YAML) -# userShell: /usr/bin/dash -bogus: true diff --git a/src/modules/users/tests/7bn-shell.conf b/src/modules/users/tests/7bn-shell.conf deleted file mode 100644 index 7e568eefda..0000000000 --- a/src/modules/users/tests/7bn-shell.conf +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# ---- -# Explicitly empty -user: - shell: "" - diff --git a/src/modules/users/tests/7bo-shell.conf b/src/modules/users/tests/7bo-shell.conf deleted file mode 100644 index 1ecaf192b8..0000000000 --- a/src/modules/users/tests/7bo-shell.conf +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# ---- -# Explicitly empty -userShell: "" - diff --git a/src/modules/users/tests/7cn-shell.conf b/src/modules/users/tests/7cn-shell.conf deleted file mode 100644 index a13e449337..0000000000 --- a/src/modules/users/tests/7cn-shell.conf +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# ---- -# Non-absolute path is ignored -user: - shell: dash - diff --git a/src/modules/users/tests/7co-shell.conf b/src/modules/users/tests/7co-shell.conf deleted file mode 100644 index b3e2d58d4e..0000000000 --- a/src/modules/users/tests/7co-shell.conf +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# ---- -# Non-absolute path is ignored -userShell: dash - diff --git a/src/modules/users/tests/7dn-shell.conf b/src/modules/users/tests/7dn-shell.conf deleted file mode 100644 index ddca7f40c9..0000000000 --- a/src/modules/users/tests/7dn-shell.conf +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# ---- -# Invalid setting (should be string), won't pass validation -user: - shell: [1] - diff --git a/src/modules/users/tests/7do-shell.conf b/src/modules/users/tests/7do-shell.conf deleted file mode 100644 index 18871495c4..0000000000 --- a/src/modules/users/tests/7do-shell.conf +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# ---- -# Invalid setting (should be string), won't pass validation -userShell: [1] - diff --git a/src/modules/users/tests/7en-shell.conf b/src/modules/users/tests/7en-shell.conf deleted file mode 100644 index d0a28a7e41..0000000000 --- a/src/modules/users/tests/7en-shell.conf +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# ---- -# Explicitly set with full path -user: - shell: /usr/bin/dash - diff --git a/src/modules/users/tests/7eo-shell.conf b/src/modules/users/tests/7eo-shell.conf deleted file mode 100644 index e8fbbf7562..0000000000 --- a/src/modules/users/tests/7eo-shell.conf +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# ---- -# Explicitly set with full path -userShell: /usr/bin/dash - diff --git a/src/modules/users/tests/7fb-shell.conf b/src/modules/users/tests/7fb-shell.conf deleted file mode 100644 index cd660e897f..0000000000 --- a/src/modules/users/tests/7fb-shell.conf +++ /dev/null @@ -1,10 +0,0 @@ -# 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 diff --git a/src/modules/users/tests/7fn-shell.conf b/src/modules/users/tests/7fn-shell.conf deleted file mode 100644 index 13dca6da43..0000000000 --- a/src/modules/users/tests/7fn-shell.conf +++ /dev/null @@ -1,10 +0,0 @@ -# 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 diff --git a/src/modules/users/tests/7fo-shell.conf b/src/modules/users/tests/7fo-shell.conf deleted file mode 100644 index c15db233da..0000000000 --- a/src/modules/users/tests/7fo-shell.conf +++ /dev/null @@ -1,10 +0,0 @@ -# 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 diff --git a/src/modules/users/users.conf b/src/modules/users/users.conf deleted file mode 100644 index 669cac038b..0000000000 --- a/src/modules/users/users.conf +++ /dev/null @@ -1,274 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Configuration for the one-user-system user module. -# -# Besides these settings, the users module also places the following -# keys into the Global Storage area, based on user input in the view step. -# -# - hostname -# - username -# - password (obscured) -# - autologinUser (if enabled, set to username) -# -# These Global Storage keys are set when the configuration for this module -# is read and when they are modified in the UI. ---- -### GROUPS CONFIGURATION -# -# The system has groups of uses. Some special groups must be -# created during installation. Optionally, there are special -# groups for users who can use sudo and for supporting autologin. - -# Used as default groups for the created user. -# Adjust to your Distribution defaults. -# -# Each entry in the *defaultGroups* list is either: -# - a string, naming a group; this is a **non**-system group -# which does not need to exist in the target system; if it -# does not exist, it will be created. -# - an entry with subkeys *name*, *must_exist* and *system*; -# if the group *must_exist* and does not, an error is thrown -# and the installation fails. -# -# The group is created if it does not exist, and it is -# created as a system group (GID < 1000) or user group -# (GID >= 1000) depending on the value of *system*. -defaultGroups: - - name: users - must_exist: true - system: true - - lp - - video - - network - - storage - - name: wheel - must_exist: false - system: true - - audio - -# When *sudoersGroup* is set to a non-empty string, Calamares creates a -# sudoers file for the user. This file is located at: -# `/etc/sudoers.d/10-installer` -# Remember to add the (value of) *sudoersGroup* to *defaultGroups*. -# -# If your Distribution already sets up a group of sudoers in its packaging, -# remove this setting (delete or comment out the line below). Otherwise, -# the setting will be duplicated in the `/etc/sudoers.d/10-installer` file, -# potentially confusing users. -sudoersGroup: wheel - -# Some Distributions require a 'autologin' group for the user. -# Autologin causes a user to become automatically logged in to -# the desktop environment on boot. -# Disable when your Distribution does not require such a group. -autologinGroup: autologin - - -### ROOT AND SUDO -# -# Some distributions have a root user enabled for login. Others -# rely entirely on sudo or similar mechanisms to raise privileges. - -# If set to `false` (the default), writes a sudoers file with `ALL=(ALL)` -# so that commands can be run as any user. If set to `true`, writes -# `ALL=(ALL:ALL)` so that any user and any group can be chosen. -sudoersConfigureWithGroup: false - -# Setting this to false, causes the root account to be disabled. -# When disabled, hides the "Use the same password for administrator" -# checkbox. Also hides the "Choose a password" and associated text-inputs. -setRootPassword: true - -# You can control the initial state for the 'reuse password for root' -# checkbox here. Possible values are: -# - true to check or -# - false to uncheck -# -# When checked, the user password is used for the root account too. -# -# NOTE: *doReusePassword* requires *setRootPassword* to be enabled. -doReusePassword: true - - -### PASSWORDS AND LOGIN -# -# Autologin is convenient for single-user systems, but depends on -# the location of the machine if it is practical. "Password strength" -# measures measures might improve security by enforcing hard-to-guess -# passwords, or might encourage a post-it-under-the-keyboard approach. -# Distributions are free to steer their users to one kind of password -# or another. Weak(er) passwords may be allowed, may cause a warning, -# or may be forbidden entirely. - -# You can control the initial state for the 'autologin checkbox' here. -# Possible values are: -# - true to check or -# - false to uncheck -# These set the **initial** state of the checkbox. -doAutologin: true - -# These are optional password-requirements that a distro can enforce -# on the user. The values given in this sample file set only very weak -# validation settings. -# -# Calamares itself supports two checks: -# - minLength -# - maxLength -# In this sample file, the values are set to -1 which means "no -# minimum", "no maximum". This allows any password at all. -# No effort is done to ensure that the checks are consistent -# (e.g. specifying a maximum length less than the minimum length -# will annoy users). -# -# Calamares supports password checking through libpwquality. -# The libpwquality check relies on the (optional) libpwquality library. -# The value for libpwquality is a list of configuration statements like -# those found in pwquality.conf. The statements are handed off to the -# libpwquality parser for evaluation. The check is ignored if -# libpwquality is not available at build time (generates a warning in -# the log). The Calamares password check rejects passwords with a -# score of < 40 with the given libpwquality settings. -# -# (additional checks may be implemented in CheckPWQuality.cpp and -# wired into UsersPage.cpp) -# -# To disable all password validations: -# - comment out the relevant 'passwordRequirements' keys below, -# or set minLength and maxLength to -1. -# - disable libpwquality at build-time. -# To allow all passwords, but provide warnings: -# - set both 'allowWeakPasswords' and 'allowWeakPasswordsDefault' to true. -# (That will show the box *Allow weak passwords* in the user- -# interface, and check it by default). -# - configure password-checking however you wish. -# To require specific password characteristics: -# - set 'allowWeakPasswords' to false (the default) -# - configure password-checking, e.g. with NIST settings - - -# These are very weak -- actually, none at all -- requirements -passwordRequirements: - minLength: -1 # Password at least this many characters - maxLength: -1 # Password at most this many characters - libpwquality: - - minlen=0 - - minclass=0 - -# These are "you must have a password, any password" -- requirements -# -# passwordRequirements: -# minLength: 1 - -# These are requirements the try to follow the suggestions from -# https://pages.nist.gov/800-63-3/sp800-63b.html , "Digital Identity Guidelines". -# Note that requiring long and complex passwords has its own cost, -# because the user has to come up with one at install time. -# Setting 'allowWeakPasswords' to false and 'doAutologin' to false -# will require a strong password and prevent (graphical) login -# without the password. It is likely to be annoying for casual users. -# -# passwordRequirements: -# minLength: 8 -# maxLength: 64 -# libpwquality: -# - minlen=8 -# - maxrepeat=3 -# - maxsequence=3 -# - usersubstr=4 -# - badwords=linux - -# You can control the visibility of the 'strong passwords' checkbox here. -# Possible values are: -# - true to show or -# - false to hide (default) -# the checkbox. This checkbox allows the user to choose to disable -# password-strength-checks. By default the box is **hidden**, so -# that you have to pick a password that satisfies the checks. -allowWeakPasswords: false -# You can control the initial state for the 'strong passwords' checkbox here. -# Possible values are: -# - true to uncheck or -# - false to check (default) -# the checkbox by default. Since the box is labeled to enforce strong -# passwords, in order to **allow** weak ones by default, the box needs -# to be unchecked. -allowWeakPasswordsDefault: false - - -# 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 ] - - -# Hostname settings -# -# The user can enter a hostname; this is configured into the system -# in some way. There are settings for how a hostname is guessed (as -# a default / suggestion) and where (or how) the hostname is set in -# the target system. -# -# Key *hostname* has the following sub-keys: -# -# - *location* How the hostname is set in the target system: -# - *None*, to not set the hostname at all -# - *EtcFile*, to write to `/etc/hostname` directly -# - *Etc*, identical to above -# - *Hostnamed*, to use systemd hostnamed(1) over DBus -# - *Transient*, to remove `/etc/hostname` from the target -# The default is *EtcFile*. Setting this to *None* or *Transient* will -# hide the hostname field. -# - *writeHostsFile* Should /etc/hosts be written with a hostname for -# this machine (also adds localhost and some ipv6 standard entries). -# Defaults to *true*. -# - *template* Is a simple template for making a suggestion for the -# hostname, based on user data. The default is "${first}-${product}". -# This is used only if the hostname field is shown. KMacroExpander is -# used; write `${key}` where `key` is one of the following: -# - *first* User's first name (whatever is first in the User Name field, -# which is first-in-order but not necessarily a "first name" as in -# "given name" or "name by which you call someone"; beware of western bias) -# - *name* All the text in the User Name field. -# - *login* The login name (which may be suggested based on User Name) -# - *product* The hardware product, based on DMI data -# - *product2* The product as described by Qt -# - *cpu* CPU name -# - *host* Current hostname (which may be a transient hostname) -# Literal text in the template is preserved. Calamares tries to map -# `${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 ] - -presets: - fullName: - # value: "OEM User" - editable: true - loginName: - # value: "oem" - editable: true diff --git a/src/modules/users/users.qrc b/src/modules/users/users.qrc deleted file mode 100644 index 70392c32b8..0000000000 --- a/src/modules/users/users.qrc +++ /dev/null @@ -1,6 +0,0 @@ - - - images/invalid.png - images/valid.png - - diff --git a/src/modules/users/users.schema.yaml b/src/modules/users/users.schema.yaml deleted file mode 100644 index a675043210..0000000000 --- a/src/modules/users/users.schema.yaml +++ /dev/null @@ -1,71 +0,0 @@ -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later ---- -$schema: https://json-schema.org/schema# -$id: https://calamares.io/schemas/users -additionalProperties: false -type: object -properties: - user: - additionalProperties: false - type: object - properties: - # User shell, should be path to /bin/sh or so - shell: { type: string } - forbidden_names: { type: array, items: { type: string } } - # Group settings - defaultGroups: - type: array - items: - oneOf: - - type: string - - type: object - properties: - name: { type: string } - must_exist: { type: boolean, default: false } - system: { type: boolean, default: false } - additionalProperties: false - required: [ name ] - autologinGroup: { type: string } - sudoersGroup: { type: string } - sudoersConfigureWithGroup: { type: boolean, default: false } - # Skip login (depends on displaymanager support) - doAutologin: { type: boolean, default: true } - # Root password separate from user password? - setRootPassword: { type: boolean, default: true } - doReusePassword: { type: boolean, default: true } - # Passwords that don't pass a quality test - allowWeakPasswords: { type: boolean, default: false } - allowWeakPasswordsDefault: { type: boolean, default: false } - passwordRequirements: - additionalProperties: false - type: object - properties: - minLength: { type: number } - maxLength: { type: number } - libpwquality: { type: array, items: { type: string } } # Don't know what libpwquality supports - hostname: - additionalProperties: false - type: object - 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 } } - - # Presets - # - # TODO: lift up somewhere, since this will return in many modules; - # the type for each field (fullName, loginName) is a - # preset-description (value, editable). - presets: - type: object - additionalProperties: false - properties: - fullName: { type: object } - loginName: { type: object } - -required: - - defaultGroups - - autologinGroup - - sudoersGroup diff --git a/src/modules/usersq/CMakeLists.txt b/src/modules/usersq/CMakeLists.txt deleted file mode 100644 index 5cfd55818f..0000000000 --- a/src/modules/usersq/CMakeLists.txt +++ /dev/null @@ -1,51 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# -if(NOT WITH_QML) - calamares_skip_module( "usersq (QML is not supported in this build)" ) - return() -endif() - -find_package(${qtname} ${QT_VERSION} CONFIG REQUIRED Core DBus Network) -find_package(Crypt REQUIRED) - -# Add optional libraries here -set(USER_EXTRA_LIB) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../users) - -find_package(LibPWQuality) -set_package_properties(LibPWQuality PROPERTIES PURPOSE "Extra checks of password quality") - -if(LibPWQuality_FOUND) - list(APPEND USER_EXTRA_LIB ${LibPWQuality_LIBRARIES}) - include_directories(${LibPWQuality_INCLUDE_DIRS}) - add_definitions(-DCHECK_PWQUALITY -DHAVE_LIBPWQUALITY) -endif() - -#needed for ${_users}/Config.cpp -find_package(ICU COMPONENTS uc i18n) -set_package_properties(ICU PROPERTIES PURPOSE "Transliteration support for full name to username conversion") - -if(ICU_FOUND) - list(APPEND USER_EXTRA_LIB ICU::uc ICU::i18n) - include_directories(${ICU_INCLUDE_DIRS}) - add_definitions(-DHAVE_ICU) -endif() - -calamares_add_plugin(usersq - TYPE viewmodule - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - UsersQmlViewStep.cpp - RESOURCES - usersq${QT_VERSION_SUFFIX}.qrc - LINK_PRIVATE_LIBRARIES - users_internal - ${CRYPT_LIBRARIES} - ${USER_EXTRA_LIB} - ${qtname}::DBus - SHARED_LIB -) diff --git a/src/modules/usersq/UsersQmlViewStep.cpp b/src/modules/usersq/UsersQmlViewStep.cpp deleted file mode 100644 index cc35c0b0fd..0000000000 --- a/src/modules/usersq/UsersQmlViewStep.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017-2018 Adriaan de Groot - * SPDX-FileCopyrightText: 2017 Gabriel Craciunescu - * SPDX-FileCopyrightText: 2020 Camilo Higuita - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "UsersQmlViewStep.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "utils/Logger.h" -#include "utils/NamedEnum.h" -#include "utils/Variant.h" - -CALAMARES_PLUGIN_FACTORY_DEFINITION( UsersQmlViewStepFactory, registerPlugin< UsersQmlViewStep >(); ) - -UsersQmlViewStep::UsersQmlViewStep( QObject* parent ) - : Calamares::QmlViewStep( parent ) - , m_config( new Config( this ) ) -{ - connect( m_config, &Config::readyChanged, this, &UsersQmlViewStep::nextStatusChanged ); - - emit nextStatusChanged( true ); -} - -QString -UsersQmlViewStep::prettyName() const -{ - return tr( "Users" ); -} - -bool -UsersQmlViewStep::isNextEnabled() const -{ - return m_config->isReady(); -} - -bool -UsersQmlViewStep::isBackEnabled() const -{ - return true; -} - -bool -UsersQmlViewStep::isAtBeginning() const -{ - return true; -} - -bool -UsersQmlViewStep::isAtEnd() const -{ - return true; -} - -Calamares::JobList -UsersQmlViewStep::jobs() const -{ - return m_config->createJobs(); -} - -void -UsersQmlViewStep::onLeave() -{ - m_config->finalizeGlobalStorage(); -} - -void -UsersQmlViewStep::setConfigurationMap( const QVariantMap& configurationMap ) -{ - m_config->setConfigurationMap( configurationMap ); - Calamares::QmlViewStep::setConfigurationMap( configurationMap ); // call parent implementation last -} diff --git a/src/modules/usersq/UsersQmlViewStep.h b/src/modules/usersq/UsersQmlViewStep.h deleted file mode 100644 index e98df9d032..0000000000 --- a/src/modules/usersq/UsersQmlViewStep.h +++ /dev/null @@ -1,54 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017 Adriaan de Groot - * SPDX-FileCopyrightText: 2020 Camilo Higuita - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef USERSQMLVIEWSTEP_H -#define USERSQMLVIEWSTEP_H - -// Config from users module -#include "Config.h" - -#include "DllMacro.h" -#include "utils/PluginFactory.h" -#include "viewpages/QmlViewStep.h" - -#include -#include - -class PLUGINDLLEXPORT UsersQmlViewStep : public Calamares::QmlViewStep -{ - Q_OBJECT - -public: - explicit UsersQmlViewStep( 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 onLeave() override; - - void setConfigurationMap( const QVariantMap& configurationMap ) override; - - QObject* getConfig() override { return m_config; } - -private: - Config* m_config; -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( UsersQmlViewStepFactory ) - -#endif // USERSQMLVIEWSTEP_H diff --git a/src/modules/usersq/usersq-qt6.qml b/src/modules/usersq/usersq-qt6.qml deleted file mode 100644 index ea17ac4eeb..0000000000 --- a/src/modules/usersq/usersq-qt6.qml +++ /dev/null @@ -1,425 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 - 2022 Anke Boersma - * SPDX-FileCopyrightText: 2021 Adriaan de Groot - * 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 -import QtQuick.Controls -import QtQuick.Layouts -import org.kde.kirigami as Kirigami -import QtQuick.Window - -Kirigami.ScrollablePage { - // You can hard-code a color here, or bind to a Kirigami theme color, - // or use a color from Calamares branding, or .. - readonly property color unfilledFieldColor: "#FBFBFB" //Kirigami.Theme.backgroundColor - readonly property color positiveFieldColor: "#F0FFF0" //Kirigami.Theme.positiveBackgroundColor - readonly property color negativeFieldColor: "#EBCED1" //Kirigami.Theme.negativeBackgroundColor - readonly property color unfilledFieldOutlineColor: "#F1F1F1" - readonly property color positiveFieldOutlineColor: "#DCFFDC" - readonly property color negativeFieldOutlineColor: "#BE5F68" - readonly property color headerTextColor: "#1F1F1F" - readonly property color commentsColor: "#6D6D6D" - - width: parent.width - height: parent.height - - header: Kirigami.Heading { - Layout.fillWidth: true - height: 50 - horizontalAlignment: Qt.AlignHCenter - color: headerTextColor - font.weight: Font.Medium - font.pointSize: 12 - text: qsTr("Pick your user name and credentials to login and perform admin tasks") - } - - ColumnLayout { - id: _formLayout - spacing: Kirigami.Units.smallSpacing - - Column { - Layout.fillWidth: true - spacing: Kirigami.Units.smallSpacing - - Label { - width: parent.width - text: qsTr("What is your name?") - } - - TextField { - id: _userNameField - width: parent.width - enabled: config.isEditable("fullName") - placeholderText: qsTr("Your full name") - text: config.fullName - onTextChanged: config.setFullName(text) - - palette.base: _userNameField.text.length - ? positiveFieldColor : unfilledFieldColor - palette.highlight : _userNameField.text.length - ? positiveFieldOutlineColor : unfilledFieldOutlineColor - } - } - - Column { - Layout.fillWidth: true - spacing: Kirigami.Units.smallSpacing - - Label { - width: parent.width - text: qsTr("What name do you want to use to log in?") - } - - TextField { - id: _userLoginField - width: parent.width - enabled: config.isEditable("loginName") - placeholderText: qsTr("Login name") - text: config.loginName - validator: RegularExpressionValidator { regularExpression: /[a-z_][a-z0-9_-]*[$]?$/ } - - onTextChanged: acceptableInput - ? ( _userLoginField.text === "root" - ? forbiddenMessage.visible=true - : ( config.setLoginName(text), - userMessage.visible = false,forbiddenMessage.visible=false ) ) - : ( userMessage.visible = true,console.log("Invalid") ) - - palette.base: _userLoginField.text.length - ? ( acceptableInput - ? ( _userLoginField.text === "root" - ? negativeFieldColor - : positiveFieldColor ) - : negativeFieldColor ) - : unfilledFieldColor - palette.highlight : _userLoginField.text.length - ? ( acceptableInput - ? ( _userLoginField.text === "root" - ? negativeFieldOutlineColor - : positiveFieldOutlineColor ) - : negativeFieldOutlineColor ) - : unfilledFieldOutlineColor - } - - Label { - width: parent.width - text: qsTr("If more than one person will use this computer, you can create multiple accounts after installation.") - font.weight: Font.Thin - font.pointSize: 8 - color: commentsColor - } - } - - Kirigami.InlineMessage { - id: userMessage - Layout.fillWidth: true - showCloseButton: true - visible: false - type: Kirigami.MessageType.Error - text: qsTr("Only lowercase letters, numbers, underscore and hyphen are allowed.") - } - - Kirigami.InlineMessage { - id: forbiddenMessage - Layout.fillWidth: true - showCloseButton: true - visible: false - type: Kirigami.MessageType.Error - text: qsTr("root is not allowed as username.") - } - - Column { - Layout.fillWidth: true - spacing: Kirigami.Units.smallSpacing - - Label { - width: parent.width - text: qsTr("What is the name of this computer?") - } - - TextField { - id: _hostName - width: parent.width - placeholderText: qsTr("Computer name") - text: config.hostname - validator: RegularExpressionValidator { regularExpression: /[a-zA-Z0-9][-a-zA-Z0-9_]+/ } - - onTextChanged: acceptableInput - ? ( _hostName.text === "localhost" - ? forbiddenHost.visible=true - : ( config.setHostName(text), - hostMessage.visible = false,forbiddenHost.visible = false ) ) - : hostMessage.visible = true - - palette.base: _hostName.text.length - ? ( acceptableInput - ? ( _hostName.text === "localhost" - ? negativeFieldColor : positiveFieldColor ) - : negativeFieldColor) - : unfilledFieldColor - palette.highlight : _hostName.text.length - ? ( acceptableInput - ? ( _hostName.text === "localhost" - ? negativeFieldOutlineColor : positiveFieldOutlineColor ) - : negativeFieldOutlineColor) - : unfilledFieldOutlineColor - } - - Label { - width: parent.width - text: qsTr("This name will be used if you make the computer visible to others on a network.") - font.weight: Font.Thin - font.pointSize: 8 - color: commentsColor - } - } - - Kirigami.InlineMessage { - id: hostMessage - Layout.fillWidth: true - showCloseButton: true - visible: false - type: Kirigami.MessageType.Error - text: qsTr("Only letters, numbers, underscore and hyphen are allowed, minimal of two characters.") - } - - Kirigami.InlineMessage { - id: forbiddenHost - Layout.fillWidth: true - showCloseButton: true - visible: false - type: Kirigami.MessageType.Error - text: qsTr("localhost is not allowed as hostname.") - } - - Column { - Layout.fillWidth: true - spacing: Kirigami.Units.smallSpacing - - Label { - width: parent.width - text: qsTr("Choose a password to keep your account safe.") - } - - Row { - width: parent.width - spacing: 20 - - TextField { - id: _passwordField - width: parent.width / 2 - 10 - placeholderText: qsTr("Password") - text: config.userPassword - onTextChanged: config.setUserPassword(text) - - palette.base: _passwordField.text.length - ? positiveFieldColor : unfilledFieldColor - palette.highlight : _passwordField.text.length - ? positiveFieldOutlineColor : unfilledFieldOutlineColor - - echoMode: TextInput.Password - passwordMaskDelay: 300 - inputMethodHints: Qt.ImhNoAutoUppercase - } - - TextField { - id: _verificationPasswordField - width: parent.width / 2 - 10 - placeholderText: qsTr("Repeat password") - text: config.userPasswordSecondary - - onTextChanged: _passwordField.text === _verificationPasswordField.text - ? ( config.setUserPasswordSecondary(text), - passMessage.visible = false, - validityMessage.visible = true ) - : ( passMessage.visible = true, - validityMessage.visible = false ) - - palette.base: _verificationPasswordField.text.length - ? ( _passwordField.text === _verificationPasswordField.text - ? positiveFieldColor : negativeFieldColor ) - : unfilledFieldColor - palette.highlight : _verificationPasswordField.text.length - ? ( _passwordField.text === _verificationPasswordField.text - ? positiveFieldOutlineColor : negativeFieldOutlineColor ) - : unfilledFieldOutlineColor - - echoMode: TextInput.Password - passwordMaskDelay: 300 - inputMethodHints: Qt.ImhNoAutoUppercase - } - } - - Label { - width: parent.width - text: qsTr("Enter the same password twice, so that it can be checked for typing errors. A good password will contain a mixture of letters, numbers and punctuation, should be at least eight characters long, and should be changed at regular intervals.") - font.weight: Font.Thin - font.pointSize: 8 - wrapMode: Text.WordWrap - color: commentsColor - } - } - - Kirigami.InlineMessage { - id: passMessage - Layout.fillWidth: true - showCloseButton: true - visible: false - type: Kirigami.MessageType.Error - text: config.userPasswordMessage - } - - Kirigami.InlineMessage { - id: validityMessage - Layout.fillWidth: true - showCloseButton: true - visible: false - type: config.userPasswordValidity - ? ( config.requireStrongPasswords - ? Kirigami.MessageType.Error : Kirigami.MessageType.Warning ) - : Kirigami.MessageType.Positive - text: config.userPasswordMessage - } - - CheckBox { - id: root - visible: config.writeRootPassword - text: qsTr("Reuse user password as root password") - checked: config.reuseUserPasswordForRoot - onCheckedChanged: config.setReuseUserPasswordForRoot(checked) - } - - Label { - visible: root.checked - width: parent.width - text: qsTr("Use the same password for the administrator account.") - font.weight: Font.Thin - font.pointSize: 8 - color: commentsColor - } - - Column { - visible: ! root.checked - Layout.fillWidth: true - spacing: Kirigami.Units.smallSpacing - - Label { - width: parent.width - text: qsTr("Choose a root password to keep your account safe.") - } - - Row { - width: parent.width - spacing: 20 - - TextField { - id: _rootPasswordField - width: parent.width / 2 -10 - placeholderText: qsTr("Root password") - text: config.rootPassword - - onTextChanged: config.setRootPassword(text) - - palette.base: _rootPasswordField.text.length - ? positiveFieldColor : unfilledFieldColor - palette.highlight : _rootPasswordField.text.length - ? positiveFieldOutlineColor : unfilledFieldOutlineColor - - echoMode: TextInput.Password - passwordMaskDelay: 300 - inputMethodHints: Qt.ImhNoAutoUppercase - } - - TextField { - id: _verificationRootPasswordField - width: parent.width / 2 -10 - placeholderText: qsTr("Repeat root password") - text: config.rootPasswordSecondary - - onTextChanged: _rootPasswordField.text === _verificationRootPasswordField.text - ? ( config.setRootPasswordSecondary(text), - rootPassMessage.visible = false,rootValidityMessage.visible = true ) - : ( rootPassMessage.visible = true,rootValidityMessage.visible = false ) - - palette.base: _verificationRootPasswordField.text.length - ? ( _rootPasswordField.text === _verificationRootPasswordField.text - ? positiveFieldColor : negativeFieldColor) - : unfilledFieldColor - palette.highlight : _verificationRootPasswordField.text.length - ? ( _rootPasswordField.text === _verificationRootPasswordField.text - ? positiveFieldOutlineColor : negativeFieldOutlineColor) - : unfilledFieldOutlineColor - - echoMode: TextInput.Password - passwordMaskDelay: 300 - inputMethodHints: Qt.ImhNoAutoUppercase - } - } - - Label { - visible: ! root.checked - width: parent.width - text: qsTr("Enter the same password twice, so that it can be checked for typing errors.") - font.weight: Font.Thin - font.pointSize: 8 - color: commentsColor - } - } - - Kirigami.InlineMessage { - id: rootPassMessage - Layout.fillWidth: true - showCloseButton: true - visible: false - type: Kirigami.MessageType.Error - text: config.rootPasswordMessage - } - - Kirigami.InlineMessage { - id: rootValidityMessage - Layout.fillWidth: true - showCloseButton: true - visible: false - type: config.rootPasswordValidity - ? ( config.requireStrongPasswords - ? Kirigami.MessageType.Error : Kirigami.MessageType.Warning ) - : Kirigami.MessageType.Positive - text: config.rootPasswordMessage - } - - CheckBox { - Layout.alignment: Qt.AlignCenter - text: qsTr("Log in automatically without asking for the password") - checked: config.doAutoLogin - onCheckedChanged: config.setAutoLogin(checked) - } - - CheckBox { - visible: config.permitWeakPasswords - Layout.alignment: Qt.AlignCenter - text: qsTr("Validate passwords quality") - checked: config.requireStrongPasswords - onCheckedChanged: config.setRequireStrongPasswords(checked), - rootPassMessage.visible = false - } - - Label { - visible: config.permitWeakPasswords - width: parent.width - Layout.alignment: Qt.AlignCenter - text: qsTr("When this box is checked, password-strength checking is done and you will not be able to use a weak password.") - font.weight: Font.Thin - font.pointSize: 8 - color: commentsColor - } - } -} diff --git a/src/modules/usersq/usersq-qt6.qrc b/src/modules/usersq/usersq-qt6.qrc deleted file mode 100644 index 98dcf61be8..0000000000 --- a/src/modules/usersq/usersq-qt6.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - usersq-qt6.qml - - diff --git a/src/modules/usersq/usersq.conf b/src/modules/usersq/usersq.conf deleted file mode 100644 index ea171bd915..0000000000 --- a/src/modules/usersq/usersq.conf +++ /dev/null @@ -1,44 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# For documentation see Users Module users.conf -# ---- -# Used as default groups for the created user. -# Adjust to your Distribution defaults. -defaultGroups: - - users - - lp - - video - - network - - storage - - wheel - - audio - - lpadmin - -autologinGroup: autologin - -doAutologin: true - -sudoersGroup: wheel - -setRootPassword: true - -doReusePassword: true - -passwordRequirements: - minLength: -1 - maxLength: -1 - libpwquality: - - minlen=0 - - minclass=0 - -allowWeakPasswords: false - -allowWeakPasswordsDefault: false - -userShell: /bin/bash - -setHostname: EtcFile - -writeHostsFile: true diff --git a/src/modules/usersq/usersq.qml b/src/modules/usersq/usersq.qml deleted file mode 100644 index d057f6454a..0000000000 --- a/src/modules/usersq/usersq.qml +++ /dev/null @@ -1,426 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 - 2022 Anke Boersma - * SPDX-FileCopyrightText: 2021 Adriaan de Groot - * 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.10 -import QtQuick.Layouts 1.3 -import org.kde.kirigami 2.7 as Kirigami -import QtGraphicalEffects 1.0 -import QtQuick.Window 2.3 - -Kirigami.ScrollablePage { - // You can hard-code a color here, or bind to a Kirigami theme color, - // or use a color from Calamares branding, or .. - readonly property color unfilledFieldColor: "#FBFBFB" //Kirigami.Theme.backgroundColor - readonly property color positiveFieldColor: "#F0FFF0" //Kirigami.Theme.positiveBackgroundColor - readonly property color negativeFieldColor: "#EBCED1" //Kirigami.Theme.negativeBackgroundColor - readonly property color unfilledFieldOutlineColor: "#F1F1F1" - readonly property color positiveFieldOutlineColor: "#DCFFDC" - readonly property color negativeFieldOutlineColor: "#BE5F68" - readonly property color headerTextColor: "#1F1F1F" - readonly property color commentsColor: "#6D6D6D" - - width: parent.width - height: parent.height - - header: Kirigami.Heading { - Layout.fillWidth: true - height: 50 - horizontalAlignment: Qt.AlignHCenter - color: headerTextColor - font.weight: Font.Medium - font.pointSize: 12 - text: qsTr("Pick your user name and credentials to login and perform admin tasks") - } - - ColumnLayout { - id: _formLayout - spacing: Kirigami.Units.smallSpacing - - Column { - Layout.fillWidth: true - spacing: Kirigami.Units.smallSpacing - - Label { - width: parent.width - text: qsTr("What is your name?") - } - - TextField { - id: _userNameField - width: parent.width - enabled: config.isEditable("fullName") - placeholderText: qsTr("Your full name") - text: config.fullName - onTextChanged: config.setFullName(text) - - palette.base: _userNameField.text.length - ? positiveFieldColor : unfilledFieldColor - palette.highlight : _userNameField.text.length - ? positiveFieldOutlineColor : unfilledFieldOutlineColor - } - } - - Column { - Layout.fillWidth: true - spacing: Kirigami.Units.smallSpacing - - Label { - width: parent.width - text: qsTr("What name do you want to use to log in?") - } - - TextField { - id: _userLoginField - width: parent.width - enabled: config.isEditable("loginName") - placeholderText: qsTr("Login name") - text: config.loginName - validator: RegularExpressionValidator { regularExpression: /[a-z_][a-z0-9_-]*[$]?$/ } - - onTextChanged: acceptableInput - ? ( _userLoginField.text === "root" - ? forbiddenMessage.visible=true - : ( config.setLoginName(text), - userMessage.visible = false,forbiddenMessage.visible=false ) ) - : ( userMessage.visible = true,console.log("Invalid") ) - - palette.base: _userLoginField.text.length - ? ( acceptableInput - ? ( _userLoginField.text === "root" - ? negativeFieldColor - : positiveFieldColor ) - : negativeFieldColor ) - : unfilledFieldColor - palette.highlight : _userLoginField.text.length - ? ( acceptableInput - ? ( _userLoginField.text === "root" - ? negativeFieldOutlineColor - : positiveFieldOutlineColor ) - : negativeFieldOutlineColor ) - : unfilledFieldOutlineColor - } - - Label { - width: parent.width - text: qsTr("If more than one person will use this computer, you can create multiple accounts after installation.") - font.weight: Font.Thin - font.pointSize: 8 - color: commentsColor - } - } - - Kirigami.InlineMessage { - id: userMessage - Layout.fillWidth: true - showCloseButton: true - visible: false - type: Kirigami.MessageType.Error - text: qsTr("Only lowercase letters, numbers, underscore and hyphen are allowed.") - } - - Kirigami.InlineMessage { - id: forbiddenMessage - Layout.fillWidth: true - showCloseButton: true - visible: false - type: Kirigami.MessageType.Error - text: qsTr("root is not allowed as username.") - } - - Column { - Layout.fillWidth: true - spacing: Kirigami.Units.smallSpacing - - Label { - width: parent.width - text: qsTr("What is the name of this computer?") - } - - TextField { - id: _hostName - width: parent.width - placeholderText: qsTr("Computer name") - text: config.hostname - validator: RegularExpressionValidator { regularExpression: /[a-zA-Z0-9][-a-zA-Z0-9_]+/ } - - onTextChanged: acceptableInput - ? ( _hostName.text === "localhost" - ? forbiddenHost.visible=true - : ( config.setHostName(text), - hostMessage.visible = false,forbiddenHost.visible = false ) ) - : hostMessage.visible = true - - palette.base: _hostName.text.length - ? ( acceptableInput - ? ( _hostName.text === "localhost" - ? negativeFieldColor : positiveFieldColor ) - : negativeFieldColor) - : unfilledFieldColor - palette.highlight : _hostName.text.length - ? ( acceptableInput - ? ( _hostName.text === "localhost" - ? negativeFieldOutlineColor : positiveFieldOutlineColor ) - : negativeFieldOutlineColor) - : unfilledFieldOutlineColor - } - - Label { - width: parent.width - text: qsTr("This name will be used if you make the computer visible to others on a network.") - font.weight: Font.Thin - font.pointSize: 8 - color: commentsColor - } - } - - Kirigami.InlineMessage { - id: hostMessage - Layout.fillWidth: true - showCloseButton: true - visible: false - type: Kirigami.MessageType.Error - text: qsTr("Only letters, numbers, underscore and hyphen are allowed, minimal of two characters.") - } - - Kirigami.InlineMessage { - id: forbiddenHost - Layout.fillWidth: true - showCloseButton: true - visible: false - type: Kirigami.MessageType.Error - text: qsTr("localhost is not allowed as hostname.") - } - - Column { - Layout.fillWidth: true - spacing: Kirigami.Units.smallSpacing - - Label { - width: parent.width - text: qsTr("Choose a password to keep your account safe.") - } - - Row { - width: parent.width - spacing: 20 - - TextField { - id: _passwordField - width: parent.width / 2 - 10 - placeholderText: qsTr("Password") - text: config.userPassword - onTextChanged: config.setUserPassword(text) - - palette.base: _passwordField.text.length - ? positiveFieldColor : unfilledFieldColor - palette.highlight : _passwordField.text.length - ? positiveFieldOutlineColor : unfilledFieldOutlineColor - - echoMode: TextInput.Password - passwordMaskDelay: 300 - inputMethodHints: Qt.ImhNoAutoUppercase - } - - TextField { - id: _verificationPasswordField - width: parent.width / 2 - 10 - placeholderText: qsTr("Repeat password") - text: config.userPasswordSecondary - - onTextChanged: _passwordField.text === _verificationPasswordField.text - ? ( config.setUserPasswordSecondary(text), - passMessage.visible = false, - validityMessage.visible = true ) - : ( passMessage.visible = true, - validityMessage.visible = false ) - - palette.base: _verificationPasswordField.text.length - ? ( _passwordField.text === _verificationPasswordField.text - ? positiveFieldColor : negativeFieldColor ) - : unfilledFieldColor - palette.highlight : _verificationPasswordField.text.length - ? ( _passwordField.text === _verificationPasswordField.text - ? positiveFieldOutlineColor : negativeFieldOutlineColor ) - : unfilledFieldOutlineColor - - echoMode: TextInput.Password - passwordMaskDelay: 300 - inputMethodHints: Qt.ImhNoAutoUppercase - } - } - - Label { - width: parent.width - text: qsTr("Enter the same password twice, so that it can be checked for typing errors. A good password will contain a mixture of letters, numbers and punctuation, should be at least eight characters long, and should be changed at regular intervals.") - font.weight: Font.Thin - font.pointSize: 8 - wrapMode: Text.WordWrap - color: commentsColor - } - } - - Kirigami.InlineMessage { - id: passMessage - Layout.fillWidth: true - showCloseButton: true - visible: false - type: Kirigami.MessageType.Error - text: config.userPasswordMessage - } - - Kirigami.InlineMessage { - id: validityMessage - Layout.fillWidth: true - showCloseButton: true - visible: false - type: config.userPasswordValidity - ? ( config.requireStrongPasswords - ? Kirigami.MessageType.Error : Kirigami.MessageType.Warning ) - : Kirigami.MessageType.Positive - text: config.userPasswordMessage - } - - CheckBox { - id: root - visible: config.writeRootPassword - text: qsTr("Reuse user password as root password") - checked: config.reuseUserPasswordForRoot - onCheckedChanged: config.setReuseUserPasswordForRoot(checked) - } - - Label { - visible: root.checked - width: parent.width - text: qsTr("Use the same password for the administrator account.") - font.weight: Font.Thin - font.pointSize: 8 - color: commentsColor - } - - Column { - visible: ! root.checked - Layout.fillWidth: true - spacing: Kirigami.Units.smallSpacing - - Label { - width: parent.width - text: qsTr("Choose a root password to keep your account safe.") - } - - Row { - width: parent.width - spacing: 20 - - TextField { - id: _rootPasswordField - width: parent.width / 2 -10 - placeholderText: qsTr("Root password") - text: config.rootPassword - - onTextChanged: config.setRootPassword(text) - - palette.base: _rootPasswordField.text.length - ? positiveFieldColor : unfilledFieldColor - palette.highlight : _rootPasswordField.text.length - ? positiveFieldOutlineColor : unfilledFieldOutlineColor - - echoMode: TextInput.Password - passwordMaskDelay: 300 - inputMethodHints: Qt.ImhNoAutoUppercase - } - - TextField { - id: _verificationRootPasswordField - width: parent.width / 2 -10 - placeholderText: qsTr("Repeat root password") - text: config.rootPasswordSecondary - - onTextChanged: _rootPasswordField.text === _verificationRootPasswordField.text - ? ( config.setRootPasswordSecondary(text), - rootPassMessage.visible = false,rootValidityMessage.visible = true ) - : ( rootPassMessage.visible = true,rootValidityMessage.visible = false ) - - palette.base: _verificationRootPasswordField.text.length - ? ( _rootPasswordField.text === _verificationRootPasswordField.text - ? positiveFieldColor : negativeFieldColor) - : unfilledFieldColor - palette.highlight : _verificationRootPasswordField.text.length - ? ( _rootPasswordField.text === _verificationRootPasswordField.text - ? positiveFieldOutlineColor : negativeFieldOutlineColor) - : unfilledFieldOutlineColor - - echoMode: TextInput.Password - passwordMaskDelay: 300 - inputMethodHints: Qt.ImhNoAutoUppercase - } - } - - Label { - visible: ! root.checked - width: parent.width - text: qsTr("Enter the same password twice, so that it can be checked for typing errors.") - font.weight: Font.Thin - font.pointSize: 8 - color: commentsColor - } - } - - Kirigami.InlineMessage { - id: rootPassMessage - Layout.fillWidth: true - showCloseButton: true - visible: false - type: Kirigami.MessageType.Error - text: config.rootPasswordMessage - } - - Kirigami.InlineMessage { - id: rootValidityMessage - Layout.fillWidth: true - showCloseButton: true - visible: false - type: config.rootPasswordValidity - ? ( config.requireStrongPasswords - ? Kirigami.MessageType.Error : Kirigami.MessageType.Warning ) - : Kirigami.MessageType.Positive - text: config.rootPasswordMessage - } - - CheckBox { - Layout.alignment: Qt.AlignCenter - text: qsTr("Log in automatically without asking for the password") - checked: config.doAutoLogin - onCheckedChanged: config.setAutoLogin(checked) - } - - CheckBox { - visible: config.permitWeakPasswords - Layout.alignment: Qt.AlignCenter - text: qsTr("Validate passwords quality") - checked: config.requireStrongPasswords - onCheckedChanged: config.setRequireStrongPasswords(checked), - rootPassMessage.visible = false - } - - Label { - visible: config.permitWeakPasswords - width: parent.width - Layout.alignment: Qt.AlignCenter - text: qsTr("When this box is checked, password-strength checking is done and you will not be able to use a weak password.") - font.weight: Font.Thin - font.pointSize: 8 - color: commentsColor - } - } -} diff --git a/src/modules/usersq/usersq.qrc b/src/modules/usersq/usersq.qrc deleted file mode 100644 index 8c1c4f9862..0000000000 --- a/src/modules/usersq/usersq.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - usersq.qml - - diff --git a/src/modules/welcomeq/CMakeLists.txt b/src/modules/welcomeq/CMakeLists.txt deleted file mode 100644 index 98b5a16739..0000000000 --- a/src/modules/welcomeq/CMakeLists.txt +++ /dev/null @@ -1,48 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# - -# This is a re-write of the welcome module using QML view steps -# instead of widgets. - -if(NOT WITH_QML) - calamares_skip_module( "welcomeq (QML is not supported in this build)" ) - return() -endif() - -set(_welcome ${CMAKE_CURRENT_SOURCE_DIR}/../welcome) - -include_directories(${_welcome}) - -# DUPLICATED WITH WELCOME MODULE -find_package(${qtname} ${QT_VERSION} CONFIG REQUIRED DBus Network) - -find_package(LIBPARTED) -if(LIBPARTED_FOUND) - set(PARTMAN_SRC ${_welcome}/checker/partman_devices.c) - set(CHECKER_LINK_LIBRARIES ${LIBPARTED_LIBRARY}) -else() - set(PARTMAN_SRC) - set(CHECKER_LINK_LIBRARIES) - add_definitions(-DWITHOUT_LIBPARTED) -endif() - -set(CHECKER_SOURCES ${_welcome}/checker/GeneralRequirements.cpp ${PARTMAN_SRC}) - -calamares_add_plugin(welcomeq - TYPE viewmodule - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - ${CHECKER_SOURCES} - WelcomeQmlViewStep.cpp - ${_welcome}/Config.cpp - RESOURCES - welcomeq${QT_VERSION_SUFFIX}.qrc - LINK_PRIVATE_LIBRARIES - ${CHECKER_LINK_LIBRARIES} - ${qtname}::DBus - ${qtname}::Network - SHARED_LIB -) diff --git a/src/modules/welcomeq/Recommended.qml b/src/modules/welcomeq/Recommended.qml deleted file mode 100644 index 1afc60950c..0000000000 --- a/src/modules/welcomeq/Recommended.qml +++ /dev/null @@ -1,91 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 Anke Boersma - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -/* THIS COMPONENT IS UNUSED -- from the default welcomeq.qml at least */ - -import io.calamares.core 1.0 -import io.calamares.ui 1.0 - -import QtQuick 2.7 -import QtQuick.Controls 2.2 -import QtQuick.Layouts 1.3 -import org.kde.kirigami 2.7 as Kirigami - -Rectangle { - focus: true - Kirigami.Theme.backgroundColor: Kirigami.Theme.backgroundColor - anchors.fill: parent - anchors.topMargin: 50 - - TextArea { - id: recommended - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: parent.top - anchors.topMargin: 1 - horizontalAlignment: TextEdit.AlignHCenter - width: 640 - font.pointSize: 11 - textFormat: Text.RichText - antialiasing: true - activeFocusOnPress: false - wrapMode: Text.WordWrap - - text: qsTr("

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

    ").arg(Branding.string(Branding.VersionedName)) - } - - Rectangle { - width: 640 - height: 360 - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: recommended.bottom - anchors.topMargin: 5 - - Component { - id: requirementsDelegate - - Item { - width: 640 - height: 35 - - Column { - anchors.centerIn: parent - - Rectangle { - implicitWidth: 640 - implicitHeight: 35 - border.color: satisfied ? "#228b22" : "#ffa411" - color: satisfied ? "#f0fff0" : "#ffefd5" - - Image { - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - anchors.margins: 20 - source: satisfied ? "qrc:/data/images/yes.svgz" : "qrc:/data/images/information.svgz" - } - - Text { - text: satisfied ? details : negatedText - anchors.centerIn: parent - font.pointSize: 11 - } - } - } - } - } - - ListView { - anchors.fill: parent - spacing: 5 - model: config.requirementsModel - delegate: requirementsDelegate - } - } -} diff --git a/src/modules/welcomeq/Requirements.qml b/src/modules/welcomeq/Requirements.qml deleted file mode 100644 index 949ac32c0a..0000000000 --- a/src/modules/welcomeq/Requirements.qml +++ /dev/null @@ -1,108 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 - 2022 Anke Boersma - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * 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.7 -import QtQuick.Controls 2.2 -import QtQuick.Layouts 1.3 -import org.kde.kirigami 2.7 as Kirigami - -Rectangle { - focus: true - Kirigami.Theme.backgroundColor: Kirigami.Theme.backgroundColor - anchors.fill: parent - anchors.topMargin: 60 - - TextArea { - id: required - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: parent.top - horizontalAlignment: TextEdit.AlignHCenter - width: parent.width - font.pointSize: 11 - textFormat: Text.RichText - antialiasing: true - activeFocusOnPress: false - wrapMode: Text.WordWrap - - property var requirementsText: qsTr("

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

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

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

    ").arg(Branding.string(Branding.VersionedName)) - - text: config.requirementsModel.satisfiedMandatory ? recommendationsText : requirementsText - } - - Rectangle { - width: parent.width * 0.8 - height: parent.height * 0.6 - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: required.bottom - anchors.topMargin: 5 - - Component { - id: requirementsDelegate - - Item { - width: parent.width - implicitHeight: message.implicitHeight + 30 - visible: true - - Column { - anchors.centerIn: parent - - Rectangle { - implicitWidth: 640 - implicitHeight: message.implicitHeight + 30 - // Colors and images based on the two satisfied-bools: - // - if satisfied, then green / ok - // - otherwise if mandatory, then red / stop - // - otherwise, then yellow / warning - border.color: satisfied ? "#228b22" : (mandatory ? "#ff0000" : "#ffa411") - color: satisfied ? "#f0fff0" : (mandatory ? "#ffc0cb" : "#ffefd5") - - Image { - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - anchors.margins: 20 - source: satisfied ? "qrc:/data/images/yes.svgz" : (mandatory ? "qrc:/data/images/no.svgz" : "qrc:/data/images/information.svgz") - } - - Text { - id: message - text: satisfied ? details : negatedText - anchors.centerIn: parent - font.pointSize: 11 - } - } - } - } - } - - ListView { - id: requirementsList - anchors.fill: parent - spacing: 5 - clip: true - // This uses the unfiltered model, so that all requirements are - // shown. You could use *unsatisfiedRequirements* to get the - // filtered model so that only unsatisfied requirements are ever shown. - //model: config.unsatisfiedRequirements - model: config.requirementsModel - delegate: requirementsDelegate - ScrollBar.vertical: ScrollBar { - active: true - } - } - } -} - diff --git a/src/modules/welcomeq/WelcomeQmlViewStep.cpp b/src/modules/welcomeq/WelcomeQmlViewStep.cpp deleted file mode 100644 index 7bd866b419..0000000000 --- a/src/modules/welcomeq/WelcomeQmlViewStep.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "WelcomeQmlViewStep.h" - -#include "checker/GeneralRequirements.h" - -#include "locale/TranslationsModel.h" -#include "utils/Dirs.h" -#include "utils/Logger.h" -#include "utils/Variant.h" - -#include "Branding.h" -#include "modulesystem/ModuleManager.h" -#include "utils/Yaml.h" - -CALAMARES_PLUGIN_FACTORY_DEFINITION( WelcomeQmlViewStepFactory, registerPlugin< WelcomeQmlViewStep >(); ) - -WelcomeQmlViewStep::WelcomeQmlViewStep( QObject* parent ) - : Calamares::QmlViewStep( parent ) - , m_config( new Config( this ) ) -{ - connect( Calamares::ModuleManager::instance(), - &Calamares::ModuleManager::requirementsComplete, - this, - &WelcomeQmlViewStep::nextStatusChanged ); -} - - -QString -WelcomeQmlViewStep::prettyName() const -{ - return tr( "Welcome", "@title" ); -} - -bool -WelcomeQmlViewStep::isNextEnabled() const -{ - return m_config->requirementsModel()->satisfiedMandatory(); -} - -bool -WelcomeQmlViewStep::isBackEnabled() const -{ - // TODO: should return true (it's weird that you are not allowed to have welcome *after* anything - return false; -} - - -bool -WelcomeQmlViewStep::isAtBeginning() const -{ - return true; -} - - -bool -WelcomeQmlViewStep::isAtEnd() const -{ - return true; -} - - -Calamares::JobList -WelcomeQmlViewStep::jobs() const -{ - return Calamares::JobList(); -} - -void -WelcomeQmlViewStep::setConfigurationMap( const QVariantMap& configurationMap ) -{ - m_config->setConfigurationMap( configurationMap ); - Calamares::QmlViewStep::setConfigurationMap( configurationMap ); // call parent implementation last -} - -Calamares::RequirementsList -WelcomeQmlViewStep::checkRequirements() -{ - return m_config->checkRequirements(); -} - -QObject* -WelcomeQmlViewStep::getConfig() -{ - return m_config; -} diff --git a/src/modules/welcomeq/WelcomeQmlViewStep.h b/src/modules/welcomeq/WelcomeQmlViewStep.h deleted file mode 100644 index 1839c7c9b5..0000000000 --- a/src/modules/welcomeq/WelcomeQmlViewStep.h +++ /dev/null @@ -1,70 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2019-2020 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef WELCOME_QMLVIEWSTEP_H -#define WELCOME_QMLVIEWSTEP_H - -#include "Config.h" - -#include "modulesystem/Requirement.h" -#include "utils/PluginFactory.h" -#include "viewpages/QmlViewStep.h" - -#include - -#include -#include - -namespace Calamares -{ -namespace GeoIP -{ -class Handler; -} // namespace GeoIP -} // namespace Calamares - - -// TODO: refactor and move what makes sense to base class -class PLUGINDLLEXPORT WelcomeQmlViewStep : public Calamares::QmlViewStep -{ - Q_OBJECT - -public: - explicit WelcomeQmlViewStep( 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 setConfigurationMap( const QVariantMap& configurationMap ) override; - - /** @brief Sets the country that Calamares is running in. - * - * This (ideally) sets up language and locale settings that are right for - * the given 2-letter country code. Uses the handler's information (if - * given) for error reporting. - */ - void setCountry( const QString&, Calamares::GeoIP::Handler* handler ); - - Calamares::RequirementsList checkRequirements() override; - QObject* getConfig() override; - -private: - Config* m_config; -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( WelcomeQmlViewStepFactory ) - -#endif // WELCOME_QMLVIEWSTEP_H diff --git a/src/modules/welcomeq/img/chevron-left-solid.svg b/src/modules/welcomeq/img/chevron-left-solid.svg deleted file mode 100644 index 41061c287f..0000000000 --- a/src/modules/welcomeq/img/chevron-left-solid.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/modules/welcomeq/img/chevron-left-solid.svg.license b/src/modules/welcomeq/img/chevron-left-solid.svg.license deleted file mode 100644 index 5f43e650d3..0000000000 --- a/src/modules/welcomeq/img/chevron-left-solid.svg.license +++ /dev/null @@ -1,2 +0,0 @@ -SPDX-FileCopyrightText: 2020 demmm -SPDX-License-Identifier: GPL-3.0-or-later diff --git a/src/modules/welcomeq/img/language-icon-48px.png b/src/modules/welcomeq/img/language-icon-48px.png deleted file mode 100644 index 4012a4bee05f8f3e38a6f9efe0ff705361b094a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2315 zcma)8XHXN`5>5hGKoA8(HDII$2wg*{N&->^Bs3|ZM2dvuL8N(+qF$sU0V7?J0SN*c z+NC6*NW0V#5CuXJFd&8|oq#X?et+JN-92;8w>$HFyE}7|>}<^i`6c-Q0Dz#y4U_{n zYW%TNC%E1jw4cZgr-?UQ!vFw*^M4HZiTQxTy#$lcE+o@XoHr?u5F+ash{pjmG}X2A z)HSt@iJ6^Tg!CW8Ey5jAgm)+oaLte4gOfE248=tdLhpvjn%>g=PyPHA001Nv=;%Un zv9U(_67X>EKQMSCo(KQ}Fpg$w2*Cfo1jMr^`_l6@L{H4d6nzM7&-K#zG9D&@RS3Scl&o1+V)JN(E4>uw?MZE6BE*=HY%~YImW&wHRg~ia3 znSxhuO>K(^tJ>!v7_TOAck(mgka6X%!Uv5h%4yILI&$DHZe*}BFQOaDLTZosmA%Hl zRH3!mQVu%1vUhsM5bVk~>ULv$iG~Nca97G_>%9UG*jh?UfSxX_enPcwTA{me=7L%M zM6je5UFQ58ZOVV$+XRvf8^?>hn{1uQan#W!z4Jr(LgDNdCU%TqbCWjKUool&h1` z<}~Vx=kQG^cpe<^H#9qj_@a39tO_kFo`AsdV_>yoieR1$wKvTYA7_bLbxxF=a)**m zol>~Rr|*oNxd*T@of;dNlPhNj6U$gg)g?C8-}D7RR3oiUmI4%O=yGYt43}(P)ZOmD@J8sY&m_ z+O*;6#102HH{=Rv;T0Iv9A{_}$Ug~s0YMP7ayci3r0rT-T5u$iW7(!MuQlHL#l=14 z378Z>ir7G-X$_B#mWD?}SgC@^et!i4$@uH`*)^i*<;JhU^C6A5rx`ISRI0)~POO=U zt84BTc6cCxK%r7$xyG>!mnx?~JU%BrKE4iWloW^SdzQoup;TAHlTc77baR!d&*dSr zbxRcex$3rJcZLkbJOg5(BYD)tS8x(lK9bbycfN%QZwz5(&CSg{$|A&`@F}KeS{4JJ*T92lqpiiyE77PUi1>M^oTx?+$Rj+K3{clu_EL*!U?~YgZ zHsB{qOG{CyX0Nt(cm0oeqoboyC=>>xnLkibWa0`t8HUVst#VQY3kW6hWOSRN(R_3| z-MuMP{_^2irE~4Q6(@iw`Xz&5Bz84UnorfURh-h-nIxhZxxXpj63+f`r}iBGV=Y<) zLRwT*R5;BH$j}46b4e9b_Zpw*AL8!yVH6ap-)RTNc#c!m{=F|AN;?o;kl23xCTU~97jgGF> zTR!7SOG_)EQh6U<8xO7ETrVh?xN7Jc_Di)jtdKRgx?b9sve8Wm@-hKjW{HJ{Sjm?7O* z4FGX#$sS_-puZ`MB`zc5Kai*E=;+x0u`n<XUsr~wKG1S7#tN1k)MuB_e#Q--V-P5J@ zpjA~>r~T!)RkeHsRvy?nyb@vD-H4fFHa*4 z28V}*O-)TDCQZPgPv?XZH=^lNtx>n8LK=T_W%B}EjazIVibrBkYa7hOS`UIykL;8l z4YB6A1GJ$Zv3iCPz5SzaV`D>T_R@s>xE#J6iWPV(vUdsV^LI^3=EJz&^`)hy7v<&t zU)FYGfm6K4$>ILUi=Z<+gQ>?L8NTowPn_ZF>4G1aX2RxYupXQbDIo zwlYVoz14^kdxq;)=S^P&T+onBIflsNEMhsXF1N{=Xwm%qtl3}hJE81wB(vs2Pf5_ycTi;$1eNWOiT2VcN$`F4Os z0N^;y$=>MjU=6VDUst2&wHP?g(8q{{jm-KtKQh diff --git a/src/modules/welcomeq/img/language-icon-48px.png.license b/src/modules/welcomeq/img/language-icon-48px.png.license deleted file mode 100644 index bc39975aea..0000000000 --- a/src/modules/welcomeq/img/language-icon-48px.png.license +++ /dev/null @@ -1,2 +0,0 @@ -SPDX-FileCopyrightText: 2011 Farhat Datta and Onur Mustak Cobanli, http://www.languageicon.org/ -SPDX-License-Identifier: GPL-3.0-or-later diff --git a/src/modules/welcomeq/img/squid.png b/src/modules/welcomeq/img/squid.png deleted file mode 100644 index 452e4450c56c10cda33dcc9c5d03753ace458862..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8313 zcmd6NXIE3*^Y%$0gd#1J04hx>q7XU=Lg*m9b1NOBD!qt82&ggiqDZeQRRmO|6RLn9 zMGz2a2I&Zf8X(|5{$4*H;K^E9XU~;6vu9s3d(LDhv8Kkl=jeIp0RT9sucu`W03hlR z1i)d`i(O!uJM{t$($KerQ(qBqH#}9Q^Vj~7d2f!uynjDv`1ix(nX#3V-}C>?dEr>@ z9|$!h22gGzR|N60?cBbERn-W|)m>5b0xUnCtN}x_aN`)U{L+lvfVvw}8i?sbxdG5r z=RN=~*p&ie(ZUHp`0oK{lTu>?7TmQ~3%X{29gG)as^@#xk1P zMyU$VorzFC*;*i>rF!Atlge}tOT z7p4@tOPo#K-Dw{Xgw;z|CpfNB0j4IG$I36>DYFusq7C^2M!pHEtm#k$^8};a)NSHc z<3fqFg9=R&`+(32Jm1m}0#@wi885oE^Y zs-GbIh2|QjWEs`qetUrT&MgrZQ8z%qoSHB4e}8vP{W;=`S)w=NDs}B-`Fm7A;B6)x z!Ep-P-uOFj$R_tdc6u@3;h$|KY0OGl%+B~y$Fk6PToXX-E(mOQ*; z3KRjipn#phT@tg=H}k%aJ=WSz0YT9UM6T}d&|(%s`xof1Eg%aWl>#CgN>b5LXfZnh zEf1>yhf;OPdTLa(A4=rMsQ=i)stb>Zy8)`wfu!bRHbUO;Wd+w$kL|eNp27m+Jn85k zh~~{|e>dwFbd5O+?MF4xxAzyr`|L2{dq#^+H3hwC&3N!&#W8&UBvR?`=tDx1LeyT~ ziyio9H?X}XY(d6?IbuKofwv0dkEwB7UTt;kr7F#t=P!@hFyf@M(7pfspEl$dBi4J+ z_Cc@X82S0Xx`6c&1ih=1{m|>tjQr>{UvMlUYRvtS8`$68Dfr ztc2G0ELmsq;HC6jlgLDJZ=*g87BOyXbl z&7N%?P3WlBgb)=)vV{GMq6=)^g!J(Bz-;uJB&wP2#|_!&DI#qrYn05lglvEtoq*4w zbJL~>7Gyj7%4c8h16*|M46$C{*$9Q7-roW51ur0__uK2SGk|p@xiWG^F0lU#Qsw0H zTebQ%=C+s_+rK|@K>e&#ZP0jh%sQ!vU7ZzenAP;xr%fB&x@nPVMT%bx88R(@7=hBJ zI)GGbhM1*Tk{I4Of!zQpk#gabU=qVuU#dXI?tS|(C27UM&~C!cwGTcn~baLpFHIJ?at$fHZ00loS`X*@du6HP6Z1dXzxbkS(P8i~vMW z43mWxA^PcgDix>te*EnqeFI12TBZBvGy7OI9knJZ@Cd>)4(-NVuVU2M46&a8bK`1P zumdr9rj3~ba;gX#!1pXmcDxcg%76`p! za&w0dqo62>VSOeJ<^tnJ<7_`e-|=IH54+XCEClKn_xR_&RLdvmyQ>&peTsUb`YH^d zF>O8tgQ$Upc_l%mCC_kb7F!OK*(CLDF}6ZD|4aPSA~?+ zN6p5e_Uu~f92$`E0{mc4CW_(J-`ZiUpRnE`0V%tePh&ey_%e zTDv{fEwH1xpiex)efQG%Fu(b$w=o>R>p!ixRw1u-Wh5T@!G=2x_O=Yq> zjj9x)uQJ^~uS@hRFkvQUaCscRwV@htMPdc|p)+$~ zMk1s`%Zne3J8I;=??JhNQI3yvqE%~ed!LaXUNPalbNtV^)+7qhtk^{xvPGRlL|jdt zx$vil$|gRa+fr%g;x&9XLF>UbF@yQ{kAG+z(o|`uVt3kSjGBG(y5ZB;n6?I>o|-Jh ze)Mr-2Gz8#2VXVxDe?})jIsZ67N@BkkTukQ0<_*OwPGiiW!a*1*X%XzfldYbipFYe zyJV5vuXI+D3}*`&6bHZy`o#f=?zdHA?||V?jhs(3gK8dJgA68_fD)HzZh@$hXL_&BCRNxAFO3D=%pc&S3bTYUiYC#$Qm4!=kKN0%+^&zvqoF>IhOLCy!q*ib(Hxv-gVagp#D2OQqX_$|Ktrc$Hld(nBhT-MAR~GM55%wkT2RVrm7e3-9zggJS2S zs3Dn3wYb$w&F2nkl6I%%##}DY_(c;-2%3uRFNZ`IXjda45o zQ_MiSDd{T_&BV4Kx?M8%>*$1bpz7A4Z8hchA%mv2=aILK$OcGWIqdp#8d~V6c+*?W zNuL8B$<&ACGX{4943fdqta$v5?2>3HSgZA}s;Ik*aSR#61L0?jsi+tUR60~}6<&UY z=cAIz_PC;=Z)rC%Rtgc6*8MLSbed-DW6JEEK$qFSJX_xw`S5kU+LM#5^Rp$rtk~I&9x9%Hf`C zKHO;5H{oFiv6PoQ)8mg1!+;X0V_j!@M&J9xOm1bv^Ne4>ELm7F`gWxTXT8`p`-L&F z4@}rT#)OWD1w zYAdSgOkfNF;Rie02bCkZW}`o-+XFG4($OEDo=SgU!SgR%-O?WuEHK7n7@Y!m6e)^R zl_t>z54i6x%N5>&?$M(f7?Ih)Cu>NK1kHQ|O-+D83NQZSpuXEW%HK_L%Ets`Q4KJ> zM|*LWZJ;r5+mDb zzjB}!pTTrNtM1ksIVeGFs=-Sp)ZxB>yzlgR{XNzuP>qlY_Qu}1g1 zfuRnCpEvu_=BS*X68oGH!QOa?;c)VHTEQ!C_W2dgoMfQGRZ}R9*yJdYT#S+G}_j~N{uZ66YV&j3^7&NY9@>{D45>iICh^vBslQ&mzm zHm%ho|J|vY{5A#Gw$~Avhj%`^R?sn`teT^QKruqpP6-7I`;!jmD0W?4LgdrK7UltA zVek!;nlbFINc&dPHFgpNz4b?E;V=@k`d;mY?3B;LB9%W&3q8z0uInagyO=z%O%wGN z*`d_iMWASl5^1qLJv0<@2d)3|U>17#<=k0mRH!b$(uS4iJb~lxPCEMCp+?pN?j~pK zy=Lk0T^*X72Q=$Z82Yjo8aMoYt~v}}n~(1N?>1Gi-28FKexP<@Shn(JqCzp8s5mrR zD^%lY0HTc{n_gd3lFglxr>z^(*LEiT! z={Pcj{u&w?yUfqErskfE_ghSzbo+q^)G{U7%Qa2&Tf|e|D0h}=hA#}1S$!T&7l2M# z9AaC4?s`UXdG_f4;yaO8cJ~kx*BtTpT^MydrN_0T>h*0#Epr>17}2EFvpudARXZ^b zi+>2_S39MTOP+_cIwT*%*al7N;QL&Ei9UJzo#c3C7ZTYZGcPB;%@|Bp3jV_{EYii@ zwbO}WR5|+P2R_2kD?Tky+nm}pb--L5r{8f2{(Gtzvh%7@=FRZD%sSuF8Xt}P>?DWI z1;ojAZzn}%Xs{ru#eqWkiHklR*5Y#RZy_CTWaek@ohl!zI+l=IM@pG@-s_^sL`}sT zK}^CgjL>FZW$wLJA)S`RJIMr+x$Ym$FuR8Oa=v`&isZhS)TGyjl95Tw%E~H>2LTJY ziwn_^hUKP>$S;%gYP8ECHCz{WWP02F+h0}FvVT1Oay(9P|4)>2)V*`<$er+WjpwiN z9^`aM5*}Apw+>BmgB)o=-)kXGk#BE^r1i_^zEhZfGvPh5&oXhzEg`TmA@ zVw$wITj#G8XnXqxtUcV?__g_E1RRU#O+HbEE%X(CS?OFFq-o?m0Yi`?1fpAa ziw5w#b@0NSwr6wmDrNi)!5%x-OBqbkV~HzreVlQZ6mPFkuDl=_&%n^OTpE3{D)LSH z?~Wjw?#1iK+^4?&Kmz2OH%CI&@S4!^%Uf0LCSQ(!(BSWrm|3q~sfJ8gia*_FVamjq zR#}^gvKNYeICn=4iDR9Y00Kw1{B*PotfWfMvZ>!DEGttb%8eixKX&3q5Qsby_*Yse zjmA~92pG!g_N$W|W5;^Gj*BP)F1tRYBlono^HZIzZU*mi+>RKC*W+BGC|>DnoI6s= zrM>6xKVHG{D=>VWX|Mg=oq>f?cPcrkiTrI>U#+yvp#mD@AlpL=#GOH&dTG9{JN`kT z{22qObiw^Q>EesZFw^<_SxU@?Zb_5h>HwZ?N@&a_%u(j8Djip_eW57*(5?3qlPaf? z@=ng|pI%fJoIq8d#K!uevJr4KO)dNh8?BQ%seQU9l_s4=r3Ccv}wwwcDK^VDsh7)TIbnpFA z&aMWGzdd%l+jM)k`HP1%^?VAp+mZX)Tr6}pIzlx$X!r+fh!g;H2?(=5HH@C1I0;SW* z>5FfqtPJDz!^vjD)W_<0*bGv~>f`Ho4`^?0RDWpWdcX1G{60d?^INUGTFsdA=`u{W z(Gq8-K)IJ3d1hA=WaG)a=GohmVF!C6))uAqr0efr?`Ac?b#^GFvMlwxxayPRKQ{qv zYiL}+dxOt|fpNx)Tmk_zR`%I8E!C@d!G{$mlt zjy<_3kmy97eTA;su%J;J?A$(ND#Xhll75pLrU3R#Z#`9zl}<2_BnZwtxaab1{hQ*+ zOc3M<)6tz`sJ`?gDWAQoyvkfFIV;F%le(+@T4A4m35bqW!!Qy+*_-RkrM}0?{#E>m*kF;f zi4LpGNKkoGLq`WY&AC|C)PbcM-!9mBCCaJMHQe+X_(I9}z+Z8_R5GPxVdO7Qgjqfa?7b^1l*TKYEJ%=$(VvaeOc>?&6MBk`HS zES&?As$`LIil2Y0?4DF#=B?tc41>XHoX3P)0`^3`RaH3}IB=EKjhxC7aLjq5(_kzs zwy@~|Z3(S{3z@7c3cBhbRuCd!+;);vmR$8EpG;$@e(y(!t>`2wI8ZHOb_E0=yVe-g z@N2wn@O)lIJIXC3^F&A%LwjI%FWv`W+VE+K4J*fpmR* zKisioWA`Mw;}2|DQwC_4jkYKiHp^7Oatxm;=*-P9)XKi%U4IgAHTNOHc>9=T{SktN z!SI~~CfXU9nU$~gv!}r2sDoAtb!u*MG_EuGb5EPEr&DPgYE#$OEjj6vYX|^wJ%UUs z1U|_N*YP)*lZ#!Q{?}ptZi9;3RM8hcHpu-;YCX}o;Qh@<&d}JXvy8Vdy##fzE`(J5 z$P9TVsZst=*(=hM<|g$tF5vWz?ac8*taS}9Uo3%RNXfm#!}RTQ6e<$#TCIvJvKV%C zT1K_E+RRw>DinX%a=Gf;2uhdZx|J>(dtHMx(EBN|>Fr{jP4YsbLK5*;?4l@Ve15NY z1HK+4puU&gRTUQ=59DvD`tGUvxAaB^~* zUg0z=e{Lp`QB;2AgB_Er>mu?3Z~T`-d^Z4~CqoR4sEh@nK2_m_d9p4!Rhp%eA3h37 z`ri1T<;^?Fw_>b@jc=$&=(9zA`V*pC_}2JMxouM+#BZ^M)(gL2ou>}T1 z+U_(vcbbBaW_kju{DOv>-Zg@W3a_&Cae2wlhAxu~yb|Q{#4j>f&p0vKs!ByG4HjEU z{6~Cxuj%9aX`Rni!&3emNSX3FjAFxOOsQ&*(vwp8aYWdTUyHDWmwBsjQU0?yLNhol zw!+J{EkeoN-Myn~*0?9{vBK<;cICp?JU;WLT|bMDC31?9;iH1Tl?(frYqlvZVzVvI zaC!$Wy0@%lzM- z{RxyA?Pvbq)K&S{_JEL9*jt%fAhJuu0*FbN0TyYIR-Tz{t|urG!W)4$-^#C0`K`<<4A8a+j;hh z8wB8jSN!OmZ#RMIm`_@f7r38vB5(Gj*{cCOU6|&%S8p@IEe)pT?;E|U;qxr>Si5NA z9L0#&=0fX?$tFnNhLv0ijbis)XR@UWMP7*~h;3$+?oZ=R1NCy>)y&8L{K?A5bnbiD z=0|5jnOQ~+ft3A$?j%o({=`+|)qB99EE`u_8!$LLd^;5Y3_c9ORW?H)i7&^OYmIFO za{o*)o#eqJblxgukEJP1&tKE*>H=h%A)&fAD-0lsuA+f?{gYbo*^9TIf6bMMKH}#2 zoy?qC1+k?!vXHtiANS-a94PLfE4m$a^5V$L;}SamJ#Ks@<43)1kdyr9lAud&`SZ*; z9IOLrDv_T1z_WQmW9I0~WXgIuX-IN?`bFb&_ejn@!yCP+wuvCwXBKh^2}wl_HBQNN znJAPdThr>U!Hw~x6Uu?CZPN+GKuQq>r*UzrsU7x9X6=)aDfYd-wtJg_$=2c&^1X7U zfptIvn^59~=Kvz_opZfl`p6vn|;kv(0Mi|%Dw|AUResXn39Cqe3@iFD1Brb26B_N>Ka*Kx!EJg z|AZW>U`bB`nNH2qK51#3bbM`|x=wSgQcP^qM74Gs+()H7x=5h8z&lJ+Z1XVBPL&x| zXkLEnN@ -SPDX-License-Identifier: GPL-3.0-or-later diff --git a/src/modules/welcomeq/release_notes.qml b/src/modules/welcomeq/release_notes.qml deleted file mode 100644 index 29ba7c032c..0000000000 --- a/src/modules/welcomeq/release_notes.qml +++ /dev/null @@ -1,94 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 - 2024 Anke Boersma - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -import io.calamares.ui 1.0 - -import QtQuick 2.7 -import QtQuick.Controls 2.2 -import QtQuick.Window 2.2 -import QtQuick.Layouts 1.3 - -Rectangle { - width: parent.width - height: parent.height - focus: true - color: "#f2f2f2" - - Flickable { - id: flick - anchors.fill: parent - contentHeight: 3500 - - ScrollBar.vertical: ScrollBar { - id: fscrollbar - width: 10 - policy: ScrollBar.AlwaysOn - } - - TextArea { - id: intro - x: 130 - y: 8 - width: 640 - font.pointSize: 14 - textFormat: Text.MarkdownText - antialiasing: true - activeFocusOnPress: false - wrapMode: Text.WordWrap - - text: qsTr("### %1 -This an example QML file, showing options in Markdown with Flickable content. - -QML with RichText can use HTML tags, with Markdown it uses the simple Markdown syntax, Flickable content is useful for touchscreens. - -**This is bold text** - -*This is italic text* - -_This is underlined text_ - -> blockquote - -~~This is strikethrough~~ - -Code example: -``` -ls -l /home -``` - -**Lists:** - * Intel CPU systems - * AMD CPU systems - -The vertical scrollbar is adjustable, current width set to 10.").arg(Branding.string(Branding.VersionedName)) - - } - } - - ToolButton { - id: toolButton - x: 19 - y: 29 - width: 105 - height: 48 - text: qsTr("Back") - hoverEnabled: true - onClicked: load.source = "" - - Image { - id: image1 - x: 0 - y: 13 - width: 22 - height: 22 - source: "img/chevron-left-solid.svg" - fillMode: Image.PreserveAspectFit - } - } -} diff --git a/src/modules/welcomeq/welcomeq-qt6.qml b/src/modules/welcomeq/welcomeq-qt6.qml deleted file mode 100644 index 7cc8c64038..0000000000 --- a/src/modules/welcomeq/welcomeq-qt6.qml +++ /dev/null @@ -1,169 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-FileCopyrightText: 2020 Anke Boersma - * 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.10 -import QtQuick.Controls 2.10 -import QtQuick.Layouts 1.3 -import QtQuick.Window 2.3 - -// Qt6 requires unversioned imports and other names -import org.kde.kirigami as Kirigami -import Qt5Compat.GraphicalEffects - - -Page -{ - id: welcome - - header: Item { - width: parent.width - height: parent.height - - Text { - id: welcomeTopText - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: parent.top - horizontalAlignment: Text.AlignHCenter - padding: 20 - // In QML, QString::arg() only takes one argument - text: qsTr("

    Welcome to the %1 %2 installer

    -

    This program will ask you some questions and set up %1 on your computer.

    ").arg(Branding.string(Branding.ProductName)).arg(Branding.string(Branding.Version)) - } - Image { - id: welcomeImage - anchors.centerIn: parent - // imagePath() returns a full pathname, so make it refer to the filesystem - // .. otherwise the path is interpreted relative to the "call site", which - // .. might be the QRC file. - source: "file:/" + Branding.imagePath(Branding.ProductWelcome) - sourceSize.width: width - sourceSize.height: height - fillMode: Image.PreserveAspectFit - } - - Requirements { - visible: !config.requirementsModel.satisfiedRequirements - } - - RowLayout { - id: buttonBar - width: parent.width / 1.5 - height: 64 - - anchors.bottom: parent.bottom - anchors.horizontalCenter: parent.horizontalCenter - - spacing: Kirigami.Units.largeSpacing* 2 - - Button { - Layout.fillWidth: true - text: qsTr("Support") - icon.name: "system-help" - Kirigami.Theme.backgroundColor: Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.4) - Kirigami.Theme.textColor: Kirigami.Theme.textColor - - visible: config.supportUrl !== "" - onClicked: Qt.openUrlExternally(config.supportUrl) - } - - Button { - Layout.fillWidth: true - text: qsTr("Known Issues") - icon.name: "tools-report-bug" - Kirigami.Theme.backgroundColor: Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.4) - Kirigami.Theme.textColor: Kirigami.Theme.textColor - - visible: config.knownIssuesUrl !== "" - onClicked: Qt.openUrlExternally(config.knownIssuesUrl) - } - - Button { - Layout.fillWidth: true - text: qsTr("Release Notes") - icon.name: "folder-text" - Kirigami.Theme.backgroundColor: Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.4) - Kirigami.Theme.textColor: Kirigami.Theme.textColor - - visible: config.releaseNotesUrl !== "" - onClicked: load.source = "release_notes.qml" - //onClicked: load.source = "file:/usr/share/calamares/release_notes.qml" - } - - Button { - Layout.fillWidth: true - text: qsTr("Donate") - icon.name: "taxes-finances" - Kirigami.Theme.backgroundColor: Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.4) - Kirigami.Theme.textColor: Kirigami.Theme.textColor - - visible: config.donateUrl !== "" - onClicked: Qt.openUrlExternally(config.donateUrl) - } - } - - RowLayout { - id: languageBar - width: parent.width /1.2 - height: 48 - - anchors.bottom: parent.bottom - anchors.bottomMargin: parent.height /7 - anchors.horizontalCenter: parent.horizontalCenter - spacing: Kirigami.Units.largeSpacing* 4 - - Rectangle { - width: parent.width - Layout.fillWidth: true - focus: true - - Loader { - id: imLoader - - Component { - id: icon - Kirigami.Icon { - source: config.languageIcon - height: 48 - width: 48 - } - } - - Component { - id: image - Image { - height: 48 - fillMode: Image.PreserveAspectFit - source: "img/language-icon-48px.png" - } - } - - sourceComponent: (config.languageIcon != "") ? icon : image - } - - ComboBox { - id: languages - anchors.left: imLoader.right - width: languageBar.width /1.1 - textRole: "label" - currentIndex: config.localeIndex - model: config.languagesModel - onCurrentIndexChanged: config.localeIndex = currentIndex - } - } - } - - Loader { - id:load - anchors.fill: parent - } - } -} diff --git a/src/modules/welcomeq/welcomeq-qt6.qrc b/src/modules/welcomeq/welcomeq-qt6.qrc deleted file mode 100644 index a6a211f038..0000000000 --- a/src/modules/welcomeq/welcomeq-qt6.qrc +++ /dev/null @@ -1,11 +0,0 @@ - - - welcomeq-qt6.qml - release_notes.qml - Recommended.qml - Requirements.qml - img/squid.png - img/chevron-left-solid.svg - img/language-icon-48px.png - - diff --git a/src/modules/welcomeq/welcomeq.conf b/src/modules/welcomeq/welcomeq.conf deleted file mode 100644 index 2efc514732..0000000000 --- a/src/modules/welcomeq/welcomeq.conf +++ /dev/null @@ -1,40 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# Configuration for the welcomeq module. -# -# The configuration for welcomeq is exactly the same -# as the welcome module, with the one exception of -# *qmlSearch* which governs QML loading. -# -# No documentation is given here: look in the welcome module. ---- -# Setting for QML loading: use QRC, branding, or both sources of files -qmlSearch: both - -# Everythin below here is documented in `welcome.conf` -showSupportUrl: true -showKnownIssuesUrl: true -showReleaseNotesUrl: true -# showDonateUrl: https://kde.org/community/donations/ - -requirements: - requiredStorage: 5.5 - requiredRam: 1.0 - internetCheckUrl: http://google.com - check: - - storage - - ram - - power - - internet - - root - - screen - required: - - ram - -geoip: - style: "none" - url: "https://geoip.kde.org/v1/ubiquity" # extended XML format - selector: "CountryCode" # blank uses default, which is wrong - -#languageIcon: languages diff --git a/src/modules/welcomeq/welcomeq.qml b/src/modules/welcomeq/welcomeq.qml deleted file mode 100644 index d3150cf949..0000000000 --- a/src/modules/welcomeq/welcomeq.qml +++ /dev/null @@ -1,169 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2020 Adriaan de Groot - * SPDX-FileCopyrightText: 2020 Anke Boersma - * 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.10 -import QtQuick.Controls 2.10 -import QtQuick.Layouts 1.3 -import QtQuick.Window 2.3 - -// Qt5 requires versioned imports -// -import org.kde.kirigami 2.7 as Kirigami -import QtGraphicalEffects 1.0 - -Page -{ - id: welcome - - header: Item { - width: parent.width - height: parent.height - - Text { - id: welcomeTopText - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: parent.top - horizontalAlignment: Text.AlignHCenter - padding: 20 - // In QML, QString::arg() only takes one argument - text: qsTr("

    Welcome to the %1 %2 installer

    -

    This program will ask you some questions and set up %1 on your computer.

    ").arg(Branding.string(Branding.ProductName)).arg(Branding.string(Branding.Version)) - } - Image { - id: welcomeImage - anchors.centerIn: parent - // imagePath() returns a full pathname, so make it refer to the filesystem - // .. otherwise the path is interpreted relative to the "call site", which - // .. might be the QRC file. - source: "file:/" + Branding.imagePath(Branding.ProductWelcome) - sourceSize.width: width - sourceSize.height: height - fillMode: Image.PreserveAspectFit - } - - Requirements { - visible: !config.requirementsModel.satisfiedRequirements - } - - RowLayout { - id: buttonBar - width: parent.width / 1.5 - height: 64 - - anchors.bottom: parent.bottom - anchors.horizontalCenter: parent.horizontalCenter - - spacing: Kirigami.Units.largeSpacing* 2 - - Button { - Layout.fillWidth: true - text: qsTr("Support") - icon.name: "system-help" - Kirigami.Theme.backgroundColor: Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.4) - Kirigami.Theme.textColor: Kirigami.Theme.textColor - - visible: config.supportUrl !== "" - onClicked: Qt.openUrlExternally(config.supportUrl) - } - - Button { - Layout.fillWidth: true - text: qsTr("Known Issues") - icon.name: "tools-report-bug" - Kirigami.Theme.backgroundColor: Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.4) - Kirigami.Theme.textColor: Kirigami.Theme.textColor - - visible: config.knownIssuesUrl !== "" - onClicked: Qt.openUrlExternally(config.knownIssuesUrl) - } - - Button { - Layout.fillWidth: true - text: qsTr("Release Notes") - icon.name: "folder-text" - Kirigami.Theme.backgroundColor: Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.4) - Kirigami.Theme.textColor: Kirigami.Theme.textColor - - visible: config.releaseNotesUrl !== "" - onClicked: load.source = "release_notes.qml" - //onClicked: load.source = "file:/usr/share/calamares/release_notes.qml" - } - - Button { - Layout.fillWidth: true - text: qsTr("Donate") - icon.name: "taxes-finances" - Kirigami.Theme.backgroundColor: Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.4) - Kirigami.Theme.textColor: Kirigami.Theme.textColor - - visible: config.donateUrl !== "" - onClicked: Qt.openUrlExternally(config.donateUrl) - } - } - - RowLayout { - id: languageBar - width: parent.width /1.2 - height: 48 - - anchors.bottom: parent.bottom - anchors.bottomMargin: parent.height /7 - anchors.horizontalCenter: parent.horizontalCenter - spacing: Kirigami.Units.largeSpacing* 4 - - Rectangle { - width: parent.width - Layout.fillWidth: true - focus: true - - Loader { - id: imLoader - - Component { - id: icon - Kirigami.Icon { - source: config.languageIcon - height: 48 - width: 48 - } - } - - Component { - id: image - Image { - height: 48 - fillMode: Image.PreserveAspectFit - source: "img/language-icon-48px.png" - } - } - - sourceComponent: (config.languageIcon != "") ? icon : image - } - - ComboBox { - id: languages - anchors.left: imLoader.right - width: languageBar.width /1.1 - textRole: "label" - currentIndex: config.localeIndex - model: config.languagesModel - onCurrentIndexChanged: config.localeIndex = currentIndex - } - } - } - - Loader { - id:load - anchors.fill: parent - } - } -} diff --git a/src/modules/welcomeq/welcomeq.qrc b/src/modules/welcomeq/welcomeq.qrc deleted file mode 100644 index 6f7a9c5df1..0000000000 --- a/src/modules/welcomeq/welcomeq.qrc +++ /dev/null @@ -1,11 +0,0 @@ - - - welcomeq.qml - release_notes.qml - Recommended.qml - Requirements.qml - img/squid.png - img/chevron-left-solid.svg - img/language-icon-48px.png - - diff --git a/src/modules/zfs/CMakeLists.txt b/src/modules/zfs/CMakeLists.txt deleted file mode 100644 index 07764a3609..0000000000 --- a/src/modules/zfs/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# -calamares_add_plugin(zfs - TYPE job - EXPORT_MACRO PLUGINDLLEXPORT_PRO - SOURCES - ZfsJob.cpp - SHARED_LIB -) diff --git a/src/modules/zfs/README.md b/src/modules/zfs/README.md deleted file mode 100644 index 992fa5cb3b..0000000000 --- a/src/modules/zfs/README.md +++ /dev/null @@ -1,21 +0,0 @@ -## zfs Module Notes - - - -There are a few considerations to be aware of when enabling the zfs module -* You must provide zfs kernel modules or kernel support on the ISO for the zfs module to function - * The zfs kernel module must be loaded prior to the partition module running - * One way to achieve this is by running `modprobe zfs` -* Support for zfs in the partition module is conditional on the zfs module being enabled -* The config for the default pools and datasets is configured and described in modules/zfs.conf -* If you use grub with zfs, you must have `ZPOOL_VDEV_NAME_PATH=1` in your environment when running grub-install or grub-mkconfig. - * Calamares will ensure this happens during the bootloader module. - * It will also add it to `/etc/environment` so it will be available in the installation - * If you have an scripts or other processes that trigger grub-mkconfig during the install process, be sure to add that to the environment -* In most cases, you will need to enable services for zfs support appropriate to your distro. For example, when testing on Arch the following services were enabled: - * zfs.target - * zfs-import-cache - * zfs-mount - * zfs-import.target diff --git a/src/modules/zfs/ZfsJob.cpp b/src/modules/zfs/ZfsJob.cpp deleted file mode 100644 index 7181656e6a..0000000000 --- a/src/modules/zfs/ZfsJob.cpp +++ /dev/null @@ -1,371 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2021 Evan James - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "ZfsJob.h" - -#include "utils/Logger.h" -#include "utils/System.h" -#include "utils/Variant.h" - -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "Settings.h" - -#include -#include - -#include - -/** @brief Returns the alphanumeric portion of a string - * - * @p input is the input string - * - */ -static QString -alphaNumeric( QString input ) -{ - return input.remove( QRegularExpression( "[^a-zA-Z\\d\\s]" ) ); -} - -/** @brief Returns the best available device for zpool creation - * - * zfs partitions generally don't have UUID until the zpool is created. Generally, - * they are formed using either the id or the partuuid. The id isn't stored by kpmcore - * so this function checks to see if we have a partuuid. If so, it forms a device path - * for it. As a backup, it uses the device name i.e. /dev/sdax. - * - * The function returns a fully qualified path to the device or an empty string if no device - * is found - * - * @p pMap is the partition map from global storage - * - */ -static QString -findBestZfsDevice( QVariantMap pMap ) -{ - // Find the best device identifier, if one isn't available, skip this partition - QString deviceName; - if ( pMap[ "partuuid" ].toString() != "" ) - { - return "/dev/disk/by-partuuid/" + pMap[ "partuuid" ].toString().toLower(); - } - else if ( pMap[ "device" ].toString() != "" ) - { - return pMap[ "device" ].toString().toLower(); - } - else - { - return QString(); - } -} - -/** @brief Converts the value in a QVariant to a string which is a valid option for canmount - * - * Storing "on" and "off" in QVariant results in a conversion to boolean. This function takes - * the Qvariant in @p canMount and converts it to a QString holding "on", "off" or the string - * value in the QVariant. - * - */ -static QString -convertCanMount( QVariant canMount ) -{ - if ( canMount == true ) - { - return "on"; - } - else if ( canMount == false ) - { - return "off"; - } - else - { - return canMount.toString(); - } -} - -ZfsJob::ZfsJob( QObject* parent ) - : Calamares::CppJob( parent ) -{ -} - -ZfsJob::~ZfsJob() {} - -QString -ZfsJob::prettyName() const -{ - return tr( "Creating ZFS pools and datasets…", "@status" ); -} - -void -ZfsJob::collectMountpoints( const QVariantList& partitions ) -{ - m_mountpoints.empty(); - for ( const QVariant& partition : partitions ) - { - if ( partition.canConvert< QVariantMap >() ) - { - QString mountpoint = partition.toMap().value( "mountPoint" ).toString(); - if ( !mountpoint.isEmpty() ) - { - m_mountpoints.append( mountpoint ); - } - } - } -} - -bool -ZfsJob::isMountpointOverlapping( const QString& targetMountpoint ) const -{ - for ( const QString& mountpoint : m_mountpoints ) - { - if ( mountpoint != '/' && targetMountpoint.startsWith( mountpoint ) ) - { - return true; - } - } - return false; -} - -ZfsResult -ZfsJob::createZpool( QString deviceName, QString poolName, QString poolOptions, bool encrypt, QString passphrase ) const -{ - // zfs doesn't wait for the devices so pause for 2 seconds to ensure we give time for the device files to be created - sleep( 2 ); - - QStringList command; - if ( encrypt ) - { - command = QStringList() << "zpool" - << "create" << poolOptions.split( ' ' ) << "-O" - << "encryption=aes-256-gcm" - << "-O" - << "keyformat=passphrase" << poolName << deviceName; - } - else - { - command = QStringList() << "zpool" - << "create" << poolOptions.split( ' ' ) << poolName << deviceName; - } - - auto r = Calamares::System::instance()->runCommand( - Calamares::System::RunLocation::RunInHost, command, QString(), passphrase, std::chrono::seconds( 10 ) ); - - if ( r.getExitCode() != 0 ) - { - cWarning() << "Failed to run zpool create. The output was: " + r.getOutput(); - return { false, tr( "Failed to create zpool on " ) + deviceName }; - } - - return { true, QString() }; -} - -Calamares::JobResult -ZfsJob::exec() -{ - QVariantList partitions; - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - if ( gs && gs->contains( "partitions" ) && gs->value( "partitions" ).canConvert< QVariantList >() ) - { - partitions = gs->value( "partitions" ).toList(); - } - else - { - cWarning() << "No *partitions* defined."; - return Calamares::JobResult::internalError( tr( "Configuration Error" ), - tr( "No partitions are available for ZFS." ), - Calamares::JobResult::InvalidConfiguration ); - } - - const Calamares::System* system = Calamares::System::instance(); - - QVariantList poolNames; - - // Check to ensure the list of zfs info from the partition module is available and convert it to a list - if ( !gs->contains( "zfsInfo" ) && gs->value( "zfsInfo" ).canConvert< QVariantList >() ) - { - return Calamares::JobResult::error( tr( "Internal data missing" ), tr( "Failed to create zpool" ) ); - } - QVariantList zfsInfoList = gs->value( "zfsInfo" ).toList(); - - for ( auto& partition : qAsConst( partitions ) ) - { - QVariantMap pMap; - if ( partition.canConvert< QVariantMap >() ) - { - pMap = partition.toMap(); - } - - // If it isn't a zfs partition, ignore it - if ( pMap[ "fsName" ] != "zfs" ) - { - continue; - } - - // Find the best device identifier, if one isn't available, skip this partition - QString deviceName = findBestZfsDevice( pMap ); - if ( deviceName.isEmpty() ) - { - continue; - } - - // If the partition doesn't have a mountpoint, skip it - QString mountpoint = pMap[ "mountPoint" ].toString(); - if ( mountpoint.isEmpty() ) - { - continue; - } - - // Build a poolname off config pool name and the mountpoint, this is not ideal but should work until there is UI built for zfs - QString poolName = m_poolName; - if ( mountpoint != '/' ) - { - poolName += alphaNumeric( mountpoint ); - } - - // Look in the zfs info list to see if this partition should be encrypted - bool encrypt = false; - QString passphrase; - for ( const QVariant& zfsInfo : qAsConst( zfsInfoList ) ) - { - if ( zfsInfo.canConvert< QVariantMap >() && zfsInfo.toMap().value( "encrypted" ).toBool() - && mountpoint == zfsInfo.toMap().value( "mountpoint" ) ) - { - encrypt = true; - passphrase = zfsInfo.toMap().value( "passphrase" ).toString(); - } - } - - // Generate the zfs hostid file - auto i = system->runCommand( { "zgenhostid" }, std::chrono::seconds( 3 ) ); - if ( i.getExitCode() != 0 ) - { - cWarning() << "Failed to create /etc/hostid"; - } - - // Create the zpool - ZfsResult zfsResult; - if ( encrypt ) - { - zfsResult = createZpool( deviceName, poolName, m_poolOptions, true, passphrase ); - } - else - { - zfsResult = createZpool( deviceName, poolName, m_poolOptions, false ); - } - - if ( !zfsResult.success ) - { - return Calamares::JobResult::error( tr( "Failed to create zpool" ), zfsResult.failureMessage ); - } - - // Save the poolname, dataset name and mountpoint. It will later be added to a list and placed in global storage. - // This will be used by later modules including mount and umount - QVariantMap poolNameEntry; - poolNameEntry[ "poolName" ] = poolName; - poolNameEntry[ "mountpoint" ] = mountpoint; - poolNameEntry[ "dsName" ] = "none"; - - // If the mountpoint is /, create datasets per the config file. If not, create a single dataset mounted at the partitions mountpoint - if ( mountpoint == '/' ) - { - collectMountpoints( partitions ); - QVariantList datasetList; - for ( const auto& dataset : qAsConst( m_datasets ) ) - { - QVariantMap datasetMap = dataset.toMap(); - - // Make sure all values are valid - if ( datasetMap[ "dsName" ].toString().isEmpty() || datasetMap[ "mountpoint" ].toString().isEmpty() - || datasetMap[ "canMount" ].toString().isEmpty() ) - { - cWarning() << "Bad dataset entry"; - continue; - } - - // We should skip this dataset if it conflicts with a permanent mountpoint - if ( isMountpointOverlapping( datasetMap[ "mountpoint" ].toString() ) ) - { - continue; - } - - QString canMount = convertCanMount( datasetMap[ "canMount" ].toString() ); - - // Create the dataset - auto r = system->runCommand( { QStringList() << "zfs" - << "create" << m_datasetOptions.split( ' ' ) << "-o" - << "canmount=" + canMount << "-o" - << "mountpoint=" + datasetMap[ "mountpoint" ].toString() - << poolName + "/" + datasetMap[ "dsName" ].toString() }, - std::chrono::seconds( 10 ) ); - if ( r.getExitCode() != 0 ) - { - cWarning() << "Failed to create dataset" << datasetMap[ "dsName" ].toString(); - continue; - } - - // Add the dataset to the list for global storage this information is used later to properly set - // the mount options on each dataset - datasetMap[ "zpool" ] = m_poolName; - datasetList.append( datasetMap ); - } - - // If the list isn't empty, add it to global storage - if ( !datasetList.isEmpty() ) - { - gs->insert( "zfsDatasets", datasetList ); - } - } - else - { - QString dsName = mountpoint; - dsName = alphaNumeric( mountpoint ); - auto r = system->runCommand( { QStringList() << "zfs" - << "create" << m_datasetOptions.split( ' ' ) << "-o" - << "canmount=on" - << "-o" - << "mountpoint=" + mountpoint << poolName + "/" + dsName }, - std::chrono::seconds( 10 ) ); - if ( r.getExitCode() != 0 ) - { - return Calamares::JobResult::error( tr( "Failed to create dataset" ), - tr( "The output was: " ) + r.getOutput() ); - } - poolNameEntry[ "dsName" ] = dsName; - } - - poolNames.append( poolNameEntry ); - - // Export the zpool so it can be reimported at the correct location later - auto r = system->runCommand( { "zpool", "export", poolName }, std::chrono::seconds( 10 ) ); - if ( r.getExitCode() != 0 ) - { - cWarning() << "Failed to export pool" << m_poolName; - } - } - - // Put the list of zpools into global storage - if ( !poolNames.isEmpty() ) - { - gs->insert( "zfsPoolInfo", poolNames ); - } - - return Calamares::JobResult::ok(); -} - -void -ZfsJob::setConfigurationMap( const QVariantMap& map ) -{ - m_poolName = Calamares::getString( map, "poolName" ); - m_poolOptions = Calamares::getString( map, "poolOptions" ); - m_datasetOptions = Calamares::getString( map, "datasetOptions" ); - - m_datasets = Calamares::getList( map, "datasets" ); -} - -CALAMARES_PLUGIN_FACTORY_DEFINITION( ZfsJobFactory, registerPlugin< ZfsJob >(); ) diff --git a/src/modules/zfs/ZfsJob.h b/src/modules/zfs/ZfsJob.h deleted file mode 100644 index 58a6450ee4..0000000000 --- a/src/modules/zfs/ZfsJob.h +++ /dev/null @@ -1,89 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2021 Evan James - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef ZFSJOB_H -#define ZFSJOB_H - -#include -#include -#include - -#include "CppJob.h" - -#include "utils/PluginFactory.h" - -#include "DllMacro.h" - -struct ZfsResult -{ - bool success; - QString failureMessage; // This message is displayed to the user and should be translated at the time of population -}; - -/** @brief Create zpools and zfs datasets - * - */ -class PLUGINDLLEXPORT ZfsJob : public Calamares::CppJob -{ - Q_OBJECT - -public: - explicit ZfsJob( QObject* parent = nullptr ); - ~ZfsJob() override; - - QString prettyName() const override; - - Calamares::JobResult exec() override; - - void setConfigurationMap( const QVariantMap& configurationMap ) override; - -private: - QString m_poolName; - QString m_poolOptions; - QString m_datasetOptions; - QStringList m_mountpoints; - - QList< QVariant > m_datasets; - - /** @brief Creates a zpool based on the provided arguments - * - * @p deviceName is a full path to the device the zpool should be created on - * @p poolName is a string containing the name of the pool to create - * @p poolOptions are the options to pass to zpool create - * @p encrypt is a boolean which determines if the pool should be encrypted - * @p passphrase is a string continaing the passphrase - * - */ - ZfsResult createZpool( QString deviceName, - QString poolName, - QString poolOptions, - bool encrypt, - QString passphrase = QString() ) const; - - /** @brief Collects all the mountpoints from the partitions - * - * Iterates over @p partitions to gather each mountpoint present - * in the list of maps and populates m_mountpoints - * - */ - void collectMountpoints( const QVariantList& partitions ); - - /** @brief Check to see if a given mountpoint overlaps with one of the defined moutnpoints - * - * Iterates over m_partitions and checks if @p targetMountpoint overlaps with them by comparing - * the beginning of targetMountpoint with all the values in m_mountpoints. Of course, / is excluded - * since all the mountpoints would begin with / - * - */ - bool isMountpointOverlapping( const QString& targetMountpoint ) const; -}; - -CALAMARES_PLUGIN_FACTORY_DECLARATION( ZfsJobFactory ) - -#endif // ZFSJOB_H diff --git a/src/modules/zfs/zfs.conf b/src/modules/zfs/zfs.conf deleted file mode 100644 index e5a0aa3484..0000000000 --- a/src/modules/zfs/zfs.conf +++ /dev/null @@ -1,45 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# The zfs module creates the zfs pools and datasets -# -# -# ---- -# The name to be used for the zpool -poolName: zpcala - -# A list of options that will be passed to zpool create -# -# Encryption options should generally not be added here since they will be added by -# selecting the encrypt disk option in the partition module -poolOptions: "-f -o ashift=12 -O mountpoint=none -O acltype=posixacl -O relatime=on" - -# A list of options that will be passed to zfs create when creating each dataset -# Do not include "canmount" or "mountpoint" as those are set below in the datasets array -datasetOptions: "-o compression=lz4 -o atime=off -o xattr=sa" - -# An array of datasets that will be created on the zpool mounted at / -# -# This default configuration is commonly used when support for booting more than one distro -# out of a single zpool is desired. If you decide to keep this default configuration, -# you should replace "distro" with an identifier that represents your distro. -datasets: - - dsName: ROOT - mountpoint: none - canMount: off - - dsName: ROOT/distro - mountpoint: none - canMount: off - - dsName: ROOT/distro/root - mountpoint: / - canMount: noauto - - dsName: ROOT/distro/home - mountpoint: /home - canMount: on - - dsName: ROOT/distro/varcache - mountpoint: /var/cache - canMount: on - - dsName: ROOT/distro/varlog - mountpoint: /var/log - canMount: on diff --git a/src/modules/zfs/zfs.schema.yaml b/src/modules/zfs/zfs.schema.yaml deleted file mode 100644 index ddad6d77b3..0000000000 --- a/src/modules/zfs/zfs.schema.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# SPDX-FileCopyrightText: 2020 Adriaan de Groot -# SPDX-License-Identifier: GPL-3.0-or-later ---- -$schema: https://json-schema.org/schema# -$id: https://calamares.io/schemas/zfs -additionalProperties: false -type: object -properties: - poolName: { type: string } - poolOptions: { type: string } - datasetOptions: { type: string } - datasets: - type: array - items: - type: object - additionalProperties: false - properties: - dsName: { type: string } - mountpoint: { type: string } - # Nominally a string, but "on" and "off" are valid and get - # turned into a boolean in the YAML parser. - canMount: { anyOf: [ { type: string }, { type: boolean } ] } - required: [ dsName, mountpoint, canMount ] -required: [ poolName, datasets ] diff --git a/src/modules/zfshostid/main.py b/src/modules/zfshostid/main.py deleted file mode 100644 index 702ba1ede0..0000000000 --- a/src/modules/zfshostid/main.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2022 Anke Boersma -# SPDX-License-Identifier: GPL-3.0-or-later -# -# Calamares is Free Software: see the License-Identifier above. -# - -import os -import shutil - -import libcalamares -from libcalamares.utils import gettext_path, gettext_languages - - -import gettext -_ = gettext.translation("calamares-python", - localedir=libcalamares.utils.gettext_path(), - languages=libcalamares.utils.gettext_languages(), - fallback=True).gettext - - -def pretty_name(): - return _("Copying zfs generated hostid.") - - -def run(): - - zfs = libcalamares.globalstorage.value("zfsDatasets") - root_mount_point = libcalamares.globalstorage.value("rootMountPoint") - - if zfs: - hostid_source = '/etc/hostid' - hostid_destination = '{!s}/etc/hostid'.format(root_mount_point) - - try: - shutil.copy2(hostid_source, hostid_destination) - except Exception as e: - libcalamares.utils.warning("Could not copy hostid") - - return None diff --git a/src/modules/zfshostid/module.desc b/src/modules/zfshostid/module.desc deleted file mode 100644 index 13fec35bef..0000000000 --- a/src/modules/zfshostid/module.desc +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 ---- -type: "job" -name: "zfshostid" -interface: "python" -script: "main.py" -noconfig: true diff --git a/src/modules/zfshostid/zfshostid.schema.yaml b/src/modules/zfshostid/zfshostid.schema.yaml deleted file mode 100644 index 24774d01ac..0000000000 --- a/src/modules/zfshostid/zfshostid.schema.yaml +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: 2022 Anke Boersma -# SPDX-License-Identifier: GPL-3.0-or-later ---- -$schema: https://json-schema.org/schema# -$id: https://calamares.io/schemas/zfshostid -additionalProperties: false -type: object