Merge branch 'calamares' of https://github.com/calamares/calamares into development

This commit is contained in:
Philip Müller 2020-06-18 22:14:18 +02:00
commit 561bc0d10c
66 changed files with 10877 additions and 962 deletions

View File

@ -26,6 +26,7 @@ ReflowComments: "false"
SortIncludes: "true"
SpaceAfterCStyleCast: "false"
SpacesBeforeTrailingComments: "2"
# SpaceInEmptyBlock: "true"
SpacesInAngles: "true"
SpacesInParentheses: "true"
SpacesInSquareBrackets: "true"

17
CHANGES
View File

@ -3,21 +3,36 @@ contributors are listed. Note that Calamares does not have a historical
changelog -- this log starts with version 3.2.0. The release notes on the
website will have to do for older versions.
# 3.2.26 (unreleased) #
# 3.2.26 (2020-06-18) #
This release contains contributions from (alphabetically by first name):
- Anke Boersma
- Gaël PORTAY
- Pablo Ovelleiro Corral
- Philip Müller
## Core ##
- The default branch for Calamares source repositories (calamares
and calamares-extensions) is now *calamares*.
- External modules can now be built again, outside of the Calamares
source and build-tree.
- The repository *calamares-tools* has been removed. The idea behind
the tooling was to provide schema validation for Calamares configuration
files. This has been merged into the primary repository, where it
is now part of the test suite.
## Modules ##
- *locale* put some more places into the correct timezone **visually**;
for instance Norfolk Island gave up UTC+11.5 in 2015 and is now
UTC+11, but Calamares still showed it in a zone separate from UTC+11.
- *localeq* can now properly switch between on & offline mode,
it detects internet status through js.
- *packages* gained support for the Void Linux package manager,
*xbps*. (thanks Pablo)
- *tracking* now supports kuserfeedback configuration.
- *welcomeq* added the GEOIP configuration option, so locale can be
initially set according to IP address.
# 3.2.25 (2020-06-06) #

View File

@ -27,8 +27,13 @@
# USE_<foo> : fills in SKIP_MODULES for modules called <foo>-<something>
# WITH_<foo> : try to enable <foo> (these usually default to ON). For
# a list of WITH_<foo> grep CMakeCache.txt after running
# CMake once.
# CMake once. These affect the ABI offered by Calamares.
# - PYTHON (enable Python Job modules)
# - QML (enable QML UI View modules)
# - PYTHONQT # TODO:3.3: remove
# BUILD_<foo> : choose additional things to build
# - TESTING (standard CMake option)
# - SCHEMA_TESTING (requires Python, see ci/configvalidator.py)
# DEBUG_<foo> : special developer flags for debugging
#
# Example usage:
@ -38,12 +43,13 @@
# One special target is "show-version", which can be built
# to obtain the version number from here.
# TODO:3.3: Require CMake 3.12
cmake_minimum_required( VERSION 3.3 FATAL_ERROR )
project( CALAMARES
VERSION 3.2.26
LANGUAGES C CXX )
set( CALAMARES_VERSION_RC 1 ) # Set to 0 during release cycle, 1 during development
set( CALAMARES_VERSION_RC 0 ) # Set to 0 during release cycle, 1 during development
### OPTIONS
#
@ -51,13 +57,17 @@ option( INSTALL_CONFIG "Install configuration files" OFF )
option( INSTALL_POLKIT "Install Polkit configuration" ON )
option( INSTALL_COMPLETION "Install shell completions" OFF )
# Options for the calamares executable
option( WITH_KF5Crash "Enable crash reporting with KCrash." ON )
option( WITH_KF5DBus "Use DBus service for unique-application." OFF )
option( WITH_KF5Crash "Enable crash reporting with KCrash." ON ) # TODO:3.3: WITH->BUILD (this isn't an ABI thing)
option( WITH_KF5DBus "Use DBus service for unique-application." OFF ) # TODO:3.3: WITH->BUILD
# When adding WITH_* that affects the ABI offered by libcalamares,
# also update libcalamares/CalamaresConfig.h.in
option( WITH_PYTHON "Enable Python modules API (requires Boost.Python)." ON )
option( WITH_PYTHONQT "Enable Python view modules API (deprecated, requires PythonQt)." OFF )
option( WITH_PYTHONQT "Enable Python view modules API (deprecated, requires PythonQt)." OFF ) # TODO:3.3: remove
option( WITH_QML "Enable QML UI options." ON )
#
# Additional parts to build
option( BUILD_SCHEMA_TESTING "Enable schema-validation-tests" ON )
# Possible debugging flags are:
# - DEBUG_TIMEZONES draws latitude and longitude lines on the timezone
@ -322,15 +332,41 @@ if( NOT KF5DBusAddons_FOUND )
set( WITH_KF5DBus OFF )
endif()
# TODO:3.3: Use FindPython3 instead
find_package( PythonInterp ${PYTHONLIBS_VERSION} )
set_package_properties(
PythonInterp PROPERTIES
DESCRIPTION "Python 3 interpreter."
URL "https://python.org"
PURPOSE "Python 3 interpreter for certain tests."
)
if ( PYTHONINTERP_FOUND )
message(STATUS "Found Python 3 interpreter ${PYTHON_EXECUTABLE}")
if ( BUILD_SCHEMA_TESTING )
# The configuration validator script has some dependencies,
# and if they are not installed, don't run. If errors out
# with exit(1) on missing dependencies.
exec_program( ${PYTHON_EXECUTABLE} ARGS "${CMAKE_SOURCE_DIR}/ci/configvalidator.py" -x RETURN_VALUE _validator_deps )
# It should never succeed, but only returns 1 when the imports fail
if ( _validator_deps EQUAL 1 )
message(STATUS "BUILD_SCHEMA_TESTING dependencies are missing." )
set( BUILD_SCHEMA_TESTING OFF )
endif()
endif()
else()
# Can't run schema tests without Python3.
set( BUILD_SCHEMA_TESTING OFF )
endif()
find_package( PythonLibs ${PYTHONLIBS_VERSION} )
set_package_properties(
PythonLibs PROPERTIES
DESCRIPTION "C interface libraries for the Python 3 interpreter."
URL "http://python.org"
URL "https://python.org"
PURPOSE "Python 3 is used for Python job modules."
)
if ( PYTHONLIBS_FOUND )
# TODO:3.3: Require Boost + CMake; sort out Boost::Python
# Since Boost provides CMake config files (starting with Boost 1.70.
# or so) the mess that is the Calamares find code picks the wrong
# bits. Suppress those CMake config files, as suggested by @jmrcpn
@ -341,7 +377,7 @@ if ( PYTHONLIBS_FOUND )
Boost PROPERTIES
PURPOSE "Boost.Python is used for Python job modules."
)
# TODO:3.3: Remove PythonQt support
find_package( PythonQt )
set_package_properties( PythonQt PROPERTIES
DESCRIPTION "A Python embedding solution for Qt applications."

View File

@ -13,7 +13,7 @@ export LANG LC_ALL LC_NUMERIC
AS=$( which astyle )
CF_VERSIONS="clang-format-7 clang-format-8 clang-format70 clang-format80 clang-format"
CF_VERSIONS="clang-format-7 clang-format-8 clang-format70 clang-format80 clang-format-9.0.1 clang-format"
for _cf in $CF_VERSIONS
do
# Not an error if this particular clang-format isn't found
@ -26,6 +26,8 @@ test -n "$CF" || { echo "! No clang-format ($CF_VERSIONS) found in PATH"; exit 1
test -x "$AS" || { echo "! $AS is not executable."; exit 1 ; }
test -x "$CF" || { echo "! $CF is not executable."; exit 1 ; }
expr `"$CF" --version | tr -dc '[^.0-9]' | cut -d . -f 1` '<' 10 > /dev/null || { echo "! $CF is version 10 or later, needs different .clang-format" ; exit 1 ; }
set -e
any_dirs=no

128
ci/configvalidator.py Normal file
View File

@ -0,0 +1,128 @@
#! /usr/bin/env python3
#
# SPDX-FileCopyrightText: 2020 Adriaan de Groot <groot@kde.org>
# SPDX-License-Identifier: BSD-2-Clause
# License-Filename: LICENSES/BSD2
#
usage = """
Validates a Calamares config file -- YAML syntax -- against a schema.
The schema is also written in YAML syntax, but the schema itself
is JSON-schema. This is possible because all JSON is YAML, and most
YAML is JSON. The limited subset of YAML that Calamares uses is
JSON-representable, anyway.
Usage:
configvalidator.py <schema> <file> ...
configvalidator.py -x
Exits with value 0 on success, otherwise:
1 on missing dependencies
2 on invalid command-line arguments
3 on missing files
4 if files have invalid syntax
5 if files fail to validate
Use -x as only command-line argument to check the imports only.
"""
# The schemata originally lived outside the Calamares repository,
# without documented tooling. By putting them in the repository
# with the example files and explicit tooling, there's a better
# chance of them catching problems and acting as documentation.
dependencies = """
Dependencies for this tool are: py-yaml and py-jsonschema.
https://pyyaml.org/
https://github.com/Julian/jsonschema
Simple installation is `pip install pyyaml jsonschema`
"""
ERR_IMPORT, ERR_USAGE, ERR_FILE_NOT_FOUND, ERR_SYNTAX, ERR_INVALID = range(1,6)
### DEPENDENCIES
#
#
try:
from jsonschema import validate, SchemaError, ValidationError
from yaml import safe_load, YAMLError
except ImportError as e:
print(e)
print(dependencies)
exit(ERR_IMPORT)
from os.path import exists
import sys
### INPUT VALIDATION
#
#
if len(sys.argv) < 3:
# Special-case: called with -x to just test the imports
if len(sys.argv) == 2 and sys.argv[1] == "-x":
exit(0)
print(usage)
exit(ERR_USAGE)
schema_file_name = sys.argv[1]
config_file_names = sys.argv[2:]
if not exists(schema_file_name):
print(usage)
print("\nSchema file '{}' does not exist.".format(schema_file_name))
exit(ERR_FILE_NOT_FOUND)
for f in config_file_names:
if not exists(f):
print(usage)
print("\nYAML file '{}' does not exist.".format(f))
exit(ERR_FILE_NOT_FOUND)
### FILES SYNTAX CHECK
#
#
with open(schema_file_name, "r") as data:
try:
schema = safe_load(data)
except YAMLError as e:
print("Schema error: {} {}.".format(e.problem, e.problem_mark))
print("\nSchema file '{}' is invalid YAML.".format(schema_file_name))
exit(ERR_SYNTAX)
try:
validate(instance={}, schema=schema)
# While developing the schemata, get full exceptions from schema failure
except SchemaError as e:
print(e)
print("\nSchema file '{}' is invalid JSON-Schema.".format(schema_file_name))
exit(ERR_INVALID)
except ValidationError:
# Just means that empty isn't valid, but the Schema itself is
pass
configs = []
for f in config_file_names:
config = None
with open(f, "r") as data:
try:
config = safe_load(data)
except YAMLError as e:
print("YAML error: {} {}.".format(e.problem, e.problem_mark))
print("\nYAML file '{}' is invalid.".format(f))
exit(ERR_SYNTAX)
if config is None:
print("YAML file '{}' is empty.".format(f))
configs.append(config)
assert len(configs) == len(config_file_names), "Not all configurations loaded."
### SCHEMA VALIDATION
#
#
for c, f in zip(configs, config_file_names):
try:
validate(instance=c, schema=schema)
except ValidationError as e:
print(e)
print("\nConfig file '{}' does not validate in schema.".format(f))
exit(ERR_INVALID)

34
data/FreeBSD/Makefile Normal file
View File

@ -0,0 +1,34 @@
# $FreeBSD$
PORTNAME= calamares
DISTVERSION= 3.2.25
CATEGORIES= sysutils
MASTER_SITES= https://github.com/${PORTNAME}/${PORTNAME}/releases/download/v${DISTVERSION}/
MAINTAINER= adridg@FreeBSD.org
COMMENT= GUI System installer and OEM configurator
LICENSE= GPLv3
LICENSE_FILE= ${WRKSRC}/LICENSE
LIB_DEPENDS= libyaml-cpp.so:devel/yaml-cpp \
libpwquality.so:security/libpwquality \
libboost_python${PYTHON_SUFFIX}.so:devel/boost-python-libs
USES= cmake compiler:c++17-lang gettext kde:5 pkgconfig \
python:3.3+ qt:5
USE_QT= concurrent core dbus declarative gui \
network quickcontrols2 svg widgets xml \
buildtools_build linguist_build qmake_build
USE_KDE= coreaddons dbusaddons parts service \
ecm_build
USE_LDCONFIG= yes
CMAKE_OFF= WITH_KF5Crash \
INSTALL_CONFIG \
INSTALL_COMPLETION \
INSTALL_POLKIT
CMAKE_ON= CMAKE_DISABLE_FIND_PACKAGE_KPMcore
CMAKE_ARGS= -DSKIP_MODULES="webview"
.include <bsd.port.mk>

3
data/FreeBSD/distinfo Normal file
View File

@ -0,0 +1,3 @@
TIMESTAMP = 1592339404
SHA256 (calamares-3.2.25.tar.gz) = 797ce33db7d4e4c06bbccef95f6c4023f7628e91bd142896695565fed4ae8c4b
SIZE (calamares-3.2.25.tar.gz) = 3580197

14
data/FreeBSD/pkg-descr Normal file
View File

@ -0,0 +1,14 @@
Calamares is an installer framework. By design it is very customizable,
in order to satisfy a wide variety of needs and use cases.
Calamares aims to be easy, usable, beautiful, pragmatic, inclusive and
distribution-agnostic.
Got a Linux distribution but no system installer? Grab Calamares, mix
and match any number of Calamares modules (or write your own in Python
or C++), throw together some branding, package it up and you are ready
to ship!
(The above applies to FreeBSD as well)
WWW: https://calamares.io/

224
data/FreeBSD/pkg-plist Normal file
View File

@ -0,0 +1,224 @@
bin/calamares
include/libcalamares/CalamaresConfig.h
include/libcalamares/CppJob.h
include/libcalamares/DllMacro.h
include/libcalamares/GlobalStorage.h
include/libcalamares/Job.h
include/libcalamares/JobExample.h
include/libcalamares/JobQueue.h
include/libcalamares/ProcessJob.h
include/libcalamares/PythonHelper.h
include/libcalamares/PythonJob.h
include/libcalamares/PythonJobApi.h
include/libcalamares/Settings.h
include/libcalamares/utils/BoostPython.h
include/libcalamares/utils/CalamaresUtilsSystem.h
include/libcalamares/utils/CommandList.h
include/libcalamares/utils/Dirs.h
include/libcalamares/utils/Entropy.h
include/libcalamares/utils/Logger.h
include/libcalamares/utils/NamedEnum.h
include/libcalamares/utils/NamedSuffix.h
include/libcalamares/utils/PluginFactory.h
include/libcalamares/utils/RAII.h
include/libcalamares/utils/Retranslator.h
include/libcalamares/utils/String.h
include/libcalamares/utils/Tests.h
include/libcalamares/utils/UMask.h
include/libcalamares/utils/Units.h
include/libcalamares/utils/Variant.h
include/libcalamares/utils/Yaml.h
include/libcalamares/utils/moc-warnings.h
lib/calamares/libcalamares.so
lib/calamares/modules/bootloader/main.py
lib/calamares/modules/bootloader/module.desc
lib/calamares/modules/bootloader/test.yaml
lib/calamares/modules/contextualprocess/libcalamares_job_contextualprocess.so
lib/calamares/modules/contextualprocess/module.desc
lib/calamares/modules/displaymanager/main.py
lib/calamares/modules/displaymanager/module.desc
lib/calamares/modules/dracut/main.py
lib/calamares/modules/dracut/module.desc
lib/calamares/modules/dracutlukscfg/libcalamares_job_dracutlukscfg.so
lib/calamares/modules/dracutlukscfg/module.desc
lib/calamares/modules/dummycpp/libcalamares_job_dummycpp.so
lib/calamares/modules/dummycpp/module.desc
lib/calamares/modules/dummyprocess/module.desc
lib/calamares/modules/dummypython/main.py
lib/calamares/modules/dummypython/module.desc
lib/calamares/modules/finished/libcalamares_viewmodule_finished.so
lib/calamares/modules/finished/module.desc
lib/calamares/modules/fstab/main.py
lib/calamares/modules/fstab/module.desc
lib/calamares/modules/fstab/test.yaml
lib/calamares/modules/grubcfg/main.py
lib/calamares/modules/grubcfg/module.desc
lib/calamares/modules/hostinfo/libcalamares_job_hostinfo.so
lib/calamares/modules/hostinfo/module.desc
lib/calamares/modules/hwclock/main.py
lib/calamares/modules/hwclock/module.desc
lib/calamares/modules/initcpio/libcalamares_job_initcpio.so
lib/calamares/modules/initcpio/module.desc
lib/calamares/modules/initcpiocfg/main.py
lib/calamares/modules/initcpiocfg/module.desc
lib/calamares/modules/initramfs/libcalamares_job_initramfs.so
lib/calamares/modules/initramfs/module.desc
lib/calamares/modules/initramfscfg/encrypt_hook
lib/calamares/modules/initramfscfg/encrypt_hook_nokey
lib/calamares/modules/initramfscfg/main.py
lib/calamares/modules/initramfscfg/module.desc
lib/calamares/modules/interactiveterminal/libcalamares_viewmodule_interactiveterminal.so
lib/calamares/modules/interactiveterminal/module.desc
lib/calamares/modules/keyboard/libcalamares_viewmodule_keyboard.so
lib/calamares/modules/keyboard/module.desc
lib/calamares/modules/keyboardq/libcalamares_viewmodule_keyboardq.so
lib/calamares/modules/keyboardq/module.desc
lib/calamares/modules/license/libcalamares_viewmodule_license.so
lib/calamares/modules/license/module.desc
lib/calamares/modules/locale/libcalamares_viewmodule_locale.so
lib/calamares/modules/locale/module.desc
lib/calamares/modules/localecfg/main.py
lib/calamares/modules/localecfg/module.desc
lib/calamares/modules/localeq/libcalamares_viewmodule_localeq.so
lib/calamares/modules/localeq/module.desc
lib/calamares/modules/luksbootkeyfile/libcalamares_job_luksbootkeyfile.so
lib/calamares/modules/luksbootkeyfile/module.desc
lib/calamares/modules/luksopenswaphookcfg/main.py
lib/calamares/modules/luksopenswaphookcfg/module.desc
lib/calamares/modules/machineid/libcalamares_job_machineid.so
lib/calamares/modules/machineid/module.desc
lib/calamares/modules/mount/main.py
lib/calamares/modules/mount/module.desc
lib/calamares/modules/mount/test.yaml
lib/calamares/modules/netinstall/libcalamares_viewmodule_netinstall.so
lib/calamares/modules/netinstall/module.desc
lib/calamares/modules/networkcfg/main.py
lib/calamares/modules/networkcfg/module.desc
lib/calamares/modules/notesqml/libcalamares_viewmodule_notesqml.so
lib/calamares/modules/notesqml/module.desc
lib/calamares/modules/oemid/libcalamares_viewmodule_oemid.so
lib/calamares/modules/oemid/module.desc
lib/calamares/modules/openrcdmcryptcfg/main.py
lib/calamares/modules/openrcdmcryptcfg/module.desc
lib/calamares/modules/packagechooser/libcalamares_viewmodule_packagechooser.so
lib/calamares/modules/packagechooser/module.desc
lib/calamares/modules/packages/main.py
lib/calamares/modules/packages/module.desc
lib/calamares/modules/packages/test.yaml
lib/calamares/modules/plymouthcfg/main.py
lib/calamares/modules/plymouthcfg/module.desc
lib/calamares/modules/preservefiles/libcalamares_job_preservefiles.so
lib/calamares/modules/preservefiles/module.desc
lib/calamares/modules/rawfs/main.py
lib/calamares/modules/rawfs/module.desc
lib/calamares/modules/removeuser/libcalamares_job_removeuser.so
lib/calamares/modules/removeuser/module.desc
lib/calamares/modules/services-openrc/main.py
lib/calamares/modules/services-openrc/module.desc
lib/calamares/modules/services-systemd/main.py
lib/calamares/modules/services-systemd/module.desc
lib/calamares/modules/shellprocess/libcalamares_job_shellprocess.so
lib/calamares/modules/shellprocess/module.desc
lib/calamares/modules/summary/libcalamares_viewmodule_summary.so
lib/calamares/modules/summary/module.desc
lib/calamares/modules/tracking/libcalamares_viewmodule_tracking.so
lib/calamares/modules/tracking/module.desc
lib/calamares/modules/umount/main.py
lib/calamares/modules/umount/module.desc
lib/calamares/modules/unpackfs/main.py
lib/calamares/modules/unpackfs/module.desc
lib/calamares/modules/unpackfs/runtests.sh
lib/calamares/modules/users/libcalamares_viewmodule_users.so
lib/calamares/modules/users/module.desc
lib/calamares/modules/welcome/libcalamares_viewmodule_welcome.so
lib/calamares/modules/welcome/module.desc
lib/calamares/modules/welcomeq/libcalamares_viewmodule_welcomeq.so
lib/calamares/modules/welcomeq/module.desc
lib/cmake/Calamares/CMakeColors.cmake
lib/cmake/Calamares/CalamaresAddBrandingSubdirectory.cmake
lib/cmake/Calamares/CalamaresAddLibrary.cmake
lib/cmake/Calamares/CalamaresAddModuleSubdirectory.cmake
lib/cmake/Calamares/CalamaresAddPlugin.cmake
lib/cmake/Calamares/CalamaresAddTest.cmake
lib/cmake/Calamares/CalamaresAddTranslations.cmake
lib/cmake/Calamares/CalamaresAutomoc.cmake
lib/cmake/Calamares/CalamaresConfig.cmake
lib/cmake/Calamares/CalamaresConfigVersion.cmake
lib/cmake/Calamares/CalamaresLibraryDepends-%%CMAKE_BUILD_TYPE%%.cmake
lib/cmake/Calamares/CalamaresLibraryDepends.cmake
lib/cmake/Calamares/CalamaresUse.cmake
lib/libcalamares.so
lib/libcalamares.so.3.2.25
lib/libcalamaresui.so
lib/libcalamaresui.so.3.2.25
man/man8/calamares.8.gz
share/applications/calamares.desktop
%%DATADIR%%/branding/default/banner.png
%%DATADIR%%/branding/default/branding.desc
%%DATADIR%%/branding/default/lang/calamares-default_ar.qm
%%DATADIR%%/branding/default/lang/calamares-default_en.qm
%%DATADIR%%/branding/default/lang/calamares-default_eo.qm
%%DATADIR%%/branding/default/lang/calamares-default_fr.qm
%%DATADIR%%/branding/default/lang/calamares-default_nl.qm
%%DATADIR%%/branding/default/languages.png
%%DATADIR%%/branding/default/show.qml
%%DATADIR%%/branding/default/squid.png
%%DATADIR%%/branding/default/stylesheet.qss
%%DATADIR%%/qml/calamares/slideshow/BackButton.qml
%%DATADIR%%/qml/calamares/slideshow/ForwardButton.qml
%%DATADIR%%/qml/calamares/slideshow/NavButton.qml
%%DATADIR%%/qml/calamares/slideshow/Presentation.qml
%%DATADIR%%/qml/calamares/slideshow/Slide.qml
%%DATADIR%%/qml/calamares/slideshow/SlideCounter.qml
%%DATADIR%%/qml/calamares/slideshow/qmldir
share/icons/hicolor/scalable/apps/calamares.svg
share/locale/ar/LC_MESSAGES/calamares-python.mo
share/locale/as/LC_MESSAGES/calamares-python.mo
share/locale/ast/LC_MESSAGES/calamares-python.mo
share/locale/be/LC_MESSAGES/calamares-python.mo
share/locale/bg/LC_MESSAGES/calamares-python.mo
share/locale/ca/LC_MESSAGES/calamares-python.mo
share/locale/cs_CZ/LC_MESSAGES/calamares-python.mo
share/locale/da/LC_MESSAGES/calamares-python.mo
share/locale/de/LC_MESSAGES/calamares-python.mo
share/locale/el/LC_MESSAGES/calamares-python.mo
share/locale/en_GB/LC_MESSAGES/calamares-python.mo
share/locale/eo/LC_MESSAGES/calamares-python.mo
share/locale/es/LC_MESSAGES/calamares-python.mo
share/locale/es_MX/LC_MESSAGES/calamares-python.mo
share/locale/es_PR/LC_MESSAGES/calamares-python.mo
share/locale/et/LC_MESSAGES/calamares-python.mo
share/locale/eu/LC_MESSAGES/calamares-python.mo
share/locale/fi_FI/LC_MESSAGES/calamares-python.mo
share/locale/fr/LC_MESSAGES/calamares-python.mo
share/locale/gl/LC_MESSAGES/calamares-python.mo
share/locale/he/LC_MESSAGES/calamares-python.mo
share/locale/hi/LC_MESSAGES/calamares-python.mo
share/locale/hr/LC_MESSAGES/calamares-python.mo
share/locale/hu/LC_MESSAGES/calamares-python.mo
share/locale/id/LC_MESSAGES/calamares-python.mo
share/locale/is/LC_MESSAGES/calamares-python.mo
share/locale/it_IT/LC_MESSAGES/calamares-python.mo
share/locale/ja/LC_MESSAGES/calamares-python.mo
share/locale/ko/LC_MESSAGES/calamares-python.mo
share/locale/lt/LC_MESSAGES/calamares-python.mo
share/locale/ml/LC_MESSAGES/calamares-python.mo
share/locale/mr/LC_MESSAGES/calamares-python.mo
share/locale/nb/LC_MESSAGES/calamares-python.mo
share/locale/nl/LC_MESSAGES/calamares-python.mo
share/locale/pl/LC_MESSAGES/calamares-python.mo
share/locale/pt_BR/LC_MESSAGES/calamares-python.mo
share/locale/pt_PT/LC_MESSAGES/calamares-python.mo
share/locale/ro/LC_MESSAGES/calamares-python.mo
share/locale/ru/LC_MESSAGES/calamares-python.mo
share/locale/sk/LC_MESSAGES/calamares-python.mo
share/locale/sl/LC_MESSAGES/calamares-python.mo
share/locale/sq/LC_MESSAGES/calamares-python.mo
share/locale/sr/LC_MESSAGES/calamares-python.mo
share/locale/sr@latin/LC_MESSAGES/calamares-python.mo
share/locale/sv/LC_MESSAGES/calamares-python.mo
share/locale/th/LC_MESSAGES/calamares-python.mo
share/locale/tr_TR/LC_MESSAGES/calamares-python.mo
share/locale/uk/LC_MESSAGES/calamares-python.mo
share/locale/zh_CN/LC_MESSAGES/calamares-python.mo
share/locale/zh_TW/LC_MESSAGES/calamares-python.mo

3827
lang/calamares_az.ts Normal file

File diff suppressed because it is too large Load Diff

3827
lang/calamares_az_AZ.ts Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2,350 +2,338 @@
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-04-30 23:13+0200\n"
"POT-Creation-Date: 2020-06-18 15:42+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: \n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
#: src/modules/packages/main.py:59 src/modules/packages/main.py:68
#: src/modules/packages/main.py:78
msgid "Install packages."
msgstr "Install packages."
#: src/modules/packages/main.py:66
#, python-format
msgid "Processing packages (%(count)d / %(total)d)"
msgstr "Processing packages (%(count)d / %(total)d)"
#: src/modules/packages/main.py:71
#, python-format
msgid "Installing one package."
msgid_plural "Installing %(num)d packages."
msgstr[0] "Installing one package."
msgstr[1] "Installing %(num)d packages."
#: src/modules/packages/main.py:74
#, python-format
msgid "Removing one package."
msgid_plural "Removing %(num)d packages."
msgstr[0] "Removing one package."
msgstr[1] "Removing %(num)d packages."
#: src/modules/networkcfg/main.py:37
msgid "Saving network configuration."
msgstr "Saving network configuration."
#: src/modules/networkcfg/main.py:48 src/modules/initcpiocfg/main.py:205
#: src/modules/initcpiocfg/main.py:209 src/modules/openrcdmcryptcfg/main.py:78
#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/localecfg/main.py:144
#: src/modules/mount/main.py:145 src/modules/luksopenswaphookcfg/main.py:95
#: src/modules/luksopenswaphookcfg/main.py:99 src/modules/fstab/main.py:332
#: src/modules/fstab/main.py:338 src/modules/initramfscfg/main.py:94
#: src/modules/initramfscfg/main.py:98 src/modules/rawfs/main.py:171
msgid "Configuration Error"
msgstr "Configuration Error"
#: src/modules/networkcfg/main.py:49 src/modules/initcpiocfg/main.py:210
#: src/modules/openrcdmcryptcfg/main.py:83 src/modules/localecfg/main.py:145
#: src/modules/luksopenswaphookcfg/main.py:100 src/modules/fstab/main.py:339
#: src/modules/initramfscfg/main.py:99
msgid "No root mount point is given for <pre>{!s}</pre> to use."
msgstr "No root mount point is given for <pre>{!s}</pre> to use."
#: src/modules/umount/main.py:40
msgid "Unmount file systems."
msgstr "Unmount file systems."
#: src/modules/initcpiocfg/main.py:37
msgid "Configuring mkinitcpio."
msgstr "Configuring mkinitcpio."
#: src/modules/initcpiocfg/main.py:206 src/modules/openrcdmcryptcfg/main.py:79
#: src/modules/mount/main.py:146 src/modules/luksopenswaphookcfg/main.py:96
#: src/modules/fstab/main.py:333 src/modules/initramfscfg/main.py:95
#: src/modules/rawfs/main.py:172
msgid "No partitions are defined for <pre>{!s}</pre> to use."
msgstr "No partitions are defined for <pre>{!s}</pre> to use."
#: src/modules/openrcdmcryptcfg/main.py:34
msgid "Configuring OpenRC dmcrypt service."
msgstr "Configuring OpenRC dmcrypt service."
#: src/modules/unpackfs/main.py:44
msgid "Filling up filesystems."
msgstr "Filling up filesystems."
#: src/modules/unpackfs/main.py:257
msgid "rsync failed with error code {}."
msgstr "rsync failed with error code {}."
#: src/modules/unpackfs/main.py:302
msgid "Unpacking image {}/{}, file {}/{}"
msgstr "Unpacking image {}/{}, file {}/{}"
#: src/modules/unpackfs/main.py:317
msgid "Starting to unpack {}"
msgstr "Starting to unpack {}"
#: src/modules/unpackfs/main.py:326 src/modules/unpackfs/main.py:432
msgid "Failed to unpack image \"{}\""
msgstr "Failed to unpack image \"{}\""
#: src/modules/unpackfs/main.py:399
msgid "No mount point for root partition"
msgstr "No mount point for root partition"
#: src/modules/unpackfs/main.py:400
msgid "globalstorage does not contain a \"rootMountPoint\" key, doing nothing"
msgstr "globalstorage does not contain a \"rootMountPoint\" key, doing nothing"
#: src/modules/unpackfs/main.py:405
msgid "Bad mount point for root partition"
msgstr "Bad mount point for root partition"
#: src/modules/unpackfs/main.py:406
msgid "rootMountPoint is \"{}\", which does not exist, doing nothing"
msgstr "rootMountPoint is \"{}\", which does not exist, doing nothing"
#: src/modules/unpackfs/main.py:422 src/modules/unpackfs/main.py:426
#: src/modules/unpackfs/main.py:446
msgid "Bad unsquash configuration"
msgstr "Bad unsquash configuration"
#: src/modules/unpackfs/main.py:423
msgid "The filesystem for \"{}\" ({}) is not supported by your current kernel"
msgstr "The filesystem for \"{}\" ({}) is not supported by your current kernel"
#: src/modules/unpackfs/main.py:427
msgid "The source filesystem \"{}\" does not exist"
msgstr "The source filesystem \"{}\" does not exist"
#: src/modules/unpackfs/main.py:433
msgid ""
"Failed to find unsquashfs, make sure you have the squashfs-tools package "
"installed"
#: src/modules/grubcfg/main.py:37
msgid "Configure GRUB."
msgstr ""
"Failed to find unsquashfs, make sure you have the squashfs-tools package "
"installed"
#: src/modules/unpackfs/main.py:447
msgid "The destination \"{}\" in the target system is not a directory"
msgstr "The destination \"{}\" in the target system is not a directory"
#: src/modules/mount/main.py:38
msgid "Mounting partitions."
msgstr ""
#: src/modules/mount/main.py:150 src/modules/initcpiocfg/main.py:205
#: src/modules/initcpiocfg/main.py:209
#: src/modules/luksopenswaphookcfg/main.py:95
#: src/modules/luksopenswaphookcfg/main.py:99 src/modules/rawfs/main.py:173
#: src/modules/initramfscfg/main.py:94 src/modules/initramfscfg/main.py:98
#: src/modules/openrcdmcryptcfg/main.py:78
#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/fstab/main.py:332
#: src/modules/fstab/main.py:338 src/modules/localecfg/main.py:144
#: src/modules/networkcfg/main.py:48
msgid "Configuration Error"
msgstr ""
#: src/modules/mount/main.py:151 src/modules/initcpiocfg/main.py:206
#: src/modules/luksopenswaphookcfg/main.py:96 src/modules/rawfs/main.py:174
#: src/modules/initramfscfg/main.py:95 src/modules/openrcdmcryptcfg/main.py:79
#: src/modules/fstab/main.py:333
msgid "No partitions are defined for <pre>{!s}</pre> to use."
msgstr ""
#: src/modules/services-systemd/main.py:35
msgid "Configure systemd services"
msgstr "Configure systemd services"
msgstr ""
#: src/modules/services-systemd/main.py:68
#: src/modules/services-openrc/main.py:102
msgid "Cannot modify service"
msgstr "Cannot modify service"
msgstr ""
#: src/modules/services-systemd/main.py:69
msgid ""
"<code>systemctl {arg!s}</code> call in chroot returned error code {num!s}."
msgstr ""
"<code>systemctl {arg!s}</code> call in chroot returned error code {num!s}."
#: src/modules/services-systemd/main.py:72
#: src/modules/services-systemd/main.py:76
msgid "Cannot enable systemd service <code>{name!s}</code>."
msgstr "Cannot enable systemd service <code>{name!s}</code>."
msgstr ""
#: src/modules/services-systemd/main.py:74
msgid "Cannot enable systemd target <code>{name!s}</code>."
msgstr "Cannot enable systemd target <code>{name!s}</code>."
msgstr ""
#: src/modules/services-systemd/main.py:78
msgid "Cannot disable systemd target <code>{name!s}</code>."
msgstr "Cannot disable systemd target <code>{name!s}</code>."
msgstr ""
#: src/modules/services-systemd/main.py:80
msgid "Cannot mask systemd unit <code>{name!s}</code>."
msgstr "Cannot mask systemd unit <code>{name!s}</code>."
msgstr ""
#: src/modules/services-systemd/main.py:82
msgid ""
"Unknown systemd commands <code>{command!s}</code> and "
"<code>{suffix!s}</code> for unit {name!s}."
"Unknown systemd commands <code>{command!s}</code> and <code>{suffix!s}</"
"code> for unit {name!s}."
msgstr ""
"Unknown systemd commands <code>{command!s}</code> and "
"<code>{suffix!s}</code> for unit {name!s}."
#: src/modules/dummypython/main.py:44
msgid "Dummy python job."
msgstr "Dummy python job."
#: src/modules/umount/main.py:40
msgid "Unmount file systems."
msgstr ""
#: src/modules/dummypython/main.py:46 src/modules/dummypython/main.py:102
#: src/modules/dummypython/main.py:103
msgid "Dummy python step {}"
msgstr "Dummy python step {}"
#: src/modules/unpackfs/main.py:44
msgid "Filling up filesystems."
msgstr ""
#: src/modules/bootloader/main.py:51
msgid "Install bootloader."
msgstr "Install bootloader."
#: src/modules/unpackfs/main.py:257
msgid "rsync failed with error code {}."
msgstr ""
#: src/modules/localecfg/main.py:39
msgid "Configuring locales."
msgstr "Configuring locales."
#: src/modules/unpackfs/main.py:302
msgid "Unpacking image {}/{}, file {}/{}"
msgstr ""
#: src/modules/mount/main.py:38
msgid "Mounting partitions."
msgstr "Mounting partitions."
#: src/modules/unpackfs/main.py:317
msgid "Starting to unpack {}"
msgstr ""
#: src/modules/plymouthcfg/main.py:36
msgid "Configure Plymouth theme"
msgstr "Configure Plymouth theme"
#: src/modules/unpackfs/main.py:326 src/modules/unpackfs/main.py:448
msgid "Failed to unpack image \"{}\""
msgstr ""
#: src/modules/unpackfs/main.py:415
msgid "No mount point for root partition"
msgstr ""
#: src/modules/unpackfs/main.py:416
msgid "globalstorage does not contain a \"rootMountPoint\" key, doing nothing"
msgstr ""
#: src/modules/unpackfs/main.py:421
msgid "Bad mount point for root partition"
msgstr ""
#: src/modules/unpackfs/main.py:422
msgid "rootMountPoint is \"{}\", which does not exist, doing nothing"
msgstr ""
#: src/modules/unpackfs/main.py:438 src/modules/unpackfs/main.py:442
#: src/modules/unpackfs/main.py:462
msgid "Bad unsquash configuration"
msgstr ""
#: src/modules/unpackfs/main.py:439
msgid "The filesystem for \"{}\" ({}) is not supported by your current kernel"
msgstr ""
#: src/modules/unpackfs/main.py:443
msgid "The source filesystem \"{}\" does not exist"
msgstr ""
#: src/modules/unpackfs/main.py:449
msgid ""
"Failed to find unsquashfs, make sure you have the squashfs-tools package "
"installed"
msgstr ""
#: src/modules/unpackfs/main.py:463
msgid "The destination \"{}\" in the target system is not a directory"
msgstr ""
#: src/modules/displaymanager/main.py:523
msgid "Cannot write KDM configuration file"
msgstr ""
#: src/modules/displaymanager/main.py:524
msgid "KDM config file {!s} does not exist"
msgstr ""
#: src/modules/displaymanager/main.py:585
msgid "Cannot write LXDM configuration file"
msgstr ""
#: src/modules/displaymanager/main.py:586
msgid "LXDM config file {!s} does not exist"
msgstr ""
#: src/modules/displaymanager/main.py:669
msgid "Cannot write LightDM configuration file"
msgstr ""
#: src/modules/displaymanager/main.py:670
msgid "LightDM config file {!s} does not exist"
msgstr ""
#: src/modules/displaymanager/main.py:744
msgid "Cannot configure LightDM"
msgstr ""
#: src/modules/displaymanager/main.py:745
msgid "No LightDM greeter installed."
msgstr ""
#: src/modules/displaymanager/main.py:776
msgid "Cannot write SLIM configuration file"
msgstr ""
#: src/modules/displaymanager/main.py:777
msgid "SLIM config file {!s} does not exist"
msgstr ""
#: src/modules/displaymanager/main.py:903
msgid "No display managers selected for the displaymanager module."
msgstr ""
#: src/modules/displaymanager/main.py:904
msgid ""
"The displaymanagers list is empty or undefined in bothglobalstorage and "
"displaymanager.conf."
msgstr ""
#: src/modules/displaymanager/main.py:986
msgid "Display manager configuration was incomplete"
msgstr ""
#: src/modules/initcpiocfg/main.py:37
msgid "Configuring mkinitcpio."
msgstr ""
#: src/modules/initcpiocfg/main.py:210
#: src/modules/luksopenswaphookcfg/main.py:100
#: src/modules/initramfscfg/main.py:99 src/modules/openrcdmcryptcfg/main.py:83
#: src/modules/fstab/main.py:339 src/modules/localecfg/main.py:145
#: src/modules/networkcfg/main.py:49
msgid "No root mount point is given for <pre>{!s}</pre> to use."
msgstr ""
#: src/modules/luksopenswaphookcfg/main.py:35
msgid "Configuring encrypted swap."
msgstr "Configuring encrypted swap."
msgstr ""
#: src/modules/fstab/main.py:38
msgid "Writing fstab."
msgstr "Writing fstab."
#: src/modules/rawfs/main.py:35
msgid "Installing data."
msgstr ""
#: src/modules/services-openrc/main.py:38
msgid "Configure OpenRC services"
msgstr "Configure OpenRC services"
msgstr ""
#: src/modules/services-openrc/main.py:66
msgid "Cannot add service {name!s} to run-level {level!s}."
msgstr "Cannot add service {name!s} to run-level {level!s}."
msgstr ""
#: src/modules/services-openrc/main.py:68
msgid "Cannot remove service {name!s} from run-level {level!s}."
msgstr "Cannot remove service {name!s} from run-level {level!s}."
msgstr ""
#: src/modules/services-openrc/main.py:70
msgid ""
"Unknown service-action <code>{arg!s}</code> for service {name!s} in run-"
"level {level!s}."
msgstr ""
"Unknown service-action <code>{arg!s}</code> for service {name!s} in run-"
"level {level!s}."
#: src/modules/services-openrc/main.py:103
msgid ""
"<code>rc-update {arg!s}</code> call in chroot returned error code {num!s}."
msgstr ""
"<code>rc-update {arg!s}</code> call in chroot returned error code {num!s}."
#: src/modules/services-openrc/main.py:110
msgid "Target runlevel does not exist"
msgstr "Target runlevel does not exist"
msgstr ""
#: src/modules/services-openrc/main.py:111
msgid ""
"The path for runlevel {level!s} is <code>{path!s}</code>, which does not "
"exist."
msgstr ""
"The path for runlevel {level!s} is <code>{path!s}</code>, which does not "
"exist."
#: src/modules/services-openrc/main.py:119
msgid "Target service does not exist"
msgstr "Target service does not exist"
msgstr ""
#: src/modules/services-openrc/main.py:120
msgid ""
"The path for service {name!s} is <code>{path!s}</code>, which does not "
"exist."
"The path for service {name!s} is <code>{path!s}</code>, which does not exist."
msgstr ""
"The path for service {name!s} is <code>{path!s}</code>, which does not "
"exist."
#: src/modules/dracut/main.py:36
msgid "Creating initramfs with dracut."
msgstr "Creating initramfs with dracut."
#: src/modules/dracut/main.py:58
msgid "Failed to run dracut on the target"
msgstr "Failed to run dracut on the target"
#: src/modules/dracut/main.py:59
msgid "The exit code was {}"
msgstr "The exit code was {}"
#: src/modules/grubcfg/main.py:37
msgid "Configure GRUB."
msgstr "Configure GRUB."
#: src/modules/displaymanager/main.py:515
msgid "Cannot write KDM configuration file"
msgstr "Cannot write KDM configuration file"
#: src/modules/displaymanager/main.py:516
msgid "KDM config file {!s} does not exist"
msgstr "KDM config file {!s} does not exist"
#: src/modules/displaymanager/main.py:577
msgid "Cannot write LXDM configuration file"
msgstr "Cannot write LXDM configuration file"
#: src/modules/displaymanager/main.py:578
msgid "LXDM config file {!s} does not exist"
msgstr "LXDM config file {!s} does not exist"
#: src/modules/displaymanager/main.py:661
msgid "Cannot write LightDM configuration file"
msgstr "Cannot write LightDM configuration file"
#: src/modules/displaymanager/main.py:662
msgid "LightDM config file {!s} does not exist"
msgstr "LightDM config file {!s} does not exist"
#: src/modules/displaymanager/main.py:736
msgid "Cannot configure LightDM"
msgstr "Cannot configure LightDM"
#: src/modules/displaymanager/main.py:737
msgid "No LightDM greeter installed."
msgstr "No LightDM greeter installed."
#: src/modules/displaymanager/main.py:768
msgid "Cannot write SLIM configuration file"
msgstr "Cannot write SLIM configuration file"
#: src/modules/displaymanager/main.py:769
msgid "SLIM config file {!s} does not exist"
msgstr "SLIM config file {!s} does not exist"
#: src/modules/displaymanager/main.py:895
msgid "No display managers selected for the displaymanager module."
msgstr "No display managers selected for the displaymanager module."
#: src/modules/displaymanager/main.py:896
msgid ""
"The displaymanagers list is empty or undefined in bothglobalstorage and "
"displaymanager.conf."
#: src/modules/plymouthcfg/main.py:36
msgid "Configure Plymouth theme"
msgstr ""
"The displaymanagers list is empty or undefined in bothglobalstorage and "
"displaymanager.conf."
#: src/modules/displaymanager/main.py:978
msgid "Display manager configuration was incomplete"
msgstr "Display manager configuration was incomplete"
#: src/modules/packages/main.py:59 src/modules/packages/main.py:68
#: src/modules/packages/main.py:78
msgid "Install packages."
msgstr ""
#: src/modules/initramfscfg/main.py:41
msgid "Configuring initramfs."
msgstr "Configuring initramfs."
#: src/modules/packages/main.py:66
#, python-format
msgid "Processing packages (%(count)d / %(total)d)"
msgstr ""
#: src/modules/packages/main.py:71
#, python-format
msgid "Installing one package."
msgid_plural "Installing %(num)d packages."
msgstr[0] ""
msgstr[1] ""
#: src/modules/packages/main.py:74
#, python-format
msgid "Removing one package."
msgid_plural "Removing %(num)d packages."
msgstr[0] ""
msgstr[1] ""
#: src/modules/bootloader/main.py:51
msgid "Install bootloader."
msgstr ""
#: src/modules/hwclock/main.py:35
msgid "Setting hardware clock."
msgstr "Setting hardware clock."
msgstr ""
#: src/modules/rawfs/main.py:35
msgid "Installing data."
msgstr "Installing data."
#: src/modules/dracut/main.py:36
msgid "Creating initramfs with dracut."
msgstr ""
#: src/modules/dracut/main.py:58
msgid "Failed to run dracut on the target"
msgstr ""
#: src/modules/dracut/main.py:59
msgid "The exit code was {}"
msgstr ""
#: src/modules/initramfscfg/main.py:41
msgid "Configuring initramfs."
msgstr ""
#: src/modules/openrcdmcryptcfg/main.py:34
msgid "Configuring OpenRC dmcrypt service."
msgstr ""
#: src/modules/fstab/main.py:38
msgid "Writing fstab."
msgstr ""
#: src/modules/dummypython/main.py:44
msgid "Dummy python job."
msgstr ""
#: src/modules/dummypython/main.py:46 src/modules/dummypython/main.py:102
#: src/modules/dummypython/main.py:103
msgid "Dummy python step {}"
msgstr ""
#: src/modules/localecfg/main.py:39
msgid "Configuring locales."
msgstr ""
#: src/modules/networkcfg/main.py:37
msgid "Saving network configuration."
msgstr ""

Binary file not shown.

View File

@ -0,0 +1,336 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-04-30 23:13+0200\n"
"PO-Revision-Date: 2017-08-09 10:34+0000\n"
"Language-Team: Azerbaijani (https://www.transifex.com/calamares/teams/20061/az/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: az\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: src/modules/packages/main.py:59 src/modules/packages/main.py:68
#: src/modules/packages/main.py:78
msgid "Install packages."
msgstr ""
#: src/modules/packages/main.py:66
#, python-format
msgid "Processing packages (%(count)d / %(total)d)"
msgstr ""
#: src/modules/packages/main.py:71
#, python-format
msgid "Installing one package."
msgid_plural "Installing %(num)d packages."
msgstr[0] ""
msgstr[1] ""
#: src/modules/packages/main.py:74
#, python-format
msgid "Removing one package."
msgid_plural "Removing %(num)d packages."
msgstr[0] ""
msgstr[1] ""
#: src/modules/networkcfg/main.py:37
msgid "Saving network configuration."
msgstr ""
#: src/modules/networkcfg/main.py:48 src/modules/initcpiocfg/main.py:205
#: src/modules/initcpiocfg/main.py:209 src/modules/openrcdmcryptcfg/main.py:78
#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/localecfg/main.py:144
#: src/modules/mount/main.py:145 src/modules/luksopenswaphookcfg/main.py:95
#: src/modules/luksopenswaphookcfg/main.py:99 src/modules/fstab/main.py:332
#: src/modules/fstab/main.py:338 src/modules/initramfscfg/main.py:94
#: src/modules/initramfscfg/main.py:98 src/modules/rawfs/main.py:171
msgid "Configuration Error"
msgstr ""
#: src/modules/networkcfg/main.py:49 src/modules/initcpiocfg/main.py:210
#: src/modules/openrcdmcryptcfg/main.py:83 src/modules/localecfg/main.py:145
#: src/modules/luksopenswaphookcfg/main.py:100 src/modules/fstab/main.py:339
#: src/modules/initramfscfg/main.py:99
msgid "No root mount point is given for <pre>{!s}</pre> to use."
msgstr ""
#: src/modules/umount/main.py:40
msgid "Unmount file systems."
msgstr ""
#: src/modules/initcpiocfg/main.py:37
msgid "Configuring mkinitcpio."
msgstr ""
#: src/modules/initcpiocfg/main.py:206 src/modules/openrcdmcryptcfg/main.py:79
#: src/modules/mount/main.py:146 src/modules/luksopenswaphookcfg/main.py:96
#: src/modules/fstab/main.py:333 src/modules/initramfscfg/main.py:95
#: src/modules/rawfs/main.py:172
msgid "No partitions are defined for <pre>{!s}</pre> to use."
msgstr ""
#: src/modules/openrcdmcryptcfg/main.py:34
msgid "Configuring OpenRC dmcrypt service."
msgstr ""
#: src/modules/unpackfs/main.py:44
msgid "Filling up filesystems."
msgstr ""
#: src/modules/unpackfs/main.py:257
msgid "rsync failed with error code {}."
msgstr ""
#: src/modules/unpackfs/main.py:302
msgid "Unpacking image {}/{}, file {}/{}"
msgstr ""
#: src/modules/unpackfs/main.py:317
msgid "Starting to unpack {}"
msgstr ""
#: src/modules/unpackfs/main.py:326 src/modules/unpackfs/main.py:432
msgid "Failed to unpack image \"{}\""
msgstr ""
#: src/modules/unpackfs/main.py:399
msgid "No mount point for root partition"
msgstr ""
#: src/modules/unpackfs/main.py:400
msgid "globalstorage does not contain a \"rootMountPoint\" key, doing nothing"
msgstr ""
#: src/modules/unpackfs/main.py:405
msgid "Bad mount point for root partition"
msgstr ""
#: src/modules/unpackfs/main.py:406
msgid "rootMountPoint is \"{}\", which does not exist, doing nothing"
msgstr ""
#: src/modules/unpackfs/main.py:422 src/modules/unpackfs/main.py:426
#: src/modules/unpackfs/main.py:446
msgid "Bad unsquash configuration"
msgstr ""
#: src/modules/unpackfs/main.py:423
msgid "The filesystem for \"{}\" ({}) is not supported by your current kernel"
msgstr ""
#: src/modules/unpackfs/main.py:427
msgid "The source filesystem \"{}\" does not exist"
msgstr ""
#: src/modules/unpackfs/main.py:433
msgid ""
"Failed to find unsquashfs, make sure you have the squashfs-tools package "
"installed"
msgstr ""
#: src/modules/unpackfs/main.py:447
msgid "The destination \"{}\" in the target system is not a directory"
msgstr ""
#: src/modules/services-systemd/main.py:35
msgid "Configure systemd services"
msgstr ""
#: src/modules/services-systemd/main.py:68
#: src/modules/services-openrc/main.py:102
msgid "Cannot modify service"
msgstr ""
#: src/modules/services-systemd/main.py:69
msgid ""
"<code>systemctl {arg!s}</code> call in chroot returned error code {num!s}."
msgstr ""
#: src/modules/services-systemd/main.py:72
#: src/modules/services-systemd/main.py:76
msgid "Cannot enable systemd service <code>{name!s}</code>."
msgstr ""
#: src/modules/services-systemd/main.py:74
msgid "Cannot enable systemd target <code>{name!s}</code>."
msgstr ""
#: src/modules/services-systemd/main.py:78
msgid "Cannot disable systemd target <code>{name!s}</code>."
msgstr ""
#: src/modules/services-systemd/main.py:80
msgid "Cannot mask systemd unit <code>{name!s}</code>."
msgstr ""
#: src/modules/services-systemd/main.py:82
msgid ""
"Unknown systemd commands <code>{command!s}</code> and "
"<code>{suffix!s}</code> for unit {name!s}."
msgstr ""
#: src/modules/dummypython/main.py:44
msgid "Dummy python job."
msgstr ""
#: src/modules/dummypython/main.py:46 src/modules/dummypython/main.py:102
#: src/modules/dummypython/main.py:103
msgid "Dummy python step {}"
msgstr ""
#: src/modules/bootloader/main.py:51
msgid "Install bootloader."
msgstr ""
#: src/modules/localecfg/main.py:39
msgid "Configuring locales."
msgstr ""
#: src/modules/mount/main.py:38
msgid "Mounting partitions."
msgstr ""
#: src/modules/plymouthcfg/main.py:36
msgid "Configure Plymouth theme"
msgstr ""
#: src/modules/luksopenswaphookcfg/main.py:35
msgid "Configuring encrypted swap."
msgstr ""
#: src/modules/fstab/main.py:38
msgid "Writing fstab."
msgstr ""
#: src/modules/services-openrc/main.py:38
msgid "Configure OpenRC services"
msgstr ""
#: src/modules/services-openrc/main.py:66
msgid "Cannot add service {name!s} to run-level {level!s}."
msgstr ""
#: src/modules/services-openrc/main.py:68
msgid "Cannot remove service {name!s} from run-level {level!s}."
msgstr ""
#: src/modules/services-openrc/main.py:70
msgid ""
"Unknown service-action <code>{arg!s}</code> for service {name!s} in run-"
"level {level!s}."
msgstr ""
#: src/modules/services-openrc/main.py:103
msgid ""
"<code>rc-update {arg!s}</code> call in chroot returned error code {num!s}."
msgstr ""
#: src/modules/services-openrc/main.py:110
msgid "Target runlevel does not exist"
msgstr ""
#: src/modules/services-openrc/main.py:111
msgid ""
"The path for runlevel {level!s} is <code>{path!s}</code>, which does not "
"exist."
msgstr ""
#: src/modules/services-openrc/main.py:119
msgid "Target service does not exist"
msgstr ""
#: src/modules/services-openrc/main.py:120
msgid ""
"The path for service {name!s} is <code>{path!s}</code>, which does not "
"exist."
msgstr ""
#: src/modules/dracut/main.py:36
msgid "Creating initramfs with dracut."
msgstr ""
#: src/modules/dracut/main.py:58
msgid "Failed to run dracut on the target"
msgstr ""
#: src/modules/dracut/main.py:59
msgid "The exit code was {}"
msgstr ""
#: src/modules/grubcfg/main.py:37
msgid "Configure GRUB."
msgstr ""
#: src/modules/displaymanager/main.py:515
msgid "Cannot write KDM configuration file"
msgstr ""
#: src/modules/displaymanager/main.py:516
msgid "KDM config file {!s} does not exist"
msgstr ""
#: src/modules/displaymanager/main.py:577
msgid "Cannot write LXDM configuration file"
msgstr ""
#: src/modules/displaymanager/main.py:578
msgid "LXDM config file {!s} does not exist"
msgstr ""
#: src/modules/displaymanager/main.py:661
msgid "Cannot write LightDM configuration file"
msgstr ""
#: src/modules/displaymanager/main.py:662
msgid "LightDM config file {!s} does not exist"
msgstr ""
#: src/modules/displaymanager/main.py:736
msgid "Cannot configure LightDM"
msgstr ""
#: src/modules/displaymanager/main.py:737
msgid "No LightDM greeter installed."
msgstr ""
#: src/modules/displaymanager/main.py:768
msgid "Cannot write SLIM configuration file"
msgstr ""
#: src/modules/displaymanager/main.py:769
msgid "SLIM config file {!s} does not exist"
msgstr ""
#: src/modules/displaymanager/main.py:895
msgid "No display managers selected for the displaymanager module."
msgstr ""
#: src/modules/displaymanager/main.py:896
msgid ""
"The displaymanagers list is empty or undefined in bothglobalstorage and "
"displaymanager.conf."
msgstr ""
#: src/modules/displaymanager/main.py:978
msgid "Display manager configuration was incomplete"
msgstr ""
#: src/modules/initramfscfg/main.py:41
msgid "Configuring initramfs."
msgstr ""
#: src/modules/hwclock/main.py:35
msgid "Setting hardware clock."
msgstr ""
#: src/modules/rawfs/main.py:35
msgid "Installing data."
msgstr ""

Binary file not shown.

View File

@ -0,0 +1,336 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-04-30 23:13+0200\n"
"PO-Revision-Date: 2017-08-09 10:34+0000\n"
"Language-Team: Azerbaijani (Azerbaijan) (https://www.transifex.com/calamares/teams/20061/az_AZ/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: az_AZ\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: src/modules/packages/main.py:59 src/modules/packages/main.py:68
#: src/modules/packages/main.py:78
msgid "Install packages."
msgstr ""
#: src/modules/packages/main.py:66
#, python-format
msgid "Processing packages (%(count)d / %(total)d)"
msgstr ""
#: src/modules/packages/main.py:71
#, python-format
msgid "Installing one package."
msgid_plural "Installing %(num)d packages."
msgstr[0] ""
msgstr[1] ""
#: src/modules/packages/main.py:74
#, python-format
msgid "Removing one package."
msgid_plural "Removing %(num)d packages."
msgstr[0] ""
msgstr[1] ""
#: src/modules/networkcfg/main.py:37
msgid "Saving network configuration."
msgstr ""
#: src/modules/networkcfg/main.py:48 src/modules/initcpiocfg/main.py:205
#: src/modules/initcpiocfg/main.py:209 src/modules/openrcdmcryptcfg/main.py:78
#: src/modules/openrcdmcryptcfg/main.py:82 src/modules/localecfg/main.py:144
#: src/modules/mount/main.py:145 src/modules/luksopenswaphookcfg/main.py:95
#: src/modules/luksopenswaphookcfg/main.py:99 src/modules/fstab/main.py:332
#: src/modules/fstab/main.py:338 src/modules/initramfscfg/main.py:94
#: src/modules/initramfscfg/main.py:98 src/modules/rawfs/main.py:171
msgid "Configuration Error"
msgstr ""
#: src/modules/networkcfg/main.py:49 src/modules/initcpiocfg/main.py:210
#: src/modules/openrcdmcryptcfg/main.py:83 src/modules/localecfg/main.py:145
#: src/modules/luksopenswaphookcfg/main.py:100 src/modules/fstab/main.py:339
#: src/modules/initramfscfg/main.py:99
msgid "No root mount point is given for <pre>{!s}</pre> to use."
msgstr ""
#: src/modules/umount/main.py:40
msgid "Unmount file systems."
msgstr ""
#: src/modules/initcpiocfg/main.py:37
msgid "Configuring mkinitcpio."
msgstr ""
#: src/modules/initcpiocfg/main.py:206 src/modules/openrcdmcryptcfg/main.py:79
#: src/modules/mount/main.py:146 src/modules/luksopenswaphookcfg/main.py:96
#: src/modules/fstab/main.py:333 src/modules/initramfscfg/main.py:95
#: src/modules/rawfs/main.py:172
msgid "No partitions are defined for <pre>{!s}</pre> to use."
msgstr ""
#: src/modules/openrcdmcryptcfg/main.py:34
msgid "Configuring OpenRC dmcrypt service."
msgstr ""
#: src/modules/unpackfs/main.py:44
msgid "Filling up filesystems."
msgstr ""
#: src/modules/unpackfs/main.py:257
msgid "rsync failed with error code {}."
msgstr ""
#: src/modules/unpackfs/main.py:302
msgid "Unpacking image {}/{}, file {}/{}"
msgstr ""
#: src/modules/unpackfs/main.py:317
msgid "Starting to unpack {}"
msgstr ""
#: src/modules/unpackfs/main.py:326 src/modules/unpackfs/main.py:432
msgid "Failed to unpack image \"{}\""
msgstr ""
#: src/modules/unpackfs/main.py:399
msgid "No mount point for root partition"
msgstr ""
#: src/modules/unpackfs/main.py:400
msgid "globalstorage does not contain a \"rootMountPoint\" key, doing nothing"
msgstr ""
#: src/modules/unpackfs/main.py:405
msgid "Bad mount point for root partition"
msgstr ""
#: src/modules/unpackfs/main.py:406
msgid "rootMountPoint is \"{}\", which does not exist, doing nothing"
msgstr ""
#: src/modules/unpackfs/main.py:422 src/modules/unpackfs/main.py:426
#: src/modules/unpackfs/main.py:446
msgid "Bad unsquash configuration"
msgstr ""
#: src/modules/unpackfs/main.py:423
msgid "The filesystem for \"{}\" ({}) is not supported by your current kernel"
msgstr ""
#: src/modules/unpackfs/main.py:427
msgid "The source filesystem \"{}\" does not exist"
msgstr ""
#: src/modules/unpackfs/main.py:433
msgid ""
"Failed to find unsquashfs, make sure you have the squashfs-tools package "
"installed"
msgstr ""
#: src/modules/unpackfs/main.py:447
msgid "The destination \"{}\" in the target system is not a directory"
msgstr ""
#: src/modules/services-systemd/main.py:35
msgid "Configure systemd services"
msgstr ""
#: src/modules/services-systemd/main.py:68
#: src/modules/services-openrc/main.py:102
msgid "Cannot modify service"
msgstr ""
#: src/modules/services-systemd/main.py:69
msgid ""
"<code>systemctl {arg!s}</code> call in chroot returned error code {num!s}."
msgstr ""
#: src/modules/services-systemd/main.py:72
#: src/modules/services-systemd/main.py:76
msgid "Cannot enable systemd service <code>{name!s}</code>."
msgstr ""
#: src/modules/services-systemd/main.py:74
msgid "Cannot enable systemd target <code>{name!s}</code>."
msgstr ""
#: src/modules/services-systemd/main.py:78
msgid "Cannot disable systemd target <code>{name!s}</code>."
msgstr ""
#: src/modules/services-systemd/main.py:80
msgid "Cannot mask systemd unit <code>{name!s}</code>."
msgstr ""
#: src/modules/services-systemd/main.py:82
msgid ""
"Unknown systemd commands <code>{command!s}</code> and "
"<code>{suffix!s}</code> for unit {name!s}."
msgstr ""
#: src/modules/dummypython/main.py:44
msgid "Dummy python job."
msgstr ""
#: src/modules/dummypython/main.py:46 src/modules/dummypython/main.py:102
#: src/modules/dummypython/main.py:103
msgid "Dummy python step {}"
msgstr ""
#: src/modules/bootloader/main.py:51
msgid "Install bootloader."
msgstr ""
#: src/modules/localecfg/main.py:39
msgid "Configuring locales."
msgstr ""
#: src/modules/mount/main.py:38
msgid "Mounting partitions."
msgstr ""
#: src/modules/plymouthcfg/main.py:36
msgid "Configure Plymouth theme"
msgstr ""
#: src/modules/luksopenswaphookcfg/main.py:35
msgid "Configuring encrypted swap."
msgstr ""
#: src/modules/fstab/main.py:38
msgid "Writing fstab."
msgstr ""
#: src/modules/services-openrc/main.py:38
msgid "Configure OpenRC services"
msgstr ""
#: src/modules/services-openrc/main.py:66
msgid "Cannot add service {name!s} to run-level {level!s}."
msgstr ""
#: src/modules/services-openrc/main.py:68
msgid "Cannot remove service {name!s} from run-level {level!s}."
msgstr ""
#: src/modules/services-openrc/main.py:70
msgid ""
"Unknown service-action <code>{arg!s}</code> for service {name!s} in run-"
"level {level!s}."
msgstr ""
#: src/modules/services-openrc/main.py:103
msgid ""
"<code>rc-update {arg!s}</code> call in chroot returned error code {num!s}."
msgstr ""
#: src/modules/services-openrc/main.py:110
msgid "Target runlevel does not exist"
msgstr ""
#: src/modules/services-openrc/main.py:111
msgid ""
"The path for runlevel {level!s} is <code>{path!s}</code>, which does not "
"exist."
msgstr ""
#: src/modules/services-openrc/main.py:119
msgid "Target service does not exist"
msgstr ""
#: src/modules/services-openrc/main.py:120
msgid ""
"The path for service {name!s} is <code>{path!s}</code>, which does not "
"exist."
msgstr ""
#: src/modules/dracut/main.py:36
msgid "Creating initramfs with dracut."
msgstr ""
#: src/modules/dracut/main.py:58
msgid "Failed to run dracut on the target"
msgstr ""
#: src/modules/dracut/main.py:59
msgid "The exit code was {}"
msgstr ""
#: src/modules/grubcfg/main.py:37
msgid "Configure GRUB."
msgstr ""
#: src/modules/displaymanager/main.py:515
msgid "Cannot write KDM configuration file"
msgstr ""
#: src/modules/displaymanager/main.py:516
msgid "KDM config file {!s} does not exist"
msgstr ""
#: src/modules/displaymanager/main.py:577
msgid "Cannot write LXDM configuration file"
msgstr ""
#: src/modules/displaymanager/main.py:578
msgid "LXDM config file {!s} does not exist"
msgstr ""
#: src/modules/displaymanager/main.py:661
msgid "Cannot write LightDM configuration file"
msgstr ""
#: src/modules/displaymanager/main.py:662
msgid "LightDM config file {!s} does not exist"
msgstr ""
#: src/modules/displaymanager/main.py:736
msgid "Cannot configure LightDM"
msgstr ""
#: src/modules/displaymanager/main.py:737
msgid "No LightDM greeter installed."
msgstr ""
#: src/modules/displaymanager/main.py:768
msgid "Cannot write SLIM configuration file"
msgstr ""
#: src/modules/displaymanager/main.py:769
msgid "SLIM config file {!s} does not exist"
msgstr ""
#: src/modules/displaymanager/main.py:895
msgid "No display managers selected for the displaymanager module."
msgstr ""
#: src/modules/displaymanager/main.py:896
msgid ""
"The displaymanagers list is empty or undefined in bothglobalstorage and "
"displaymanager.conf."
msgstr ""
#: src/modules/displaymanager/main.py:978
msgid "Display manager configuration was incomplete"
msgstr ""
#: src/modules/initramfscfg/main.py:41
msgid "Configuring initramfs."
msgstr ""
#: src/modules/hwclock/main.py:35
msgid "Setting hardware clock."
msgstr ""
#: src/modules/rawfs/main.py:35
msgid "Installing data."
msgstr ""

Binary file not shown.

View File

@ -4,7 +4,7 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
# Translators:
# Panwar108 <caspian7pena@gmail.com>, 2019
# Panwar108 <caspian7pena@gmail.com>, 2020
#
#, fuzzy
msgid ""
@ -13,7 +13,7 @@ msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-04-30 23:13+0200\n"
"PO-Revision-Date: 2017-08-09 10:34+0000\n"
"Last-Translator: Panwar108 <caspian7pena@gmail.com>, 2019\n"
"Last-Translator: Panwar108 <caspian7pena@gmail.com>, 2020\n"
"Language-Team: Hindi (https://www.transifex.com/calamares/teams/20061/hi/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -84,7 +84,7 @@ msgstr "<pre>{!s}</pre> के उपयोग हेतु कोई विभ
#: src/modules/openrcdmcryptcfg/main.py:34
msgid "Configuring OpenRC dmcrypt service."
msgstr "OpenRC dmcrypt सेवा को विन्यस्त करना।"
msgstr "OpenRC dmcrypt सेवा विन्यस्त करना।"
#: src/modules/unpackfs/main.py:44
msgid "Filling up filesystems."
@ -96,11 +96,11 @@ msgstr "rsync त्रुटि कोड {} के साथ विफल।"
#: src/modules/unpackfs/main.py:302
msgid "Unpacking image {}/{}, file {}/{}"
msgstr ""
msgstr "इमेज फ़ाइल {}/{}, फ़ाइल {}/{} सम्पीड़ित की जा रही है"
#: src/modules/unpackfs/main.py:317
msgid "Starting to unpack {}"
msgstr ""
msgstr "{} हेतु संपीड़न प्रक्रिया आरंभ हो रही है "
#: src/modules/unpackfs/main.py:326 src/modules/unpackfs/main.py:432
msgid "Failed to unpack image \"{}\""
@ -129,7 +129,7 @@ msgstr "ख़राब unsquash विन्यास सेटिंग्स"
#: src/modules/unpackfs/main.py:423
msgid "The filesystem for \"{}\" ({}) is not supported by your current kernel"
msgstr ""
msgstr "\"{}\" ({}) हेतु फ़ाइल सिस्टम आपके वर्तमान कर्नेल द्वारा समर्थित नहीं है"
#: src/modules/unpackfs/main.py:427
msgid "The source filesystem \"{}\" does not exist"

View File

@ -1,5 +1,5 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
*
* SPDX-FileCopyrightText: 2013-2016 Teo Mrnjavac <teo@kde.org>
* SPDX-FileCopyrightText: 2018 Adriaan de Groot <groot@kde.org>
*
@ -65,6 +65,20 @@ getString( const QVariantMap& map, const QString& key )
return QString();
}
QStringList
getStringList( const QVariantMap& map, const QString& key )
{
if ( map.contains( key ) )
{
auto v = map.value( key );
if ( v.type() == QVariant::StringList )
{
return v.toStringList();
}
}
return QStringList();
}
qint64
getInteger( const QVariantMap& map, const QString& key, qint64 d )
{
@ -72,14 +86,20 @@ getInteger( const QVariantMap& map, const QString& key, qint64 d )
if ( map.contains( key ) )
{
auto v = map.value( key );
if ( v.type() == QVariant::Int )
{
result = v.toInt();
}
else if ( v.type() == QVariant::LongLong )
{
result = v.toLongLong();
}
result = v.toString().toLongLong(nullptr, 0);
}
return result;
}
quint64
getUnsignedInteger( const QVariantMap& map, const QString& key, quint64 u )
{
quint64 result = u;
if ( map.contains( key ) )
{
auto v = map.value( key );
result = v.toString().toULongLong(nullptr, 0);
}
return result;

View File

@ -1,5 +1,5 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
*
* SPDX-FileCopyrightText: 2013-2016 Teo Mrnjavac <teo@kde.org>
* SPDX-FileCopyrightText: 2018 Adriaan de Groot <groot@kde.org>
*
@ -43,11 +43,21 @@ DLLEXPORT bool getBool( const QVariantMap& map, const QString& key, bool d );
*/
DLLEXPORT QString getString( const QVariantMap& map, const QString& key );
/**
* Get a string list from a mapping; returns empty list if no value.
*/
DLLEXPORT QStringList getStringList( const QVariantMap& map, const QString& key );
/**
* Get an integer value from a mapping; returns @p d if no value.
*/
DLLEXPORT qint64 getInteger( const QVariantMap& map, const QString& key, qint64 d );
/**
* Get an unsigned integer value from a mapping; returns @p u if no value.
*/
DLLEXPORT quint64 getUnsignedInteger( const QVariantMap& map, const QString& key, quint64 u );
/**
* Get a double value from a mapping (integers are converted); returns @p d if no value.
*/

View File

@ -66,3 +66,21 @@ endforeach()
include( CalamaresAddTranslations )
add_calamares_python_translations( ${CALAMARES_TRANSLATION_LANGUAGES} )
# TODO:3.3: Use FindPython3
if ( BUILD_TESTING AND BUILD_SCHEMA_TESTING AND PYTHONINTERP_FOUND AND PYTHON_EXECUTABLE )
# The tests for each config file are independent of whether the
# module is enabled or not: the config file should match its schema
# regardless.
foreach( SUBDIRECTORY ${SUBDIRECTORIES} )
set( _schema_file "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIRECTORY}/${SUBDIRECTORY}.schema.yaml" )
set( _conf_file "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIRECTORY}/${SUBDIRECTORY}.conf" )
if ( EXISTS "${_schema_file}" AND EXISTS "${_conf_file}" )
add_test(
NAME validate-${SUBDIRECTORY}
COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_SOURCE_DIR}/ci/configvalidator.py" "${_schema_file}" "${_conf_file}"
)
endif()
endforeach()
endif()

View File

@ -0,0 +1,33 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/bootloader
additionalProperties: false
type: object
properties:
efiBootLoader: { type: string }
kernel: { type: string }
img: { type: string }
fallback: { type: string }
timeout: { type: string } # Inserted verbatim
bootloaderEntryName: { type: string }
kernelLine: { type: string }
fallbackKernelLine: { type: string }
# Programs
grubInstall: { type: string }
grubMkconfig: { type: string }
grubCfg: { type: string }
grubProbe: { type: string }
efiBootMgr: { type: string }
efiBootloaderId: { type: string }
installEFIFallback: { type: boolean }
required:
- efiBootLoader
- kernel
- img
- grubInstall
- grubMkconfig
- grubCfg
- grubProbe

View File

@ -0,0 +1,16 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/displaymanager
additionalProperties: false
type: object
properties:
"displaymanagers":
type: seq
sequence:
- { type: string, required: true, enum: [slim, sddm, lightdm, gdm, mdm, lxdm, kdm] }
"defaultDesktopEnvironment":
type: map
mapping:
"executable": { type: str }
"desktopFile": { type: str }
"basicSetup": { type: boolean, default: false }

View File

@ -2,41 +2,41 @@
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-04-30 23:13+0200\n"
"POT-Creation-Date: 2020-06-18 15:42+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: \n"
#: src/modules/dummypythonqt/main.py:84
msgid "Click me!"
msgstr "Click me!"
msgstr ""
#: src/modules/dummypythonqt/main.py:94
msgid "A new QLabel."
msgstr "A new QLabel."
msgstr ""
#: src/modules/dummypythonqt/main.py:97
msgid "Dummy PythonQt ViewStep"
msgstr "Dummy PythonQt ViewStep"
msgstr ""
#: src/modules/dummypythonqt/main.py:183
msgid "The Dummy PythonQt Job"
msgstr "The Dummy PythonQt Job"
msgstr ""
#: src/modules/dummypythonqt/main.py:186
msgid "This is the Dummy PythonQt Job. The dummy job says: {}"
msgstr "This is the Dummy PythonQt Job. The dummy job says: {}"
msgstr ""
#: src/modules/dummypythonqt/main.py:190
msgid "A status message for Dummy PythonQt Job."
msgstr "A status message for Dummy PythonQt Job."
msgstr ""

View File

@ -0,0 +1,11 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/finished
additionalProperties: false
type: object
properties:
restartNowEnabled: { type: boolean, default: true } # TODO:3.3: remove
restartNowChecked: { type: boolean, default: false } # TODO:3.3: remove
restartNowCommand: { type: string }
restartNowMode: { type: string, enum: [ never, user-unchecked, user-checked, always ] }
notifyOnFinished: { type: boolean }

View File

@ -0,0 +1,19 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/fstab
additionalProperties: false
type: object
properties:
"mountOptions":
type: map
mapping:
"default": { type: string, required: true }
"btrfs": { type: string, required: true }
"ssdExtraMountOptions":
type: map
mapping:
"ext4": { type: string, required: true }
"jfs": { type: string, required: true }
"xfs": { type: string, required: true }
"swap": { type: string, required: true }
"btrfs": { type: string, required: true }

View File

@ -0,0 +1,15 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/grubcfg
additionalProperties: false
type: object
properties:
"overwrite": { type: boolean, default: false }
"defaults":
type: map
mapping:
"GRUB_TIMEOUT": { type: int, required: true }
"GRUB_DEFAULT": { type: string, required: true }
"GRUB_DISABLE_SUBMENU": { type: boolean, default: true }
"GRUB_TERMINAL_OUTPUT": { type: string, required: true }
"GRUB_DISABLE_RECOVERY": { type: boolean, default: true }

View File

@ -0,0 +1,7 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/initcpio
additionalProperties: false
type: object
properties:
kernel: { type: string, required: true }

View File

@ -0,0 +1,8 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/finished
additionalProperties: keyboard
type: object
properties:
xOrgConfFileName: { type: string, required: true }
convertedKeymapPath: { type: string, required: true }

View File

@ -0,0 +1,17 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/license
additionalProperties: false
type: object
properties:
"entries":
type: seq
sequence:
- type: map
mapping:
"id": { type: str }
"name": { type: str }
"vendor": { type: str }
"type": { type: str }
"url": { type: str }
"required": { type: boolean, default: false }

View File

@ -0,0 +1,10 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/locale
additionalProperties: false
type: object
properties:
"region": { type: str }
"zone": { type: str }
"localeGenPath": { type: string, required: true }
"geoipUrl": { type: str }

View File

@ -34,6 +34,32 @@ Page {
//Needs to come from .conf/geoip
property var hasInternet: true
function getInt(format) {
var requestURL = "https://example.org/";
var xhr = new XMLHttpRequest;
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status !== 200) {
console.log("Disconnected!!");
var connected = false
hasInternet = connected
return;
}
else {
console.log("Connected!!");
}
}
}
xhr.open("GET", requestURL, true);
xhr.send();
}
Component.onCompleted: {
getInt();
}
Loader {
id: image
anchors.horizontalCenter: parent.horizontalCenter

View File

@ -0,0 +1,7 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/luksopenswaphookcfg
additionalProperties: false
type: object
properties:
"configFilePath": { type: string, required: true }

View File

@ -0,0 +1,9 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/machineid
additionalProperties: false
type: object
properties:
"systemd": { type: boolean, default: true }
"dbus": { type: boolean, default: true }
"symlink": { type: boolean, default: true }

View File

@ -0,0 +1,24 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/mount
additionalProperties: false
type: object
properties:
"extraMounts":
type: seq
sequence:
- type: map
mapping:
"device": { type: string, required: true }
"fs": { type: str }
"mountPoint": { type: string, required: true }
"options": { type: str }
"extraMountsEfi":
type: seq
sequence:
- type: map
mapping:
"device": { type: string, required: true }
"fs": { type: str }
"mountPoint": { type: string, required: true }
"options": { type: str }

View File

@ -0,0 +1,7 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/netinstall
additionalProperties: false
type: object
properties:
groupsUrl: { type: string, required: true }

View File

@ -5,6 +5,7 @@ set( _extra_src "" )
### OPTIONAL AppData XML support in PackageModel
#
#
# TODO:3.3:WITH->BUILD (this doesn't affect the ABI offered by Calamares)
option( WITH_APPDATA "Support appdata: items in PackageChooser (requires QtXml)" ON )
if ( WITH_APPDATA )
find_package(Qt5 COMPONENTS Xml)

View File

@ -0,0 +1,33 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/packages
additionalProperties: false
type: object
properties:
"backend": { type: string, required: true, enum: [packagekit, zypp, yum, dnf, urpmi, apt, pacman, portage, entropy] }
"update_db": { type: boolean, default: true }
"operations":
type: seq
sequence:
- type: map
mapping:
"install":
type: seq
sequence:
- { type: text }
"remove":
type: seq
sequence:
- { type: text }
"localInstall":
type: seq
sequence:
- { type: text }
"try_install":
type: seq
sequence:
- { type: text }
"try_remove":
type: seq
sequence:
- { type: text }

View File

@ -883,7 +883,9 @@ PartitionCoreModule::initLayout( const QVariantList& config )
}
if ( !m_partLayout->addEntry( CalamaresUtils::getString( pentry, "name" ),
CalamaresUtils::getString( pentry, "uuid" ),
CalamaresUtils::getString( pentry, "type" ),
CalamaresUtils::getUnsignedInteger( pentry, "attributes", 0 ),
CalamaresUtils::getString( pentry, "mountPoint" ),
CalamaresUtils::getString( pentry, "filesystem" ),
CalamaresUtils::getSubMap( pentry, "features", ok ),

View File

@ -118,7 +118,9 @@ PartitionLayout::addEntry( const QString& mountPoint, const QString& size, const
bool
PartitionLayout::addEntry( const QString& label,
const QString& uuid,
const QString& type,
quint64 attributes,
const QString& mountPoint,
const QString& fs,
const QVariantMap& features,
@ -140,7 +142,9 @@ PartitionLayout::addEntry( const QString& label,
}
entry.partLabel = label;
entry.partUUID = uuid;
entry.partType = type;
entry.partAttributes = attributes;
entry.partMountPoint = mountPoint;
PartUtils::findFS( fs, &entry.partFileSystem );
if ( entry.partFileSystem == FileSystem::Unknown )
@ -244,12 +248,24 @@ PartitionLayout::execute( Device* dev,
currentPartition->setLabel( part.partLabel );
currentPartition->fileSystem().setLabel( part.partLabel );
}
if ( !part.partUUID.isEmpty() )
{
currentPartition->setUUID( part.partUUID );
}
if ( !part.partType.isEmpty() )
{
#if defined( WITH_KPMCORE42API )
currentPartition->setType( part.partType );
#else
cWarning() << "Ignoring type; requires KPMcore >= 4.2.0.";
#endif
}
if ( part.partAttributes )
{
#if defined( WITH_KPMCORE42API )
currentPartition->setAttributes( part.partAttributes );
#else
cWarning() << "Ignoring attributes; requires KPMcore >= 4.2.0.";
#endif
}
if ( !part.partFeatures.isEmpty() )

View File

@ -41,7 +41,9 @@ public:
struct PartitionEntry
{
QString partLabel;
QString partUUID;
QString partType;
quint64 partAttributes;
QString partMountPoint;
FileSystem::Type partFileSystem = FileSystem::Unknown;
QVariantMap partFeatures;
@ -76,7 +78,9 @@ public:
const QString& min = QString(),
const QString& max = QString() );
bool addEntry( const QString& label,
const QString& uuid,
const QString& type,
quint64 attributes,
const QString& mountPoint,
const QString& fs,
const QVariantMap& features,

View File

@ -91,6 +91,8 @@ mapForPartition( Partition* partition, const QString& uuid )
{
QVariantMap map;
map[ "device" ] = partition->partitionPath();
map[ "partlabel" ] = partition->label();
map[ "partuuid" ] = partition->uuid();
map[ "mountPoint" ] = PartitionInfo::mountPoint( partition );
map[ "fsName" ] = userVisibleFS( partition->fileSystem() );
map[ "fs" ] = untranslatedFS( partition->fileSystem() );
@ -107,6 +109,7 @@ mapForPartition( Partition* partition, const QString& uuid )
Logger::CDebug deb;
using TR = Logger::DebugRow< const char* const, const QString& >;
deb << Logger::SubEntry << "mapping for" << partition->partitionPath() << partition->deviceNode()
<< TR( "partlabel", map[ "partlabel" ].toString() ) << TR( "partuuid", map[ "partuuid" ].toString() )
<< TR( "mountPoint:", PartitionInfo::mountPoint( partition ) ) << TR( "fs:", map[ "fs" ].toString() )
<< TR( "fsName", map[ "fsName" ].toString() ) << TR( "uuid", uuid )
<< TR( "claimed", map[ "claimed" ].toString() );

View File

@ -106,6 +106,7 @@ defaultFileSystemType: "ext4"
# size: 20%
# minSize: 500M
# maxSize: 10G
# attributes: 0xffff000000000003
# - name: "home"
# type = "933ac7e1-2eb4-4f13-b844-0e14e2aef915"
# filesystem: "ext4"
@ -127,7 +128,9 @@ defaultFileSystemType: "ext4"
# - name: filesystem label
# and
# partition name (gpt only; since KPMCore 4.2.0)
# - uuid: partition uuid (optional parameter; gpt only; requires KPMCore >= 4.2.0)
# - type: partition type (optional parameter; gpt only; requires KPMCore >= 4.2.0)
# - attributes: partition attributes (optional parameter; gpt only; requires KPMCore >= 4.2.0)
# - filesystem: filesystem type
# - mountPoint: partition mount point
# - size: partition size in bytes (append 'K', 'M' or 'G' for KiB, MiB or GiB)

View File

@ -0,0 +1,11 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/partition
additionalProperties: false
type: object
properties:
efiSystemPartition: { type: string, required: true }
ensureSuspendToDisk: { type: boolean, default: true }
drawNestedPartitions: { type: boolean, default: false }
alwaysShowPartitionLabels: { type: boolean, default: true }
defaultFileSystemType: { type: string, required: true }

View File

@ -0,0 +1,7 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/plymouthcfg
additionalProperties: false
type: object
properties:
plymouth_theme: { type: str }

View File

@ -0,0 +1,7 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/removeuser
additionalProperties: false
type: object
properties:
"username": { type: string, required: true }

View File

@ -2,6 +2,7 @@ calamares_add_plugin( tracking
TYPE viewmodule
EXPORT_MACRO PLUGINDLLEXPORT_PRO
SOURCES
Config.cpp
TrackingJobs.cpp
TrackingPage.cpp
TrackingViewStep.cpp

View File

@ -0,0 +1,256 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2020, Adriaan de Groot <groot@kde.org>
*
* Calamares is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Calamares is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Config.h"
#include "TrackingType.h"
#include "utils/Logger.h"
#include "utils/Variant.h"
#include <QUrl>
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 = CalamaresUtils::getBool( config, "enabled", false ) ? DisabledByUser : DisabledByConfig;
m_policy = CalamaresUtils::getString( config, "policy" );
validateUrl( m_policy );
emit policyChanged( m_policy );
emit trackingChanged();
}
InstallTrackingConfig::InstallTrackingConfig( QObject* parent )
: TrackingStyleConfig( parent )
{
setObjectName( "InstallTrackingConfig" );
}
void
InstallTrackingConfig::setConfigurationMap( const QVariantMap& configurationMap )
{
TrackingStyleConfig::setConfigurationMap( configurationMap );
m_installTrackingUrl = CalamaresUtils::getString( configurationMap, "url" );
validateUrl( m_installTrackingUrl );
}
MachineTrackingConfig::MachineTrackingConfig( QObject* parent )
: TrackingStyleConfig( parent )
{
setObjectName( "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 = CalamaresUtils::getString( configurationMap, "style" );
validate( m_machineTrackingStyle, isValidMachineTrackingStyle );
}
UserTrackingConfig::UserTrackingConfig( QObject* parent )
: TrackingStyleConfig( parent )
{
setObjectName( "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 = CalamaresUtils::getString( configurationMap, "style" );
validate( m_userTrackingStyle, isValidUserTrackingStyle );
m_userTrackingAreas = CalamaresUtils::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 );
FALLTHRU;
case TrackingType::MachineTracking:
config->machineTracking()->setTracking( TrackingStyleConfig::TrackingState::EnabledByUser );
FALLTHRU;
case TrackingType::InstallTracking:
config->installTracking()->setTracking( TrackingStyleConfig::TrackingState::EnabledByUser );
break;
case TrackingType::NoTracking:
config->noTracking( true );
break;
}
}
void
Config::setConfigurationMap( const QVariantMap& configurationMap )
{
m_generalPolicy = CalamaresUtils::getString( configurationMap, "policy" );
if ( !QUrl( m_generalPolicy ).isValid() )
{
m_generalPolicy = QString();
}
emit generalPolicyChanged( m_generalPolicy );
bool success = false;
auto subconfig = CalamaresUtils::getSubMap( configurationMap, "install", success );
if ( success )
{
m_installTracking->setConfigurationMap( subconfig );
}
subconfig = CalamaresUtils::getSubMap( configurationMap, "machine", success );
if ( success )
{
m_machineTracking->setConfigurationMap( subconfig );
}
subconfig = CalamaresUtils::getSubMap( configurationMap, "user", success );
if ( success )
{
m_userTracking->setConfigurationMap( subconfig );
}
auto level = trackingNames().find( CalamaresUtils::getString( configurationMap, "default" ), success );
if ( !success )
{
cWarning() << "Default tracking level unknown:" << CalamaresUtils::getString( configurationMap, "default" );
level = TrackingType::NoTracking;
}
enableLevelsBelow( this, level );
}
QString
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 );
}

View File

@ -0,0 +1,192 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2020, Adriaan de Groot <groot@kde.org>
*
* Calamares is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Calamares is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TRACKING_CONFIG_H
#define TRACKING_CONFIG_H
#include <QObject>
#include <QString>
#include <QVariantMap>
/** @brief Base class for configuring a specific kind of tracking.
*
* All tracking types have a policy URL, which is used to explain what
* kind of tracking is involved, what data is sent, etc. The content
* of that URL is the responsibility of the distro.
*
* A tracking type is disabled by default: if it isn't specifically
* enabled (for configuration) in the config file, it will always be disabled.
* If it is enabled (for configuration) in the config file, it still
* defaults to disabled, but the user can choose to enable it.
*/
class TrackingStyleConfig : public QObject
{
Q_OBJECT
Q_PROPERTY( TrackingState trackingStatus READ tracking WRITE setTracking NOTIFY trackingChanged FINAL )
Q_PROPERTY( bool isEnabled READ isEnabled NOTIFY trackingChanged FINAL )
Q_PROPERTY( bool isConfigurable READ isConfigurable NOTIFY trackingChanged FINAL )
Q_PROPERTY( QString policy READ policy NOTIFY policyChanged FINAL )
public:
TrackingStyleConfig( QObject* parent );
virtual ~TrackingStyleConfig();
void setConfigurationMap( const QVariantMap& );
enum TrackingState
{
DisabledByConfig,
DisabledByUser,
EnabledByUser
};
Q_ENUM( TrackingState );
public Q_SLOTS:
TrackingState tracking() const { return m_state; }
/// @brief Has the user specifically enabled this kind of tracking?
bool isEnabled() const { return m_state == EnabledByUser; }
/// @brief Is this tracking enabled for configuration?
bool isConfigurable() const { return m_state != DisabledByConfig; }
/** @brief Sets the tracking state
*
* Unless the tracking is enabled for configuration, it always
* remains disabled.
*/
void setTracking( TrackingState );
/** @brief Sets the tracking state
*
* Use @c true for @c EnabledByUser, @c false for DisabledByUser,
* but keep in mind that if the tracking is not enabled for
* configuration, it will always remain disabled.
*/
void setTracking( bool );
/// @brief URL for the policy explaining this tracking
QString policy() const { return m_policy; }
signals:
void trackingChanged();
void policyChanged( QString );
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 );
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 );
void setConfigurationMap( const QVariantMap& configurationMap );
QString machineTrackingStyle() { return m_machineTrackingStyle; }
private:
QString m_machineTrackingStyle;
};
/** @brief User tracking reports user actions
*
* When user tracking is on, it is enabled for the user configured
* in Calamares -- not for users created afterwards in the target
* system, unless the target system defaults to tracking them.
* The kind of user tracking depends on the target system and
* environment; KDE user tracking is one example, which can be
* configured in a fine-grained way and defaults to off.
*/
class UserTrackingConfig : public TrackingStyleConfig
{
public:
UserTrackingConfig( QObject* parent );
void setConfigurationMap( const QVariantMap& configurationMap );
QString userTrackingStyle() { return m_userTrackingStyle; }
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

View File

@ -18,10 +18,16 @@
#include "TrackingJobs.h"
#include "Config.h"
#include "GlobalStorage.h"
#include "JobQueue.h"
#include "network/Manager.h"
#include "utils/CalamaresUtilsSystem.h"
#include "utils/Logger.h"
#include <KMacroExpander>
#include <QSemaphore>
#include <QTimer>
@ -32,7 +38,7 @@ TrackingInstallJob::TrackingInstallJob( const QString& url )
{
}
TrackingInstallJob::~TrackingInstallJob() { }
TrackingInstallJob::~TrackingInstallJob() {}
QString
TrackingInstallJob::prettyName() const
@ -72,38 +78,72 @@ TrackingInstallJob::exec()
return Calamares::JobResult::ok();
}
void
TrackingInstallJob::addJob( Calamares::JobList& list, InstallTrackingConfig* config )
{
if ( config->isEnabled() )
{
const auto* s = CalamaresUtils::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
TrackingMachineJob::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;
}
}
}
QString
TrackingMachineNeonJob::prettyName() const
TrackingMachineUpdateManagerJob::prettyName() const
{
return tr( "Machine feedback" );
}
QString
TrackingMachineNeonJob::prettyDescription() const
TrackingMachineUpdateManagerJob::prettyDescription() const
{
return prettyName();
}
QString
TrackingMachineNeonJob::prettyStatusMessage() const
TrackingMachineUpdateManagerJob::prettyStatusMessage() const
{
return tr( "Configuring machine feedback." );
}
Calamares::JobResult
TrackingMachineNeonJob::exec()
TrackingMachineUpdateManagerJob::exec()
{
static const auto script = QStringLiteral(
R"x(
MACHINE_ID=`cat /etc/machine-id`
sed -i "s,URI =.*,URI = http://releases.neon.kde.org/meta-release/${MACHINE_ID}," /etc/update-manager/meta-release
sed -i "s,URI_LTS =.*,URI_LTS = http://releases.neon.kde.org/meta-release-lts/${MACHINE_ID}," /etc/update-manager/meta-release
true
)x" );
int r = CalamaresUtils::System::instance()->targetEnvCall( "/bin/sh",
"sed -i '/^URI/s,${MACHINE_ID},'`cat /etc/machine-id`',' /etc/update-manager/meta-release || true" );
auto res = CalamaresUtils::System::instance()->runCommand( CalamaresUtils::System::RunLocation::RunInTarget,
QStringList { QStringLiteral( "/bin/sh" ) },
QString(), // Working dir
script,
script, // standard input
std::chrono::seconds( 1 ) );
int r = res.first;
if ( r == 0 )
{
@ -122,3 +162,87 @@ true
tr( "Could not configure machine feedback correctly, Calamares error %1." ).arg( r ) );
}
}
void
TrackingUserJob::addJob( Calamares::JobList& list, UserTrackingConfig* config )
{
if ( config->isEnabled() )
{
const auto* 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;
}
}
}
TrackingKUserFeedbackJob::TrackingKUserFeedbackJob( const QString& username, const QStringList& areas )
: m_username( username )
, m_areas( areas )
{
}
QString
TrackingKUserFeedbackJob::prettyName() const
{
return tr( "KDE user feedback" );
}
QString
TrackingKUserFeedbackJob::prettyDescription() const
{
return prettyName();
}
QString
TrackingKUserFeedbackJob::prettyStatusMessage() const
{
return tr( "Configuring KDE user feedback." );
}
Calamares::JobResult
TrackingKUserFeedbackJob::exec()
{
// This is the contents of a config file to turn on some kind
// of KUserFeedback tracking; the level (16) is chosen for minimal
// but not zero tracking.
static const char config[] = R"x([Global]
FeedbackLevel=16
)x";
for ( const QString& area : m_areas )
{
QString path = QStringLiteral( "/home/%1/.config/%2" ).arg( m_username, area );
cDebug() << "Configuring KUserFeedback" << path;
int r = CalamaresUtils::System::instance()->createTargetFile( path, config );
if ( r > 0 )
{
return Calamares::JobResult::error(
tr( "Error in KDE user feedback configuration." ),
tr( "Could not configure KDE user feedback correctly, script error %1." ).arg( r ) );
}
else if ( r < 0 )
{
return Calamares::JobResult::error(
tr( "Error in KDE user feedback configuration." ),
tr( "Could not configure KDE user feedback correctly, Calamares error %1." ).arg( r ) );
}
}
return Calamares::JobResult::ok();
}

View File

@ -16,13 +16,36 @@
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TRACKINGJOBS
#define TRACKINGJOBS
#ifndef TRACKING_TRACKINGJOBS_H
#define TRACKING_TRACKINGJOBS_H
#include "Job.h"
class InstallTrackingConfig;
class MachineTrackingConfig;
class UserTrackingConfig;
class QSemaphore;
/** @section Tracking Jobs
*
* The tracking jobs do the actual work of configuring tracking on the
* target machine. Tracking jobs may have *styles*, variations depending
* on the distro or environment of the target system. At the root of
* each family of tracking jobs (installation, machine, user) there is
* a class with static method `addJob()` that takes the configuration
* information from the relevant Config sub-object and optionally
* adds the right job (subclass!) to the list of jobs.
*/
/** @brief Install-tracking job (gets a URL)
*
* The install-tracking job (there is only one kind) does a GET
* on a configured URL with some additional information about
* the machine (if configured into the URL).
*
* No persistent tracking is done.
*/
class TrackingInstallJob : public Calamares::Job
{
Q_OBJECT
@ -35,11 +58,31 @@ public:
QString prettyStatusMessage() const override;
Calamares::JobResult exec() override;
static void addJob( Calamares::JobList& list, InstallTrackingConfig* config );
private:
const QString m_url;
};
class TrackingMachineNeonJob : public Calamares::Job
/** @brief Base class for machine-tracking jobs
*
* Machine-tracking configuraiton depends on the distro / style of machine
* being tracked, so it has subclasses to switch on the relevant kind
* of tracking. A machine is tracked persistently.
*/
class TrackingMachineJob : public Calamares::Job
{
public:
static void addJob( Calamares::JobList& list, MachineTrackingConfig* config );
};
/** @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 TrackingMachineJob
{
Q_OBJECT
public:
@ -49,5 +92,38 @@ public:
Calamares::JobResult exec() override;
};
/** @brief Base class for user-tracking jobs
*
* User-tracking configuration depends on the distro / style of user
* tracking being implemented, so there are subclasses to switch on the
* relevant kind of tracking. Users are tracked persistently (the user
* can of course configure the tracking again once the system is restarted).
*/
class TrackingUserJob : public Calamares::Job
{
public:
static void addJob( Calamares::JobList& list, UserTrackingConfig* config );
};
/** @brief Turn on KUserFeedback in target system
*
* This writes suitable files for turning on KUserFeedback for the
* normal user configured in Calamares. The feedback can be reconfigured
* by the user through Plasma's user-feedback dialog.
*/
class TrackingKUserFeedbackJob : public Calamares::Job
{
public:
TrackingKUserFeedbackJob( const QString& username, const QStringList& areas );
QString prettyName() const override;
QString prettyDescription() const override;
QString prettyStatusMessage() const override;
Calamares::JobResult exec() override;
private:
QString m_username;
QStringList m_areas;
};
#endif

View File

@ -18,6 +18,7 @@
#include "TrackingPage.h"
#include "Config.h"
#include "ui_page_trackingstep.h"
#include "Branding.h"
@ -28,178 +29,128 @@
#include "utils/Logger.h"
#include "utils/Retranslator.h"
#include <QButtonGroup>
#include <QDesktopServices>
#include <QLabel>
TrackingPage::TrackingPage( QWidget* parent )
TrackingPage::TrackingPage( Config* config, QWidget* parent )
: QWidget( parent )
, ui( new Ui::TrackingPage )
{
ui->setupUi( this );
CALAMARES_RETRANSLATE(
QString product = Calamares::Branding::instance()->shortProductName(); ui->retranslateUi( this );
ui->generalExplanation->setText(
tr( "Install tracking helps %1 to see how many users they have, what hardware they install %1 to and (with "
"the last two options below), get continuous information about preferred applications. To see what "
"will be sent, please click the help icon next to each area." )
.arg( product ) );
ui->installExplanation->setText(
tr( "By selecting this you will send information about your installation and hardware. This information "
"will <b>only be sent once</b> after the installation finishes." ) );
ui->machineExplanation->setText( tr( "By selecting this you will <b>periodically</b> send information about "
"your installation, hardware and applications, to %1." )
.arg( product ) );
ui->userExplanation->setText( tr( "By selecting this you will <b>regularly</b> send information about your "
"installation, hardware, applications and usage patterns, to %1." )
.arg( product ) ); )
CALAMARES_RETRANSLATE_SLOT( &TrackingPage::retranslate );
QButtonGroup* group = new QButtonGroup( this );
group->setExclusive( true );
group->addButton( ui->noneRadio );
group->addButton( ui->installRadio );
group->addButton( ui->machineRadio );
group->addButton( ui->userRadio );
ui->noneRadio->setChecked( true );
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::enableTrackingOption( TrackingType t, bool enabled )
TrackingPage::retranslate()
{
QWidget* group = nullptr;
switch ( t )
{
case TrackingType::InstallTracking:
group = ui->installGroup;
break;
case TrackingType::MachineTracking:
group = ui->machineGroup;
break;
case TrackingType::UserTracking:
group = ui->userGroup;
break;
}
if ( group != nullptr )
{
if ( enabled )
{
group->show();
}
else
{
group->hide();
}
}
else
{
cWarning() << "unknown tracking option" << int( t );
}
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 <b>once</b> after the installation finishes." ) );
ui->machineExplanation->setText(
tr( "By selecting this you will periodically send information about your <b>machine</b> installation, "
"hardware and applications, to %1." )
.arg( product ) );
ui->userExplanation->setText(
tr( "By selecting this you will regularly send information about your "
"<b>user</b> installation, hardware, applications and application usage patterns, to %1." )
.arg( product ) );
}
bool
TrackingPage::getTrackingOption( TrackingType t )
TrackingPage::anyOtherChecked() const
{
bool enabled = false;
return ui->installCheckBox->isChecked() || ui->machineCheckBox->isChecked() || ui->userCheckBox->isChecked();
}
// A tracking type is enabled if it is checked, or
// any higher level is checked.
#define ch( x ) ui->x->isChecked()
switch ( t )
void
TrackingPage::buttonNoneChecked( int state )
{
if ( state )
{
case TrackingType::InstallTracking:
enabled = ch( installRadio ) || ch( machineRadio ) || ch( userRadio );
break;
case TrackingType::MachineTracking:
enabled = ch( machineRadio ) || ch( userRadio );
break;
case TrackingType::UserTracking:
enabled = ch( userRadio );
break;
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 );
}
#undef ch
return enabled;
}
void
TrackingPage::setTrackingPolicy( TrackingType t, QString url )
TrackingPage::buttonChecked( int state )
{
QToolButton* button = nullptr;
switch ( t )
if ( state )
{
case TrackingType::InstallTracking:
button = ui->installPolicyButton;
break;
case TrackingType::MachineTracking:
button = ui->machinePolicyButton;
break;
case TrackingType::UserTracking:
button = ui->userPolicyButton;
break;
// Can't have none checked, if another one is
ui->noneCheckBox->setEnabled( true );
ui->noneCheckBox->setChecked( false );
}
if ( button != nullptr )
if ( url.isEmpty() )
else
{
if ( !anyOtherChecked() )
{
button->hide();
ui->noneCheckBox->setChecked( true );
ui->noneCheckBox->setEnabled( false );
}
else
{
connect( button, &QToolButton::clicked, [ url ] { QDesktopServices::openUrl( url ); } );
cDebug() << "Tracking policy" << int( t ) << "set to" << url;
}
else
{
cWarning() << "unknown tracking option" << int( t );
}
}
void
TrackingPage::setGeneralPolicy( QString url )
TrackingPage::trackerChanged( TrackingStyleConfig* config, QWidget* panel, QCheckBox* check )
{
if ( url.isEmpty() )
{
ui->generalPolicyLabel->hide();
}
else
{
ui->generalPolicyLabel->show();
ui->generalPolicyLabel->setTextInteractionFlags( Qt::TextBrowserInteraction );
ui->generalPolicyLabel->show();
connect( ui->generalPolicyLabel, &QLabel::linkActivated, [ url ] { QDesktopServices::openUrl( url ); } );
}
}
void
TrackingPage::setTrackingLevel( const QString& l )
{
QString level = l.toLower();
QRadioButton* button = nullptr;
if ( level.isEmpty() || level == "none" )
{
button = ui->noneRadio;
}
else if ( level == "install" )
{
button = ui->installRadio;
}
else if ( level == "machine" )
{
button = ui->machineRadio;
}
else if ( level == "user" )
{
button = ui->userRadio;
}
if ( button != nullptr )
{
button->setChecked( true );
}
else
{
cWarning() << "unknown default tracking level" << l;
}
panel->setVisible( config->isConfigurable() );
check->setChecked( config->isEnabled() );
}

View File

@ -21,6 +21,7 @@
#include "TrackingType.h"
#include <QCheckBox>
#include <QUrl>
#include <QWidget>
@ -29,35 +30,48 @@ namespace Ui
class TrackingPage;
}
class Config;
class TrackingStyleConfig;
class TrackingPage : public QWidget
{
Q_OBJECT
public:
explicit TrackingPage( QWidget* parent = nullptr );
explicit TrackingPage( Config* config, QWidget* parent = nullptr );
/**
* Enables or disables the tracking-option block for the given
* tracking option @p t, and sets the initial state of the
* checkbox to the @p user default.
/** @brief is any of the enable-tracking buttons checked?
*
* Call this in ascending order of tracking type.
* Returns true if any one or more of install, machine or user
* tracking is enabled.
*/
void enableTrackingOption( TrackingType t, bool enabled );
/**
* Returns whether tracking type @p is selected by the user
* (i.e. is the radio button for that level, or for a higher
* tracking level, enabled).
*/
bool getTrackingOption( TrackingType t );
bool anyOtherChecked() const;
/* URL for given level @p t */
void setTrackingPolicy( TrackingType t, QString url );
/* URL for the global link */
void setGeneralPolicy( QString url );
/* Select one of the four levels by name */
void setTrackingLevel( const QString& level );
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;
};

View File

@ -19,11 +19,17 @@
#ifndef TRACKINGTYPE_H
#define TRACKINGTYPE_H
#include "utils/NamedEnum.h"
enum class TrackingType
{
InstallTracking,
MachineTracking,
UserTracking
NoTracking, // Do not enable tracking at all
InstallTracking, // Track that *this* install has happened
MachineTracking, // Track the machine, ongoing
UserTracking // Track the user, ongoing
};
// Implemented in Config.cpp
const NamedEnumTable< TrackingType >& trackingNames();
#endif //TRACKINGTYPE_H

View File

@ -18,6 +18,7 @@
#include "TrackingViewStep.h"
#include "Config.h"
#include "TrackingJobs.h"
#include "TrackingPage.h"
@ -33,17 +34,10 @@
CALAMARES_PLUGIN_FACTORY_DEFINITION( TrackingViewStepFactory, registerPlugin< TrackingViewStep >(); )
/** @brief Is @p s a valid machine-tracking style. */
static bool
isValidStyle( const QString& s )
{
static QStringList knownStyles { "neon" };
return knownStyles.contains( s );
}
TrackingViewStep::TrackingViewStep( QObject* parent )
: Calamares::ViewStep( parent )
, m_widget( new TrackingPage )
, m_config( new Config( this ) )
, m_widget( new TrackingPage( m_config ) )
{
emit nextStatusChanged( false );
}
@ -103,89 +97,28 @@ TrackingViewStep::isAtEnd() const
void
TrackingViewStep::onLeave()
{
m_installTracking.userEnabled = m_widget->getTrackingOption( TrackingType::InstallTracking );
m_machineTracking.userEnabled = m_widget->getTrackingOption( TrackingType::MachineTracking );
m_userTracking.userEnabled = m_widget->getTrackingOption( TrackingType::UserTracking );
cDebug() << "Install tracking:" << m_installTracking.enabled();
cDebug() << "Machine tracking:" << m_machineTracking.enabled();
cDebug() << " User tracking:" << m_userTracking.enabled();
cDebug() << "Install tracking:" << m_config->installTracking()->isEnabled();
cDebug() << Logger::SubEntry << "Machine tracking:" << m_config->machineTracking()->isEnabled();
cDebug() << Logger::SubEntry << " User tracking:" << m_config->userTracking()->isEnabled();
}
Calamares::JobList
TrackingViewStep::jobs() const
{
Calamares::JobList l;
cDebug() << "Creating tracking jobs ..";
if ( m_installTracking.enabled() && !m_installTrackingUrl.isEmpty() )
{
QString installUrl = m_installTrackingUrl;
const auto s = CalamaresUtils::System::instance();
QString memory, disk;
memory.setNum( s->getTotalMemoryB().first );
disk.setNum( s->getTotalDiskB() );
installUrl.replace( "$CPU", s->getCpuDescription() ).replace( "$MEMORY", memory ).replace( "$DISK", disk );
cDebug() << Logger::SubEntry << "install-tracking URL" << installUrl;
l.append( Calamares::job_ptr( new TrackingInstallJob( installUrl ) ) );
}
if ( m_machineTracking.enabled() && !m_machineTrackingStyle.isEmpty() )
{
Q_ASSERT( isValidStyle( m_machineTrackingStyle ) );
if ( m_machineTrackingStyle == "neon" )
{
l.append( Calamares::job_ptr( new TrackingMachineNeonJob() ) );
}
}
Calamares::JobList l;
TrackingInstallJob::addJob( l, m_config->installTracking() );
TrackingMachineJob::addJob( l, m_config->machineTracking() );
TrackingUserJob::addJob( l, m_config->userTracking() );
cDebug() << Logger::SubEntry << l.count() << "jobs queued.";
return l;
}
QVariantMap
TrackingViewStep::setTrackingOption( const QVariantMap& configurationMap, const QString& key, TrackingType t )
{
bool settingEnabled = false;
bool success = false;
auto config = CalamaresUtils::getSubMap( configurationMap, key, success );
if ( success )
{
settingEnabled = CalamaresUtils::getBool( config, "enabled", false );
}
TrackingEnabled& trackingConfiguration = tracking( t );
trackingConfiguration.settingEnabled = settingEnabled;
trackingConfiguration.userEnabled = false;
m_widget->enableTrackingOption( t, settingEnabled );
m_widget->setTrackingPolicy( t, CalamaresUtils::getString( config, "policy" ) );
return config;
}
void
TrackingViewStep::setConfigurationMap( const QVariantMap& configurationMap )
{
QVariantMap config;
config = setTrackingOption( configurationMap, "install", TrackingType::InstallTracking );
m_installTrackingUrl = CalamaresUtils::getString( config, "url" );
config = setTrackingOption( configurationMap, "machine", TrackingType::MachineTracking );
auto s = CalamaresUtils::getString( config, "style" );
if ( isValidStyle( s ) )
{
m_machineTrackingStyle = s;
}
setTrackingOption( configurationMap, "user", TrackingType::UserTracking );
m_widget->setGeneralPolicy( CalamaresUtils::getString( configurationMap, "policy" ) );
m_widget->setTrackingLevel( CalamaresUtils::getString( configurationMap, "default" ) );
m_config->setConfigurationMap( configurationMap );
}

View File

@ -29,6 +29,7 @@
#include <QUrl>
#include <QVariantMap>
class Config;
class TrackingPage;
class PLUGINDLLEXPORT TrackingViewStep : public Calamares::ViewStep
@ -56,42 +57,8 @@ public:
void setConfigurationMap( const QVariantMap& configurationMap ) override;
private:
QVariantMap setTrackingOption( const QVariantMap& configurationMap, const QString& key, TrackingType t );
Config* m_config;
TrackingPage* m_widget;
QString m_installTrackingUrl;
QString m_machineTrackingStyle;
struct TrackingEnabled
{
bool settingEnabled; // Enabled in config file
bool userEnabled; // User checked "yes"
TrackingEnabled()
: settingEnabled( false )
, userEnabled( false )
{
}
bool enabled() const { return settingEnabled && userEnabled; }
};
TrackingEnabled m_installTracking, m_machineTracking, m_userTracking;
inline TrackingEnabled& tracking( TrackingType t )
{
if ( t == TrackingType::UserTracking )
{
return m_userTracking;
}
else if ( t == TrackingType::MachineTracking )
{
return m_machineTracking;
}
else
{
return m_installTracking;
}
}
};
CALAMARES_PLUGIN_FACTORY_DECLARATION( TrackingViewStepFactory )

View File

@ -32,7 +32,7 @@ margin-left: 2em;</string>
<widget class="QWidget" name="noneGroup" native="true">
<layout class="QHBoxLayout" name="noneLayout">
<item>
<widget class="QRadioButton" name="noneRadio">
<widget class="QCheckBox" name="noneCheckBox">
<property name="text">
<string/>
</property>
@ -69,7 +69,7 @@ margin-left: 2em;</string>
</sizepolicy>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;By selecting this, you will send &lt;span style=&quot; font-weight:600;&quot;&gt;no information at all&lt;/span&gt; about your installation.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Click here to send &lt;span style=&quot; font-weight:600;&quot;&gt;no information at all&lt;/span&gt; about your installation.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@ -83,7 +83,7 @@ margin-left: 2em;</string>
<widget class="QWidget" name="installGroup" native="true">
<layout class="QHBoxLayout" name="installLayout">
<item>
<widget class="QRadioButton" name="installRadio">
<widget class="QCheckBox" name="installCheckBox">
<property name="text">
<string/>
</property>
@ -145,7 +145,7 @@ margin-left: 2em;</string>
<widget class="QWidget" name="machineGroup" native="true">
<layout class="QHBoxLayout" name="machineLayout">
<item>
<widget class="QRadioButton" name="machineRadio">
<widget class="QCheckBox" name="machineCheckBox">
<property name="text">
<string/>
</property>
@ -207,7 +207,7 @@ margin-left: 2em;</string>
<widget class="QWidget" name="userGroup" native="true">
<layout class="QHBoxLayout" name="userLayout">
<item>
<widget class="QRadioButton" name="userRadio">
<widget class="QCheckBox" name="userCheckBox">
<property name="text">
<string/>
</property>
@ -279,6 +279,9 @@ margin-left: 2em;</string>
<property name="openExternalLinks">
<bool>false</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextBrowserInteraction</set>
</property>
</widget>
</item>
<item>

View File

@ -28,14 +28,16 @@
# policy applies.
#
# Each area has a key *enabled*. If the area is enabled, it is shown to
# the user. This defaults to off, which means no tracking would be
# the user. This defaults to false, which means no tracking would be
# configured or enabled by Calamares.
#
# Each area has a key *policy*, which is a Url to be opened when
# the user clicks on the corresponding Help button for an explanation
# of the details of that particular kind of tracking. If no policy
# is set, the help button is hidden. The example policy links
# go to Calamares' generic user manual.
# is set, that tracking style is disabled. The example policy links
# go to Calamares' generic user manual (which is a terrible idea
# for distro's: you have GDPR obligations under most of these tracking
# styles, so do your homework).
#
# Each area may have other configuration keys, depending on the
# area and how it needs to be configured.
@ -48,13 +50,14 @@
---
# This is the global policy; it is displayed as a link on the page.
# If blank or commented out, no link is displayed on the tracking
# page. It is recommended to either provide policy URLs for each
# area, *or* one general link, and not to mix them.
# page. You **must** provide policy links per-area as well.
policy: "https://github.com/calamares/calamares/wiki/Use-Guide#installation-tracking"
# This is the default level to enable for tracking. If commented out,
# This is the default area to enable for tracking. If commented out,
# empty, or otherwise invalid, "none" is used, so no tracking by default.
default: user
# Setting an area here also checks the areas before it (install, machine,
# then user) by default -- subject to those areas being enabled at all.
# default: user
# The install area has one specific configuration key:
# url: this URL (remember to include the protocol, and prefer https)
@ -72,17 +75,28 @@ default: user
install:
enabled: false
policy: "https://github.com/calamares/calamares/wiki/Use-Guide#installation-tracking"
# url: "https://example.com/install.php?c=$CPU&m=$MEMORY"
url: "https://example.com/install.php?c=$CPU&m=$MEMORY"
# The machine area has one specific configuration key:
# style: This string specifies what kind of tracking configuration
# needs to be done. There is currently only one valid
# style, "neon", which edits two files in the installed
# system to enable system-tracking.
# 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: neon
style: updatemanager
policy: "https://github.com/calamares/calamares/wiki/Use-Guide#machine-tracking"
# The user area is not yet implemented, and has no specific configuration.
# The user area has one specific configuration key:
# style: This string specifies what kind of tracking configuration
# needs to be done. See below for valid styles.
#
# Available styles:
# - *kuserfeedback* sets up KUserFeedback tracking (applicable to the KDE
# Plasma Desktop) for each KUserFeedback area listed in *areas*.
user:
enabled: false
style: kuserfeedback
areas: [ PlasmaUserFeedback ]

View File

@ -0,0 +1,8 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/umount
additionalProperties: false
type: object
properties:
"srcLog": { type: str }
"destLog": { type: str }

View File

@ -388,6 +388,22 @@ def get_supported_filesystems():
return ["file"] + get_supported_filesystems_kernel()
def repair_root_permissions(root_mount_point):
"""
If the / of the system gets permission 777, change it down
to 755. Any other permission is left alone. This
works around standard behavior from squashfs where
permissions are (easily, accidentally) set to 777.
"""
existing_root_mode = os.stat(root_mount_point).st_mode & 0o777
if existing_root_mode == 0o777:
try:
os.chmod(root_mount_point, 0o755) # Want / to be rwxr-xr-x
except OSError as e:
utils.warning("Could not set / to safe permissions: {}".format(e))
# But ignore it
def run():
"""
Unsquash filesystem.
@ -457,6 +473,9 @@ def run():
is_first = False
unpackop = UnpackOperation(unpack)
return unpackop.run()
repair_root_permissions(root_mount_point)
try:
unpackop = UnpackOperation(unpack)
return unpackop.run()
finally:
repair_root_permissions(root_mount_point)

View File

@ -0,0 +1,14 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/unpackfs
additionalProperties: false
type: object
properties:
"unpack":
type: seq
sequence:
- type: map
mapping:
"source": { type: string, required: true }
"sourcefs": { type: str }
"destination": { type: str }

View File

@ -124,7 +124,7 @@ allowWeakPasswordsDefault: false
# and rely on a correct configuration file in /etc/default/useradd
# - set, non-empty, use that path as shell. No validation is done
# that the shell actually exists or is executable.
# userShell: /bin/bash
userShell: /bin/bash
# Hostname setting
#

View File

@ -0,0 +1,38 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/users
additionalProperties: false
type: object
properties:
# User shell, should be path to /bin/sh or so
userShell: { type: string }
# Group settings
defaultGroups:
type: array
items: { type: string }
autologinGroup: { type: string }
sudoersGroup: { type: string }
# Skip login (depends on displaymanager support)
doAutologin: { type: boolean, default: true }
# Root password separate from user password?
setRootPassword: { type: boolean, default: true }
doReusePassword: { type: boolean, default: true }
# Passwords that don't pass a quality test
allowWeakPasswords: { type: boolean, default: false }
allowWeakPasswordsDefault: { type: boolean, default: false }
passwordRequirements:
additionalProperties: false
type: object
properties:
nonempty: { type: boolean, default: true }
minLength: { type: number }
maxLength: { type: number }
libpwquality: { type: array, items: { type: string } } # Don't know what libpwquality supports
# Hostname setting
setHostname: { type: string, enum: [ None, EtcFile, Hostnamed ] }
writeHostsFile: { type: boolean, default: true }
required:
- defaultGroups
- autologinGroup
- sudoersGroup

View File

@ -0,0 +1,36 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/welcome
additionalProperties: false
type: object
properties:
# TODO:3.3: drop the string alternatives and put the URL part in Branding
showSupportUrl: { anyOf: [ { type: boolean, default: true }, { type: string } ] }
showKnownIssuesUrl: { anyOf: [ { type: boolean, default: true }, { type: string } ] }
showReleaseNotesUrl: { anyOf: [ { type: boolean, default: true }, { type: string } ] }
showDonateUrl: { anyOf: [ { type: boolean, default: true }, { type: string } ] }
requirements:
additionalProperties: false
type: object
properties:
requiredStorage: { type: number }
requiredRam: { type: number }
internetCheckUrl: { type: string }
check:
type: array
items: { type: string, enum: [storage, ram, power, internet, root, screen], unique: true }
required: # Key-name in the config-file
type: array
items: { type: string, enum: [storage, ram, power, internet, root, screen], unique: true }
required: [ requiredStorage, requiredRam, check ] # Schema keyword
# TODO: refactor, this is reused in locale
geoip:
additionalProperties: false
type: object
properties:
style: { type: string, enum: [ none, fixed, xml, json ] }
url: { type: string }
selector: { type: string }
required: [ style, url, selector ]