Merge branch 'calamares' into issue-1176
This commit is contained in:
commit
d83543d904
14
CHANGES
14
CHANGES
@ -3,7 +3,7 @@ contributors are listed. Note that Calamares does not have a historical
|
||||
changelog -- this log starts with version 3.2.0. The release notes on the
|
||||
website will have to do for older versions.
|
||||
|
||||
# 3.2.28 (unreleased) #
|
||||
# 3.2.28 (2020-08-09) #
|
||||
|
||||
This release contains contributions from (alphabetically by first name):
|
||||
- Anke Boersma
|
||||
@ -14,9 +14,11 @@ This release contains contributions from (alphabetically by first name):
|
||||
- A new object *Network* is available to QML modules in `io.calamares.core`.
|
||||
It exposes network status through the *hasInternet* property.
|
||||
- Welcome to Tajik translations. The Tajik language has quickly reached
|
||||
100% completion.
|
||||
100% completion. Thanks Victor!
|
||||
- Welcome to [Interlingue](https://en.wikipedia.org/wiki/Interlingue).
|
||||
The translation is at an early stage.
|
||||
The translation is at an early stage. Qt does not support language
|
||||
code *ie* though, so it may take some time to be integrated (much
|
||||
like Esperanto wasn't supported until Qt 5.12).
|
||||
|
||||
## Modules ##
|
||||
- The *locale* module has been completely redone on the inside.
|
||||
@ -31,9 +33,15 @@ This release contains contributions from (alphabetically by first name):
|
||||
timezone setting -- this can be useful to avoid both hard-coding an
|
||||
initial zone and doing extra GeoIP lookups, in the case where the
|
||||
live system already does so. #1391
|
||||
- The *locale* and *localeq* modules have additional machinery for
|
||||
timezone lookups; please report cases where clicking on the map
|
||||
returns an obviously bogus timezone (up until this release, for
|
||||
instance, Cape Town).
|
||||
- The *users* module no longer accepts `root` as a username. #1462
|
||||
- The *keyboardq* module is now more inline with the look of the rest
|
||||
of the Calamares modules, use of a background image is removed.
|
||||
- The *grubcfg* module now understands `/etc/default/grub.d`. #1457
|
||||
|
||||
|
||||
# 3.2.27 (2020-07-11) #
|
||||
|
||||
|
@ -1,5 +1,8 @@
|
||||
# === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2017 Adriaan de Groot <groot@kde.org>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# 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
|
||||
@ -13,9 +16,6 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# License-Filename: LICENSE
|
||||
#
|
||||
###
|
||||
#
|
||||
# Generally, this CMakeLists.txt will find all the dependencies for Calamares
|
||||
@ -49,7 +49,7 @@ project( CALAMARES
|
||||
VERSION 3.2.28
|
||||
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
|
||||
#
|
||||
@ -140,20 +140,18 @@ set( CALAMARES_DESCRIPTION_SUMMARY
|
||||
# TODO: drop the es_ES translation from Transifex
|
||||
#
|
||||
# NOTE: move eo (Esperanto) to _ok once Qt can actually create a
|
||||
# locale for it. (Qt 5.12.2 can, see check later on).
|
||||
# NOTE: update these lines by running txstats.py, or copy these four lines
|
||||
# and prefix each variable name with "p", so that the automatic
|
||||
# checks for new languages and misspelled ones are done (that is,
|
||||
# copy these four lines to four backup lines, add "p", and then update
|
||||
# the original four lines with the current translations).
|
||||
# locale for it. (Qt 5.12.2 can, see Translation Status section).
|
||||
# NOTE: move ie (Interlingue) to _ok once Qt supports it.
|
||||
# NOTE: update these lines by running `txstats.py`, or for full automation
|
||||
# `txstats.py -e`. See also
|
||||
#
|
||||
# Total 68 languages
|
||||
set( _tx_complete ca fi_FI he hr nl pt_BR sq tg tr_TR uk zh_TW )
|
||||
set( _tx_good as ast az az_AZ be cs_CZ da de es fr hi hu it_IT ja
|
||||
ko lt ml pt_PT ru sk sv zh_CN )
|
||||
set( _tx_ok ar bg el en_GB es_MX es_PR et eu fa gl id ie is mr nb
|
||||
set( _tx_ok ar bg el en_GB es_MX es_PR et eu fa gl id is mr nb
|
||||
pl ro sl sr sr@latin th )
|
||||
set( _tx_incomplete bn ca@valencia eo fr_CH gu kk kn lo lv mk ne_NP
|
||||
set( _tx_incomplete bn ca@valencia eo fr_CH gu ie kk kn lo lv mk ne_NP
|
||||
ur uz )
|
||||
|
||||
### Required versions
|
||||
@ -286,14 +284,6 @@ find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED Concurrent Core Gui LinguistTool
|
||||
if( WITH_QML )
|
||||
find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED Quick QuickWidgets )
|
||||
endif()
|
||||
if( Qt5_VERSION VERSION_GREATER 5.12.1 )
|
||||
# At least Qt 5.12.2 seems to support Esperanto in QLocale
|
||||
if( "eo" IN_LIST _tx_incomplete )
|
||||
message(STATUS "Esperanto support since Qt 5.12.2, enabling Esperanto locale")
|
||||
list( REMOVE_ITEM _tx_incomplete "eo" )
|
||||
list( APPEND _tx_ok "eo" )
|
||||
endif()
|
||||
endif()
|
||||
# Optional Qt parts
|
||||
find_package( Qt5DBus CONFIG )
|
||||
|
||||
@ -429,30 +419,22 @@ set(Calamares_WITH_QML ${WITH_QML})
|
||||
|
||||
### Transifex Translation status
|
||||
#
|
||||
# Construct language lists for use. If there are p_tx* variables,
|
||||
# then run an extra cmake-time check for consistency of the old
|
||||
# (p_tx*) and new (_tx*) lists.
|
||||
# Construct language lists for use.
|
||||
#
|
||||
set( prev_tx ${p_tx_complete} ${p_tx_good} ${p_tx_ok} ${p_tx_incomplete} )
|
||||
if( Qt5_VERSION VERSION_GREATER 5.12.1 )
|
||||
# At least Qt 5.12.2 seems to support Esperanto in QLocale
|
||||
if( "eo" IN_LIST _tx_incomplete )
|
||||
message(STATUS "Esperanto support since Qt 5.12.2, enabling Esperanto locale")
|
||||
list( REMOVE_ITEM _tx_incomplete "eo" )
|
||||
list( APPEND _tx_ok "eo" )
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set( curr_tx ${_tx_complete} ${_tx_good} ${_tx_ok} ${_tx_incomplete} )
|
||||
set( tx_errors OFF )
|
||||
if ( prev_tx )
|
||||
# Gone in new list
|
||||
foreach( l ${prev_tx} )
|
||||
list( FIND curr_tx ${l} p_l )
|
||||
if( p_l EQUAL -1 )
|
||||
message(WARNING "Language ${l} was present in previous translations and is now absent.")
|
||||
set( tx_errors ON )
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if ( curr_tx )
|
||||
# New in list
|
||||
foreach( l ${curr_tx} )
|
||||
list( FIND prev_tx ${l} p_l )
|
||||
if( p_l EQUAL -1 )
|
||||
message(WARNING "Language ${l} is new.")
|
||||
set( tx_errors ON )
|
||||
endif()
|
||||
set( p_l "lang/calamares_${l}.ts" )
|
||||
if( NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${p_l} )
|
||||
message(WARNING "Language ${l} has no .ts file yet.")
|
||||
@ -463,7 +445,6 @@ if ( prev_tx )
|
||||
unset( p_l )
|
||||
unset( l )
|
||||
endif()
|
||||
unset( prev_tx )
|
||||
unset( curr_tx )
|
||||
if( tx_errors )
|
||||
message( FATAL_ERROR "Translation warnings, see above." )
|
||||
@ -474,14 +455,6 @@ list( SORT CALAMARES_TRANSLATION_LANGUAGES )
|
||||
|
||||
add_subdirectory( lang ) # i18n tools
|
||||
|
||||
if ( INSTALL_COMPLETION )
|
||||
if( NOT CMAKE_INSTALL_BASHCOMPLETIONDIR )
|
||||
set( CMAKE_INSTALL_BASHCOMPLETIONDIR "${CMAKE_INSTALL_DATADIR}/bash-completion/completions" )
|
||||
endif()
|
||||
|
||||
install( FILES ${CMAKE_SOURCE_DIR}/data/completion/bash/calamares DESTINATION "${CMAKE_INSTALL_BASHCOMPLETIONDIR}" )
|
||||
endif()
|
||||
|
||||
### Example Distro
|
||||
#
|
||||
# For testing purposes Calamares includes a very, very, limited sample
|
||||
@ -671,6 +644,14 @@ if( INSTALL_POLKIT )
|
||||
)
|
||||
endif()
|
||||
|
||||
if ( INSTALL_COMPLETION )
|
||||
if( NOT CMAKE_INSTALL_BASHCOMPLETIONDIR )
|
||||
set( CMAKE_INSTALL_BASHCOMPLETIONDIR "${CMAKE_INSTALL_DATADIR}/bash-completion/completions" )
|
||||
endif()
|
||||
|
||||
install( FILES ${CMAKE_SOURCE_DIR}/data/completion/bash/calamares DESTINATION "${CMAKE_INSTALL_BASHCOMPLETIONDIR}" )
|
||||
endif()
|
||||
|
||||
install(
|
||||
FILES calamares.desktop
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/applications
|
||||
|
@ -187,13 +187,22 @@ function( calamares_add_plugin )
|
||||
install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${PLUGIN_DESC_FILE}
|
||||
DESTINATION ${PLUGIN_DESTINATION} )
|
||||
|
||||
set( _warned_config OFF )
|
||||
foreach( PLUGIN_CONFIG_FILE ${PLUGIN_CONFIG_FILES} )
|
||||
if( ${CMAKE_CURRENT_SOURCE_DIR}/${PLUGIN_CONFIG_FILE} IS_NEWER_THAN ${CMAKE_CURRENT_BINARY_DIR}/${PLUGIN_CONFIG_FILE} OR INSTALL_CONFIG )
|
||||
configure_file( ${PLUGIN_CONFIG_FILE} ${PLUGIN_CONFIG_FILE} COPYONLY )
|
||||
else()
|
||||
message( " ${BoldYellow}Not updating${ColorReset} ${PLUGIN_CONFIG_FILE}" )
|
||||
set( _warned_config ON )
|
||||
endif()
|
||||
if ( INSTALL_CONFIG )
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/${PLUGIN_CONFIG_FILE}
|
||||
DESTINATION ${PLUGIN_DATA_DESTINATION} )
|
||||
endif()
|
||||
endforeach()
|
||||
if ( _warned_config )
|
||||
message( "" )
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
@ -6,10 +6,16 @@
|
||||
# LibPWQuality_LIBRARIES, where to find the library
|
||||
# LibPWQuality_INCLUDE_DIRS, where to find pwquality.h
|
||||
#
|
||||
include(FindPkgConfig)
|
||||
find_package(PkgConfig)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
if(PkgConfig_FOUND)
|
||||
pkg_search_module(pc_pwquality QUIET pwquality)
|
||||
else()
|
||||
# It's just possible that the find_path and find_library will
|
||||
# find it **anyway**, so let's pretend it was there.
|
||||
set(pc_pwquality_FOUND ON)
|
||||
endif()
|
||||
|
||||
find_path(LibPWQuality_INCLUDE_DIR
|
||||
NAMES pwquality.h
|
||||
|
@ -119,7 +119,7 @@ test -n "$V" || { echo "Could not obtain version in $BUILDDIR." ; exit 1 ; }
|
||||
#
|
||||
# This is the signing key ID associated with the GitHub account adriaandegroot,
|
||||
# which is used to create all "verified" tags in the Calamares repo.
|
||||
KEY_ID="61A7D26277E4D0DB"
|
||||
KEY_ID="CFDDC96F12B1915C"
|
||||
git tag -u "$KEY_ID" -m "Release v$V" "v$V" || { echo "Could not sign tag v$V." ; exit 1 ; }
|
||||
|
||||
### Create the tarball
|
||||
|
@ -29,7 +29,7 @@
|
||||
### END USAGE
|
||||
|
||||
# The files that are translated; should match the contents of .tx/config
|
||||
TX_FILE_LIST="lang/calamares_en.ts lang/python.pot src/modules/dummypythonqt/lang/dummypythonqt.pot calamares.desktop"
|
||||
TX_FILE_LIST="lang/calamares_en.ts lang/python.pot calamares.desktop"
|
||||
|
||||
### COMMAND ARGUMENTS
|
||||
#
|
||||
@ -125,7 +125,7 @@ tx_sum()
|
||||
|
||||
# Remove linenumbers from .ts (XML) and .pot
|
||||
sed -i'' -e '/<location filename/d' "$WORKTREE_NAME/lang/calamares_en.ts"
|
||||
sed -i'' -e '/^#: src..*[0-9]$/d' $WORKTREE_NAME/lang/python.pot $WORKTREE_NAME/src/modules/dummypythonqt/lang/dummypythonqt.pot
|
||||
sed -i'' -e '/^#: src..*[0-9]$/d' $WORKTREE_NAME/lang/python.pot
|
||||
|
||||
_SUM=$( cd $WORKTREE_NAME && cat $TX_FILE_LIST | $SHA256 )
|
||||
echo "$_SUM"
|
||||
|
@ -64,7 +64,7 @@ tx pull --force --source --all
|
||||
# so clean them up after pulling.
|
||||
#
|
||||
drop_language() {
|
||||
rm -rf lang/python/"$1" src/modules/dummypythonqt/lang/"$1" lang/calamares_"$1".ts
|
||||
rm -rf lang/python/"$1" lang/calamares_"$1".ts
|
||||
grep -v "\\[$1]" calamares.desktop > calamares.desktop.new
|
||||
mv calamares.desktop.new calamares.desktop
|
||||
}
|
||||
|
@ -178,6 +178,7 @@ def get_tx_stats(languages, outputter, verbose):
|
||||
# and it's at-the-least ok.
|
||||
incomplete_languages = (
|
||||
"eo", # Not supported by QLocale < 5.12.1
|
||||
"ie", # Not supported by Qt at least through 5.15.0
|
||||
)
|
||||
|
||||
all_langs = []
|
||||
|
@ -212,17 +212,17 @@
|
||||
<message>
|
||||
<location filename="../src/libcalamaresui/viewpages/QmlViewStep.cpp" line="76"/>
|
||||
<source>Loading ...</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>ভৰ্টিকৰন ...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libcalamaresui/viewpages/QmlViewStep.cpp" line="97"/>
|
||||
<source>QML Step <i>%1</i>.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>QML Step <i>%1</i>.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/libcalamaresui/viewpages/QmlViewStep.cpp" line="277"/>
|
||||
<source>Loading failed.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>ভৰ্টিকৰন বিফল |</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -717,7 +717,7 @@ The installer will quit and all changes will be lost.</source>
|
||||
<message>
|
||||
<location filename="../src/modules/locale/Config.cpp" line="333"/>
|
||||
<source>Set timezone to %1/%2.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>সময় অঞ্চলৰ সিদ্ধান্ত কৰক %`1%2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/locale/Config.cpp" line="348"/>
|
||||
@ -742,7 +742,7 @@ The installer will quit and all changes will be lost.</source>
|
||||
<message>
|
||||
<location filename="../src/modules/netinstall/Config.cpp" line="51"/>
|
||||
<source>Network Installation. (Disabled: internal error)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>নেটৱৰ্ক ইনস্তলেচন। (নিস্ক্ৰিয়: ভিতৰুৱা দোষ)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/netinstall/Config.cpp" line="53"/>
|
||||
@ -777,22 +777,22 @@ The installer will quit and all changes will be lost.</source>
|
||||
<message>
|
||||
<location filename="../src/modules/welcome/Config.cpp" line="245"/>
|
||||
<source><h1>Welcome to the Calamares setup program for %1</h1></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>%1ৰ Calamares চেত্ আপ প্ৰগ্ৰামলৈ আদৰণি জনাইছো।</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/welcome/Config.cpp" line="246"/>
|
||||
<source><h1>Welcome to %1 setup</h1></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><h1> %1 চেত্ আপলৈ আদৰণি জনাইছো।</h1></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/welcome/Config.cpp" line="251"/>
|
||||
<source><h1>Welcome to the Calamares installer for %1</h1></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><h1>%1ৰ কেলামাৰেচ ইনস্তলাৰলৈ আদৰণি জনাইছো।</h1></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/welcome/Config.cpp" line="252"/>
|
||||
<source><h1>Welcome to the %1 installer</h1></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><h1>%1 ইনস্তলাৰলৈ আদৰণি জনাইছো।</h1></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="125"/>
|
||||
@ -802,7 +802,7 @@ The installer will quit and all changes will be lost.</source>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="131"/>
|
||||
<source>'%1' is not allowed as username.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>'%1'ক ব্যৱহাৰকাৰীৰ নাম হিচাপে ব্যৱহাৰ কৰা অবধ্য |</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="141"/>
|
||||
@ -827,7 +827,7 @@ The installer will quit and all changes will be lost.</source>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="201"/>
|
||||
<source>'%1' is not allowed as hostname.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>'%1'ক আয়োজকৰ নাম হিচাপে ব্যৱহাৰ কৰা অবধ্য |</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="211"/>
|
||||
@ -1768,7 +1768,7 @@ The installer will quit and all changes will be lost.</source>
|
||||
<message>
|
||||
<location filename="../src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp" line="208"/>
|
||||
<source>Could not configure LUKS key file on partition %1.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>%1 বিভাজনত LUKS কি ফাইল কনফিগাৰ কৰিব পৰা নগ'ল।</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -1796,7 +1796,9 @@ The installer will quit and all changes will be lost.</source>
|
||||
<source>Please select your preferred location on the map so the installer can suggest the locale
|
||||
and timezone settings for you. You can fine-tune the suggested settings below. Search the map by dragging
|
||||
to move and using the +/- buttons to zoom in/out or use mouse scrolling for zooming.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>অনুগ্ৰহ কৰি নিজৰ প্রিয় স্থান নক্সাখ্নত বাছক জাতে ইস্নস্তালাৰটোৱে অপোনাক থলী
|
||||
আৰু সময় অঞ্চলৰ ছেটিংছ আপোৰ বাবে মিলাই দায়ক | আপোনি পৰামৰ্শমূলক ছেটিংছবোৰক তলত অনুকূলিত কৰিব পাৰে | নক্সাখ্নত পৈন্তেৰদালক টানি অনুসন্ধান কৰিব |
|
||||
আৰু +/- বুটামেৰে যোম in/out কৰক বা মাউছৰ সচৰোলৰও ব্যবহাৰ কৰিব পাৰে |</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -1810,92 +1812,92 @@ The installer will quit and all changes will be lost.</source>
|
||||
<message>
|
||||
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="64"/>
|
||||
<source>Office software</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>কাৰ্যালয়ৰ ছফটৱেৰ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="65"/>
|
||||
<source>Office package</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>কাৰ্যালয়ৰ পেকেজ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="66"/>
|
||||
<source>Browser software</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>ব্ৰাউজাৰৰ ছফটৱেৰ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="67"/>
|
||||
<source>Browser package</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>ব্ৰাউজাৰৰ পেকেজ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="68"/>
|
||||
<source>Web browser</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation> ৱেব ব্ৰাউজাৰ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="69"/>
|
||||
<source>Kernel</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>কাৰ্ণেল</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="70"/>
|
||||
<source>Services</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>সেৰ্ৱিচেস</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="71"/>
|
||||
<source>Login</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>পৰীক্ষণ কৰক</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="72"/>
|
||||
<source>Desktop</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>দেস্কেতোপ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="73"/>
|
||||
<source>Applications</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>এপ্লীকেছ্নচ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="74"/>
|
||||
<source>Communication</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>যোগাযোগ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="75"/>
|
||||
<source>Development</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>প্রবৃদ্ধি</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="76"/>
|
||||
<source>Office</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>কাৰ্যালয়</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="77"/>
|
||||
<source>Multimedia</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>মাল্টিমিডিয়া</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="78"/>
|
||||
<source>Internet</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>ইণ্টাৰনেট</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="79"/>
|
||||
<source>Theming</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>থিমীং</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="80"/>
|
||||
<source>Gaming</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>খেলা</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="81"/>
|
||||
<source>Utilities</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>সঁজুলি</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -1903,7 +1905,7 @@ The installer will quit and all changes will be lost.</source>
|
||||
<message>
|
||||
<location filename="../src/modules/notesqml/NotesQmlViewStep.cpp" line="34"/>
|
||||
<source>Notes</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>টোকা</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -1942,12 +1944,12 @@ The installer will quit and all changes will be lost.</source>
|
||||
<message>
|
||||
<location filename="../src/modules/localeq/Offline.qml" line="62"/>
|
||||
<source>Timezone: %1</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>সময় অঞ্চল: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/localeq/Offline.qml" line="77"/>
|
||||
<source>To be able to select a timezone, make sure you are connected to the internet. Restart the installer after connecting. You can fine-tune Language and Locale settings below.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>সময় অঞ্চল বাছিবলৈ, ইণ্টাৰনেটত সংশ্লিষ্ট কৰি ৰাখিব | সংশ্লিষ্ট কৰি ইন্স্তালাৰটো পুনৰাৰম্ভ কৰক | আপোনি ভাসা অৰু থলীৰ ছেটিংছবোৰ তলত অনুকূলিত কৰিব পাৰে |</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -2599,12 +2601,12 @@ The installer will quit and all changes will be lost.</source>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="436"/>
|
||||
<source>An EFI system partition is necessary to start %1.<br/><br/>To configure an EFI system partition, go back and select or create a FAT32 filesystem with the <strong>%3</strong> flag enabled and mount point <strong>%2</strong>.<br/><br/>You can continue without setting up an EFI system partition but your system may fail to start.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>%1 আৰম্ভ কৰিবলৈ এটা EFI চিছটেম থকাটো আৱশ্যক। <br/><br/>এটা EFI চিছটেম কন্ফিগাৰ কৰিবলৈ উভতি যাওক আৰু FAT32 ফাইল চিছটেম এটা বাচনি কৰক যিটোত <strong>%3</strong> ফ্লেগ সক্ষম হৈ আছে আৰু <strong>%2</strong> মাউন্ট্ পইণ্ট্ আছে।<br/><br/>আপুনি EFI চিছটেমবিভাজন কন্ফিগাৰ নকৰাকৈ অগ্ৰসৰ হ'ব পাৰে কিন্তু ইয়াৰ ফলত চিছটেম বিফল হ'ব পাৰে।</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="450"/>
|
||||
<source>An EFI system partition is necessary to start %1.<br/><br/>A partition was configured with mount point <strong>%2</strong> but its <strong>%3</strong> flag is not set.<br/>To set the flag, go back and edit the partition.<br/><br/>You can continue without setting the flag but your system may fail to start.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>%1 আৰম্ভ কৰিবলৈ এটা EFI চিছটেম থকাটো আৱশ্যক। %2 মাউন্ট্ পইন্ট্ নোহোৱকৈ কন্ফিগাৰ কৰা হৈছিল, কিন্তু ইয়াৰ esp ফ্লেগ ছেট কৰা হোৱা নাই। ফ্লেগ্ ছেট কৰিবলৈ উভতি যাওক আৰু বিভাজন সলনি কৰক। আপুনি ফ্লেগ ছেট নকৰাকৈ অগ্ৰসৰ হ'ব পাৰে কিন্তু ইয়াৰ ফলত চিছটেম বিফল হ'ব পাৰে। </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="449"/>
|
||||
@ -2614,12 +2616,12 @@ The installer will quit and all changes will be lost.</source>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="476"/>
|
||||
<source>Option to use GPT on BIOS</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>GPTৰ BIOSত ব্যৱহাৰৰ বাবে বিকল্প</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="477"/>
|
||||
<source>A GPT partition table is the best option for all systems. This installer supports such a setup for BIOS systems too.<br/><br/>To configure a GPT partition table on BIOS, (if not done so already) go back and set the partition table to GPT, next create a 8 MB unformatted partition with the <strong>bios_grub</strong> flag enabled.<br/><br/>An unformatted 8 MB partition is necessary to start %1 on a BIOS system with GPT.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>এটা GPT পৰ্তিসোন টেবুল সকলো স্যস্তেমৰ বাবে উত্তম বিকল্প হয় | এই ইন্সালাৰতোৱে তেনে স্থাপনকৰণ BIOS স্যস্তেমতো কৰে |<br/><br/>এটা GPT পৰ্তিসোন টেবুল কনফিগাৰ কৰিবলৈ ( যদি আগতে কৰা নাই ) পাছলৈ গৈ পৰ্তিসোন টেবুলখনক GPTলৈ পৰিৱৰ্তন কৰক, তাৰপাচত 8 MBৰ উনফোৰমেতেট পৰ্তিতিওন এটা বনাব | <strong>bios_grub</strong> flag enabled.<br/><br/>An unformatted 8 MB partition is necessary to start %1 on a BIOS system with GPT.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="505"/>
|
||||
@ -2639,7 +2641,7 @@ The installer will quit and all changes will be lost.</source>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="724"/>
|
||||
<source>There are no partitions to install on.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>ইনস্তল কৰিবলৈ কোনো বিভাজন নাই।</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -2852,7 +2854,7 @@ Output:
|
||||
<location filename="../src/modules/welcomeq/Recommended.qml" line="49"/>
|
||||
<source><p>This computer does not satisfy some of the recommended requirements for setting up %1.<br/>
|
||||
Setup can continue, but some features might be disabled.</p></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>%1 চেত্ আপৰ বাবে পৰামৰ্শ দিয়া আৱশ্যকতা এই কম্পিউটাৰটোৱে পূৰ্ণ নকৰে। <br/>স্থাপন প্ৰক্ৰিয়া অবিৰত ৰাখিব পাৰিব, কিন্তু কিছুমান সুবিধা নিষ্ক্রিয় হৈ থাকিব। </translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -2963,13 +2965,14 @@ Output:
|
||||
<location filename="../src/modules/welcomeq/Requirements.qml" line="47"/>
|
||||
<source><p>This computer does not satisfy the minimum requirements for installing %1.<br/>
|
||||
Installation cannot continue.</p></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>%1 ইনস্তলচেনৰ বাবে নিম্নতম আৱশ্যকতা এই কম্পিউটাৰটোৱে পূৰ্ণ নকৰে।
|
||||
<br/>ইনস্তলচেন প্ৰক্ৰিয়া অবিৰত ৰাখিব নোৱাৰিব।</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/welcomeq/Requirements.qml" line="49"/>
|
||||
<source><p>This computer does not satisfy some of the recommended requirements for setting up %1.<br/>
|
||||
Setup can continue, but some features might be disabled.</p></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>%1 চেত্ আপৰ বাবে পৰামৰ্শ দিয়া আৱশ্যকতা এই কম্পিউটাৰটোৱে পূৰ্ণ নকৰে। <br/>স্থাপন প্ৰক্ৰিয়া অবিৰত ৰাখিব পাৰিব, কিন্তু কিছুমান সুবিধা নিষ্ক্রিয় হৈ থাকিব। </translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -3435,28 +3438,28 @@ Output:
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/TrackingJobs.cpp" line="143"/>
|
||||
<source>KDE user feedback</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>KDE ব্যৱহাৰকৰ্তাৰ সম্বন্ধীয় প্ৰতিক্ৰীয়া</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/TrackingJobs.cpp" line="155"/>
|
||||
<source>Configuring KDE user feedback.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>কনফিগাৰত KDE ব্যৱহাৰকৰ্তাৰ সম্বন্ধীয় প্ৰতিক্ৰীয়া</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/TrackingJobs.cpp" line="177"/>
|
||||
<location filename="../src/modules/tracking/TrackingJobs.cpp" line="183"/>
|
||||
<source>Error in KDE user feedback configuration.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>KDE ব্যৱহাৰকৰ্তাৰ ফিডবেক কনফিগাৰেচনৰ ক্ৰুটি।</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/TrackingJobs.cpp" line="178"/>
|
||||
<source>Could not configure KDE user feedback correctly, script error %1.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>KDE ব্যৱহাৰকৰ্তাৰ প্ৰতিক্ৰিয়া ঠাকভাৱে কন্ফিগাৰ কৰিব পৰা নগ'ল, লিপি ক্ৰুটি %1।</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/TrackingJobs.cpp" line="184"/>
|
||||
<source>Could not configure KDE user feedback correctly, Calamares error %1.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>KDE ব্যৱহাৰকৰ্তাৰ প্ৰতিক্ৰিয়া ঠাকভাৱে কন্ফিগাৰ কৰিব পৰা নগ'ল, কেলামাৰেচ ক্ৰুটি %1।</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -3503,7 +3506,7 @@ Output:
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/page_trackingstep.ui" line="72"/>
|
||||
<source><html><head/><body><p>Click here to send <span style=" font-weight:600;">no information at all</span> about your installation.</p></body></html></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><html><head/><body><p>এইটো বাচনি কৰি, ইনস্তলচেনৰ বিষয়ে <span style=" font-weight:600;">মুঠতে একো তথ্য</span> আপুনি নপঠায়।</p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/page_trackingstep.ui" line="271"/>
|
||||
@ -3518,17 +3521,17 @@ Output:
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/TrackingPage.cpp" line="100"/>
|
||||
<source>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.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>এইটো বাচনি কৰি আপুনি ইনস্তলচেন আৰু হাৰ্ডৱেৰৰ বিষয়ে তথ্য পঠাব। ইনস্তলচেনৰ পিছত <b>এই তথ্য এবাৰ পঠোৱা হ'ব</b>।</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/TrackingPage.cpp" line="103"/>
|
||||
<source>By selecting this you will periodically send information about your <b>machine</b> installation, hardware and applications, to %1.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>এইটো বাচনি কৰি আপুনি ইনস্তলচেন, হাৰ্ডৱেৰ আৰু এপ্লিকেচনৰ বিষয়ে <b>মেচিন</b> %1লৈ তথ্য পঠাব।</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/TrackingPage.cpp" line="107"/>
|
||||
<source>By selecting this you will regularly send information about your <b>user</b> installation, hardware, applications and application usage patterns, to %1.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>এইটো বাচনি কৰি আপুনি ইনস্তলচেন, হাৰ্ডৱেৰ আৰু এপ্লিকেচনৰ বিষয়ে <b>ব্যৱহাৰকৰ্তা</b> %1লৈ তথ্য পঠাব।</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -3727,7 +3730,7 @@ Output:
|
||||
<message>
|
||||
<location filename="../src/modules/welcome/WelcomePage.cpp" line="247"/>
|
||||
<source><h1>%1</h1><br/><strong>%2<br/>for %3</strong><br/><br/>Copyright 2014-2017 Teo Mrnjavac &lt;teo@kde.org&gt;<br/>Copyright 2017-2020 Adriaan de Groot &lt;groot@kde.org&gt;<br/>Thanks to <a href="https://calamares.io/team/">the Calamares team</a> and the <a href="https://www.transifex.com/calamares/calamares/">Calamares translators team</a>.<br/><br/><a href="https://calamares.io/">Calamares</a> development is sponsored by <br/><a href="http://www.blue-systems.com/">Blue Systems</a> - Liberating Software.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><h1>%1</h1><br/><strong>%2<br/>ৰ বাবে %3</strong><br/><br/> মালিকিস্বত্ত 2014-2017 Teo Mrnjavac &lt;teo@kde.org&gt;<br/>মালিকিস্বত্ত 2017-2020 Adriaan de Groot &lt;groot@kde.org&gt;<br/><a href="https://calamares.io/team/">Calamares দল</a> আৰু <a href="https://www.transifex.com/calamares/calamares/">কেলামাৰেচ অনুবাদক দল</a>ক ধন্যবাদ জনাইছো।<br/><br/><a href="https://calamares.io/">Calamares</a>ৰ বিকাশ<br/><a href="http://www.blue-systems.com/">Blue Systems</a>- Liberating Softwareৰ দ্বাৰা প্ৰযোজিত।</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -3762,12 +3765,23 @@ Output:
|
||||
development is sponsored by <br/>
|
||||
<a href='http://www.blue-systems.com/'>Blue Systems</a> -
|
||||
Liberating Software.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><h1>%1</h1><br/>
|
||||
<strong>%2<br/>
|
||||
ৰ বাবে %3</strong><br/><br/>
|
||||
মালিকিস্বত্ত 2014-2017 Teo Mrnjavac &lt;teo@kde.org&gt;<br/>
|
||||
মালিকিস্বত্ত 2017-2020 Adriaan de Groot &lt;groot@kde.org&gt;<br/>
|
||||
ক ধন্যবাদ জনাইছো<a href='https://calamares.io/team/'> Calamares দল
|
||||
আৰু <a href='https://www.transifex.com/calamares/calamares/'>Calamares
|
||||
অনুবাদক দল</a>.<br/><br/>
|
||||
<a href='https://calamares.io/'>Calamares</a>
|
||||
ৰ বিকাশ<br/>
|
||||
<a href='http://www.blue-systems.com/'>Blue Systems</a> -
|
||||
Liberating Softwareৰ দ্বাৰা প্ৰযোজিত।.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/welcomeq/about.qml" line="105"/>
|
||||
<source>Back</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>পাছলৈ</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -3776,18 +3790,20 @@ Output:
|
||||
<location filename="../src/modules/localeq/i18n.qml" line="55"/>
|
||||
<source><h1>Languages</h1> </br>
|
||||
The system locale setting affects the language and character set for some command line user interface elements. The current setting is <strong>%1</strong>.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><h1>ভাষা</h1> </br>
|
||||
চিছটেমৰ স্থানীয় ছেটিংস্ কমাণ্ডলাইনৰ কিছুমান উপভোক্তা ইন্টাৰফেছ উপাদানৰ ভাষা আৰু আখৰবোৰত প্ৰভাৱ পেলায়। বৰ্তমান ছেটিংস্ হ'ল: <strong>%1</strong>.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/localeq/i18n.qml" line="115"/>
|
||||
<source><h1>Locales</h1> </br>
|
||||
The system locale setting affects the numbers and dates format. The current setting is <strong>%1</strong>.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><h1>স্থানীয়</h1> </br>
|
||||
চিছটেমৰ স্থানীয় ছেটিংসে উপাদানৰ নম্বৰ আৰু তাৰিখ সজ্জা প্ৰভাৱ পেলায়। বৰ্তমান ছেটিংস্ হ'ল: <strong>%1</strong>.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/localeq/i18n.qml" line="167"/>
|
||||
<source>Back</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>পাছলৈ</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -3795,44 +3811,44 @@ Output:
|
||||
<message>
|
||||
<location filename="../src/modules/keyboardq/keyboardq.qml" line="20"/>
|
||||
<source>Keyboard Model</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>কিবোৰ্ড মডেল</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/keyboardq/keyboardq.qml" line="21"/>
|
||||
<source>Pick your preferred keyboard model or use the default one based on the detected hardware</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>আপোনাৰ প্ৰিয় কিবোৰ্ড মডেল চয়ন কৰক বা আপোনাৰ হাৰ্ডৱেৰৰ গতানুগতিকখ্নক ব্যৱহাৰ কৰক |</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/keyboardq/keyboardq.qml" line="56"/>
|
||||
<source>Refresh</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>সতেজ কৰক</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/keyboardq/keyboardq.qml" line="62"/>
|
||||
<location filename="../src/modules/keyboardq/keyboardq.qml" line="169"/>
|
||||
<source>Layouts</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>লেআউট</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/keyboardq/keyboardq.qml" line="75"/>
|
||||
<location filename="../src/modules/keyboardq/keyboardq.qml" line="134"/>
|
||||
<source>Keyboard Layout</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>কিবোৰ্ড লেআউট</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/keyboardq/keyboardq.qml" line="113"/>
|
||||
<source>Models</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>মডেল</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/keyboardq/keyboardq.qml" line="121"/>
|
||||
<source>Variants</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>ভিন্ন ৰুপ</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/keyboardq/keyboardq.qml" line="180"/>
|
||||
<source>Test your keyboard</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>কিবোৰ্ড পৰীক্ষা কৰক</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -3840,7 +3856,7 @@ Output:
|
||||
<message>
|
||||
<location filename="../src/modules/localeq/localeq.qml" line="82"/>
|
||||
<source>Change</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>সলনি</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -3849,7 +3865,8 @@ Output:
|
||||
<location filename="../src/modules/notesqml/notesqml.qml" line="61"/>
|
||||
<source><h3>%1</h3>
|
||||
<p>These are example release notes.</p></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><h3>%1</h3>
|
||||
<p>এই খিনি ৰিলিজ নোতৰ উদাহৰণ </p></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -3882,7 +3899,7 @@ Output:
|
||||
<message>
|
||||
<location filename="../src/modules/welcomeq/release_notes.qml" line="85"/>
|
||||
<source>Back</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>পাছলৈ</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -3891,32 +3908,33 @@ Output:
|
||||
<location filename="../src/modules/welcomeq/welcomeq.qml" line="44"/>
|
||||
<source><h3>Welcome to the %1 <quote>%2</quote> installer</h3>
|
||||
<p>This program will ask you some questions and set up %1 on your computer.</p></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><h3>স্বাগতম আপোনাক %1 <quote>%2</quote> ইন্সালাৰটোত</h3>
|
||||
<p>এই প্ৰোগ্ৰেমটোএয়ে অপোনাক কিৱছোমান প্ৰশ্ন সুধিব আৰু আপোনাৰ কোম্পিউটাৰত %1 স্থাপনকৰণ কৰিব |</p></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/welcomeq/welcomeq.qml" line="75"/>
|
||||
<source>About</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>সম্পর্কে</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/welcomeq/welcomeq.qml" line="89"/>
|
||||
<source>Support</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>সহায়</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/welcomeq/welcomeq.qml" line="100"/>
|
||||
<source>Known issues</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>জ্ঞাত সমস্যা</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/welcomeq/welcomeq.qml" line="111"/>
|
||||
<source>Release notes</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>মুক্তি টোকা </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/welcomeq/welcomeq.qml" line="123"/>
|
||||
<source>Donate</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>দান কৰক </translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
|
@ -776,22 +776,22 @@ L'instalador va colar y van perdese tolos cambeos.</translation>
|
||||
<message>
|
||||
<location filename="../src/modules/welcome/Config.cpp" line="245"/>
|
||||
<source><h1>Welcome to the Calamares setup program for %1</h1></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><h1>Afáyate nel programa de configuración de Calamares pa %1</h1></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/welcome/Config.cpp" line="246"/>
|
||||
<source><h1>Welcome to %1 setup</h1></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><h1>Afáyate na configuración de %1</h1></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/welcome/Config.cpp" line="251"/>
|
||||
<source><h1>Welcome to the Calamares installer for %1</h1></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><h1>Afáyate nel instalador Calamares pa %1</h1></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/welcome/Config.cpp" line="252"/>
|
||||
<source><h1>Welcome to the %1 installer</h1></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><h1>Afáyate nel instalador de %1</h1></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="125"/>
|
||||
@ -1432,7 +1432,7 @@ L'instalador va colar y van perdese tolos cambeos.</translation>
|
||||
<message>
|
||||
<location filename="../src/modules/welcome/checker/GeneralRequirements.cpp" line="198"/>
|
||||
<source>is running the installer as an administrator (root)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>ta executando l'instalador como alministrador (root)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/welcome/checker/GeneralRequirements.cpp" line="201"/>
|
||||
@ -1447,7 +1447,7 @@ L'instalador va colar y van perdese tolos cambeos.</translation>
|
||||
<message>
|
||||
<location filename="../src/modules/welcome/checker/GeneralRequirements.cpp" line="210"/>
|
||||
<source>has a screen large enough to show the whole installer</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>tien una pantalla abondo grande como p'amosar tol instalador</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/welcome/checker/GeneralRequirements.cpp" line="213"/>
|
||||
@ -1884,7 +1884,7 @@ L'instalador va colar y van perdese tolos cambeos.</translation>
|
||||
<message>
|
||||
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="79"/>
|
||||
<source>Theming</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Estilu</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/netinstall/NetInstallViewStep.cpp" line="80"/>
|
||||
@ -2851,7 +2851,8 @@ Salida:
|
||||
<location filename="../src/modules/welcomeq/Recommended.qml" line="49"/>
|
||||
<source><p>This computer does not satisfy some of the recommended requirements for setting up %1.<br/>
|
||||
Setup can continue, but some features might be disabled.</p></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><p>Esti ordenador nun satisfaz nengún de los requirimientos aconseyaos pa configurar %1.<br/>
|
||||
La configuración pue siguir pero quiciabes se desactiven dalgunes carauterístiques.</p></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -2962,13 +2963,15 @@ Salida:
|
||||
<location filename="../src/modules/welcomeq/Requirements.qml" line="47"/>
|
||||
<source><p>This computer does not satisfy the minimum requirements for installing %1.<br/>
|
||||
Installation cannot continue.</p></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><p>Esti ordenador nun satisfaz los requirimientos mínimos pa instalar %1.<br/>
|
||||
La instalación nun pue siguir.</p></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/welcomeq/Requirements.qml" line="49"/>
|
||||
<source><p>This computer does not satisfy some of the recommended requirements for setting up %1.<br/>
|
||||
Setup can continue, but some features might be disabled.</p></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><p>Esti ordenador nun satisfaz nengún de los requirimientos aconseyaos pa configurar %1.<br/>
|
||||
La configuración pue siguir pero quiciabes se desactiven dalgunes carauterístiques.</p></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -3517,7 +3520,7 @@ Salida:
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/TrackingPage.cpp" line="100"/>
|
||||
<source>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.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Al esbillar esto vas unviar información tocante a la instalación y el hardware. Esta información va unviase namás <b>una vegada</b> dempués de finar la instalación.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/TrackingPage.cpp" line="103"/>
|
||||
|
@ -6,7 +6,7 @@
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/BootInfoWidget.cpp" line="71"/>
|
||||
<source>The <strong>boot environment</strong> of this system.<br><br>Older x86 systems only support <strong>BIOS</strong>.<br>Modern systems usually use <strong>EFI</strong>, but may also show up as BIOS if started in compatibility mode.</source>
|
||||
<translation>Bu sistemin <strong>açılış mühiti</strong>.<br><br>Köhnə x86 sistemlər yalnız <strong>BIOS</strong> dəstəkləyir.<br>Müasir sistemlər isə adətən <strong>EFI</strong> istifadə edir, lakin açılış mühiti əgər uyğun rejimdə başladılmışsa, həmçinin BİOS istiafadə edə bilər.</translation>
|
||||
<translation>Sistemin <strong>açılış mühiti</strong>.<br><br>Köhnə x86 sistemlər yalnız <strong>BIOS</strong> dəstəkləyir.<br>Müasir sistemlər isə adətən <strong>EFI</strong> istifadə edir, lakin açılış mühiti əgər uyğun rejimdə başladılmışsa, həmçinin BİOS istiafadə edə bilər.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/BootInfoWidget.cpp" line="81"/>
|
||||
@ -65,12 +65,12 @@
|
||||
<message>
|
||||
<location filename="../src/calamares/DebugWindow.ui" line="24"/>
|
||||
<source>GlobalStorage</source>
|
||||
<translation>Ümumi yaddaş</translation>
|
||||
<translation>ÜmumiYaddaş</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/calamares/DebugWindow.ui" line="34"/>
|
||||
<source>JobQueue</source>
|
||||
<translation>Tapşırıq sırası</translation>
|
||||
<translation>TapşırıqSırası</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/calamares/DebugWindow.ui" line="44"/>
|
||||
@ -530,7 +530,7 @@ Bu proqramdan çıxılacaq və bütün dəyişikliklər itiriləcəkdir.</transl
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="334"/>
|
||||
<source><strong>Manual partitioning</strong><br/>You can create or resize partitions yourself.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><strong>Əl ilə bölmək</strong><br/>Siz bölməni özünüz yarada və ölçüsünü dəyişə bilərsiniz.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="831"/>
|
||||
@ -717,7 +717,7 @@ Bu proqramdan çıxılacaq və bütün dəyişikliklər itiriləcəkdir.</transl
|
||||
<message>
|
||||
<location filename="../src/modules/locale/Config.cpp" line="333"/>
|
||||
<source>Set timezone to %1/%2.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Saat quraşağını təyin etmək %1/%2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/locale/Config.cpp" line="348"/>
|
||||
@ -802,7 +802,7 @@ Bu proqramdan çıxılacaq və bütün dəyişikliklər itiriləcəkdir.</transl
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="131"/>
|
||||
<source>'%1' is not allowed as username.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>İstifadəçi adı '%1' ola bilməz</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="141"/>
|
||||
@ -827,7 +827,7 @@ Bu proqramdan çıxılacaq və bütün dəyişikliklər itiriləcəkdir.</transl
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="201"/>
|
||||
<source>'%1' is not allowed as hostname.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Host_adı '%1' ola bilməz</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="211"/>
|
||||
@ -3800,7 +3800,8 @@ Output:
|
||||
<location filename="../src/modules/localeq/i18n.qml" line="115"/>
|
||||
<source><h1>Locales</h1> </br>
|
||||
The system locale setting affects the numbers and dates format. The current setting is <strong>%1</strong>.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><h1>Yerlər</h1></br>
|
||||
Sistemin məkan ayarları say və tarix formatlarəna təsir edir. Cari ayar <strong>%1</strong>-dir</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/localeq/i18n.qml" line="167"/>
|
||||
|
@ -530,7 +530,7 @@ Bu proqramdan çıxılacaq və bütün dəyişikliklər itiriləcəkdir.</transl
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="334"/>
|
||||
<source><strong>Manual partitioning</strong><br/>You can create or resize partitions yourself.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><strong>Əl ilə bölmək</strong><br/>Siz bölməni özünüz yarada və ölçüsünü dəyişə bilərsiniz.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="831"/>
|
||||
@ -717,7 +717,7 @@ Bu proqramdan çıxılacaq və bütün dəyişikliklər itiriləcəkdir.</transl
|
||||
<message>
|
||||
<location filename="../src/modules/locale/Config.cpp" line="333"/>
|
||||
<source>Set timezone to %1/%2.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Saat quraşağını təyin etmək %1/%2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/locale/Config.cpp" line="348"/>
|
||||
@ -802,7 +802,7 @@ Bu proqramdan çıxılacaq və bütün dəyişikliklər itiriləcəkdir.</transl
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="131"/>
|
||||
<source>'%1' is not allowed as username.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>İstifadəçi adı '%1' ola bilməz</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="141"/>
|
||||
@ -827,7 +827,7 @@ Bu proqramdan çıxılacaq və bütün dəyişikliklər itiriləcəkdir.</transl
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="201"/>
|
||||
<source>'%1' is not allowed as hostname.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Host_adı '%1' ola bilməz</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="211"/>
|
||||
@ -3800,7 +3800,8 @@ Output:
|
||||
<location filename="../src/modules/localeq/i18n.qml" line="115"/>
|
||||
<source><h1>Locales</h1> </br>
|
||||
The system locale setting affects the numbers and dates format. The current setting is <strong>%1</strong>.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><h1>Yerlər</h1></br>
|
||||
Sistemin məkan ayarları say və tarix formatlarəna təsir edir. Cari ayar <strong>%1</strong>-dir</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/localeq/i18n.qml" line="167"/>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -717,7 +717,7 @@ Installationsprogrammet vil stoppe og alle ændringer vil gå tabt.</translation
|
||||
<message>
|
||||
<location filename="../src/modules/locale/Config.cpp" line="333"/>
|
||||
<source>Set timezone to %1/%2.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Indstil tidszone til %1/%2.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/locale/Config.cpp" line="348"/>
|
||||
@ -802,7 +802,7 @@ Installationsprogrammet vil stoppe og alle ændringer vil gå tabt.</translation
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="131"/>
|
||||
<source>'%1' is not allowed as username.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>'%1' er ikke tilladt som brugernavn.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="141"/>
|
||||
@ -827,7 +827,7 @@ Installationsprogrammet vil stoppe og alle ændringer vil gå tabt.</translation
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="201"/>
|
||||
<source>'%1' is not allowed as hostname.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>'%1' er ikke tilladt som værtsnavn.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="211"/>
|
||||
@ -3801,7 +3801,8 @@ setting
|
||||
<location filename="../src/modules/localeq/i18n.qml" line="115"/>
|
||||
<source><h1>Locales</h1> </br>
|
||||
The system locale setting affects the numbers and dates format. The current setting is <strong>%1</strong>.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><h1>Lokaliteter</h1> </br>
|
||||
Systemets lokalitetsindstillinger påvirker tal- og datoformater. Den nuværende indstilling er <strong>%1</strong>.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/localeq/i18n.qml" line="167"/>
|
||||
|
@ -510,134 +510,134 @@ The installer will quit and all changes will be lost.</translation>
|
||||
<translation>Form</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="156"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="139"/>
|
||||
<source>Select storage de&vice:</source>
|
||||
<translation>Select storage de&vice:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="157"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="955"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1000"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1086"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="140"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="938"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="983"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1069"/>
|
||||
<source>Current:</source>
|
||||
<translation>Current:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="158"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="141"/>
|
||||
<source>After:</source>
|
||||
<translation>After:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="334"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="317"/>
|
||||
<source><strong>Manual partitioning</strong><br/>You can create or resize partitions yourself.</source>
|
||||
<translation><strong>Manual partitioning</strong><br/>You can create or resize partitions yourself.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="831"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="814"/>
|
||||
<source>Reuse %1 as home partition for %2.</source>
|
||||
<translation>Reuse %1 as home partition for %2.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="956"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="939"/>
|
||||
<source><strong>Select a partition to shrink, then drag the bottom bar to resize</strong></source>
|
||||
<translation><strong>Select a partition to shrink, then drag the bottom bar to resize</strong></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="971"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="954"/>
|
||||
<source>%1 will be shrunk to %2MiB and a new %3MiB partition will be created for %4.</source>
|
||||
<translation>%1 will be shrunk to %2MiB and a new %3MiB partition will be created for %4.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1028"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1011"/>
|
||||
<source>Boot loader location:</source>
|
||||
<translation>Boot loader location:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1077"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1060"/>
|
||||
<source><strong>Select a partition to install on</strong></source>
|
||||
<translation><strong>Select a partition to install on</strong></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1133"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1116"/>
|
||||
<source>An EFI system partition cannot be found anywhere on this system. Please go back and use manual partitioning to set up %1.</source>
|
||||
<translation>An EFI system partition cannot be found anywhere on this system. Please go back and use manual partitioning to set up %1.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1142"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1125"/>
|
||||
<source>The EFI system partition at %1 will be used for starting %2.</source>
|
||||
<translation>The EFI system partition at %1 will be used for starting %2.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1150"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1133"/>
|
||||
<source>EFI system partition:</source>
|
||||
<translation>EFI system partition:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1268"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1251"/>
|
||||
<source>This storage device does not seem to have an operating system on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device.</source>
|
||||
<translation>This storage device does not seem to have an operating system on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1273"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1311"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1334"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1360"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1256"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1294"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1317"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1343"/>
|
||||
<source><strong>Erase disk</strong><br/>This will <font color="red">delete</font> all data currently present on the selected storage device.</source>
|
||||
<translation><strong>Erase disk</strong><br/>This will <font color="red">delete</font> all data currently present on the selected storage device.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1277"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1307"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1330"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1356"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1260"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1290"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1313"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1339"/>
|
||||
<source><strong>Install alongside</strong><br/>The installer will shrink a partition to make room for %1.</source>
|
||||
<translation><strong>Install alongside</strong><br/>The installer will shrink a partition to make room for %1.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1281"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1316"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1338"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1364"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1264"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1299"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1321"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1347"/>
|
||||
<source><strong>Replace a partition</strong><br/>Replaces a partition with %1.</source>
|
||||
<translation><strong>Replace a partition</strong><br/>Replaces a partition with %1.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1301"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1284"/>
|
||||
<source>This storage device has %1 on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device.</source>
|
||||
<translation>This storage device has %1 on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1325"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1308"/>
|
||||
<source>This storage device already has an operating system on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device.</source>
|
||||
<translation>This storage device already has an operating system on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1351"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1334"/>
|
||||
<source>This storage device has multiple operating systems on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device.</source>
|
||||
<translation>This storage device has multiple operating systems on it. What would you like to do?<br/>You will be able to review and confirm your choices before any change is made to the storage device.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1505"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1517"/>
|
||||
<source>No Swap</source>
|
||||
<translation>No Swap</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1510"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1522"/>
|
||||
<source>Reuse Swap</source>
|
||||
<translation>Reuse Swap</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1513"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1525"/>
|
||||
<source>Swap (no Hibernate)</source>
|
||||
<translation>Swap (no Hibernate)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1516"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1528"/>
|
||||
<source>Swap (with Hibernate)</source>
|
||||
<translation>Swap (with Hibernate)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1519"/>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="1531"/>
|
||||
<source>Swap to file</source>
|
||||
<translation>Swap to file</translation>
|
||||
</message>
|
||||
@ -715,17 +715,17 @@ The installer will quit and all changes will be lost.</translation>
|
||||
<translation>Set keyboard layout to %1/%2.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/locale/Config.cpp" line="333"/>
|
||||
<location filename="../src/modules/locale/Config.cpp" line="350"/>
|
||||
<source>Set timezone to %1/%2.</source>
|
||||
<translation>Set timezone to %1/%2.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/locale/Config.cpp" line="348"/>
|
||||
<location filename="../src/modules/locale/Config.cpp" line="388"/>
|
||||
<source>The system language will be set to %1.</source>
|
||||
<translation>The system language will be set to %1.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/locale/Config.cpp" line="355"/>
|
||||
<location filename="../src/modules/locale/Config.cpp" line="395"/>
|
||||
<source>The numbers and dates locale will be set to %1.</source>
|
||||
<translation>The numbers and dates locale will be set to %1.</translation>
|
||||
</message>
|
||||
@ -795,42 +795,42 @@ The installer will quit and all changes will be lost.</translation>
|
||||
<translation><h1>Welcome to the %1 installer</h1></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="125"/>
|
||||
<location filename="../src/modules/users/Config.cpp" line="141"/>
|
||||
<source>Your username is too long.</source>
|
||||
<translation>Your username is too long.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="131"/>
|
||||
<location filename="../src/modules/users/Config.cpp" line="147"/>
|
||||
<source>'%1' is not allowed as username.</source>
|
||||
<translation>'%1' is not allowed as username.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="141"/>
|
||||
<location filename="../src/modules/users/Config.cpp" line="154"/>
|
||||
<source>Your username must start with a lowercase letter or underscore.</source>
|
||||
<translation>Your username must start with a lowercase letter or underscore.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="145"/>
|
||||
<location filename="../src/modules/users/Config.cpp" line="158"/>
|
||||
<source>Only lowercase letters, numbers, underscore and hyphen are allowed.</source>
|
||||
<translation>Only lowercase letters, numbers, underscore and hyphen are allowed.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="191"/>
|
||||
<location filename="../src/modules/users/Config.cpp" line="204"/>
|
||||
<source>Your hostname is too short.</source>
|
||||
<translation>Your hostname is too short.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="195"/>
|
||||
<location filename="../src/modules/users/Config.cpp" line="208"/>
|
||||
<source>Your hostname is too long.</source>
|
||||
<translation>Your hostname is too long.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="201"/>
|
||||
<location filename="../src/modules/users/Config.cpp" line="214"/>
|
||||
<source>'%1' is not allowed as hostname.</source>
|
||||
<translation>'%1' is not allowed as hostname.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="211"/>
|
||||
<location filename="../src/modules/users/Config.cpp" line="220"/>
|
||||
<source>Only letters, numbers, underscore and hyphen are allowed.</source>
|
||||
<translation>Only letters, numbers, underscore and hyphen are allowed.</translation>
|
||||
</message>
|
||||
@ -1251,7 +1251,8 @@ The installer will quit and all changes will be lost.</translation>
|
||||
<translation>Confirm passphrase</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/EncryptWidget.cpp" line="153"/>
|
||||
<location filename="../src/modules/partition/gui/EncryptWidget.cpp" line="113"/>
|
||||
<location filename="../src/modules/partition/gui/EncryptWidget.cpp" line="123"/>
|
||||
<source>Please enter the same passphrase in both boxes.</source>
|
||||
<translation>Please enter the same passphrase in both boxes.</translation>
|
||||
</message>
|
||||
@ -1703,18 +1704,18 @@ The installer will quit and all changes will be lost.</translation>
|
||||
<context>
|
||||
<name>LocalePage</name>
|
||||
<message>
|
||||
<location filename="../src/modules/locale/LocalePage.cpp" line="132"/>
|
||||
<location filename="../src/modules/locale/LocalePage.cpp" line="134"/>
|
||||
<source>Region:</source>
|
||||
<translation>Region:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/locale/LocalePage.cpp" line="133"/>
|
||||
<location filename="../src/modules/locale/LocalePage.cpp" line="135"/>
|
||||
<source>Zone:</source>
|
||||
<translation>Zone:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/locale/LocalePage.cpp" line="134"/>
|
||||
<location filename="../src/modules/locale/LocalePage.cpp" line="135"/>
|
||||
<location filename="../src/modules/locale/LocalePage.cpp" line="136"/>
|
||||
<location filename="../src/modules/locale/LocalePage.cpp" line="137"/>
|
||||
<source>&Change...</source>
|
||||
<translation>&Change...</translation>
|
||||
</message>
|
||||
@ -1792,7 +1793,12 @@ The installer will quit and all changes will be lost.</translation>
|
||||
<context>
|
||||
<name>Map</name>
|
||||
<message>
|
||||
<location filename="../src/modules/localeq/Map.qml" line="239"/>
|
||||
<location filename="../src/modules/localeq/Map.qml" line="252"/>
|
||||
<source>Timezone: %1</source>
|
||||
<translation type="unfinished">Timezone: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/localeq/Map.qml" line="273"/>
|
||||
<source>Please select your preferred location on the map so the installer can suggest the locale
|
||||
and timezone settings for you. You can fine-tune the suggested settings below. Search the map by dragging
|
||||
to move and using the +/- buttons to zoom in/out or use mouse scrolling for zooming.</source>
|
||||
@ -1955,247 +1961,247 @@ The installer will quit and all changes will be lost.</translation>
|
||||
<context>
|
||||
<name>PWQ</name>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="57"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="56"/>
|
||||
<source>Password is too short</source>
|
||||
<translation>Password is too short</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="73"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="72"/>
|
||||
<source>Password is too long</source>
|
||||
<translation>Password is too long</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="149"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="148"/>
|
||||
<source>Password is too weak</source>
|
||||
<translation>Password is too weak</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="157"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="156"/>
|
||||
<source>Memory allocation error when setting '%1'</source>
|
||||
<translation>Memory allocation error when setting '%1'</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="162"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="161"/>
|
||||
<source>Memory allocation error</source>
|
||||
<translation>Memory allocation error</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="164"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="163"/>
|
||||
<source>The password is the same as the old one</source>
|
||||
<translation>The password is the same as the old one</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="166"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="165"/>
|
||||
<source>The password is a palindrome</source>
|
||||
<translation>The password is a palindrome</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="168"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="167"/>
|
||||
<source>The password differs with case changes only</source>
|
||||
<translation>The password differs with case changes only</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="170"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="169"/>
|
||||
<source>The password is too similar to the old one</source>
|
||||
<translation>The password is too similar to the old one</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="172"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="171"/>
|
||||
<source>The password contains the user name in some form</source>
|
||||
<translation>The password contains the user name in some form</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="174"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="173"/>
|
||||
<source>The password contains words from the real name of the user in some form</source>
|
||||
<translation>The password contains words from the real name of the user in some form</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="177"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="176"/>
|
||||
<source>The password contains forbidden words in some form</source>
|
||||
<translation>The password contains forbidden words in some form</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="181"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="180"/>
|
||||
<source>The password contains less than %1 digits</source>
|
||||
<translation>The password contains less than %1 digits</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="184"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="183"/>
|
||||
<source>The password contains too few digits</source>
|
||||
<translation>The password contains too few digits</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="188"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="187"/>
|
||||
<source>The password contains less than %1 uppercase letters</source>
|
||||
<translation>The password contains less than %1 uppercase letters</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="191"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="190"/>
|
||||
<source>The password contains too few uppercase letters</source>
|
||||
<translation>The password contains too few uppercase letters</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="195"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="194"/>
|
||||
<source>The password contains less than %1 lowercase letters</source>
|
||||
<translation>The password contains less than %1 lowercase letters</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="198"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="197"/>
|
||||
<source>The password contains too few lowercase letters</source>
|
||||
<translation>The password contains too few lowercase letters</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="202"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="201"/>
|
||||
<source>The password contains less than %1 non-alphanumeric characters</source>
|
||||
<translation>The password contains less than %1 non-alphanumeric characters</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="206"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="205"/>
|
||||
<source>The password contains too few non-alphanumeric characters</source>
|
||||
<translation>The password contains too few non-alphanumeric characters</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="210"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="209"/>
|
||||
<source>The password is shorter than %1 characters</source>
|
||||
<translation>The password is shorter than %1 characters</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="213"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="212"/>
|
||||
<source>The password is too short</source>
|
||||
<translation>The password is too short</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="215"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="214"/>
|
||||
<source>The password is just rotated old one</source>
|
||||
<translation>The password is just rotated old one</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="219"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="218"/>
|
||||
<source>The password contains less than %1 character classes</source>
|
||||
<translation>The password contains less than %1 character classes</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="222"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="221"/>
|
||||
<source>The password does not contain enough character classes</source>
|
||||
<translation>The password does not contain enough character classes</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="226"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="225"/>
|
||||
<source>The password contains more than %1 same characters consecutively</source>
|
||||
<translation>The password contains more than %1 same characters consecutively</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="230"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="229"/>
|
||||
<source>The password contains too many same characters consecutively</source>
|
||||
<translation>The password contains too many same characters consecutively</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="234"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="233"/>
|
||||
<source>The password contains more than %1 characters of the same class consecutively</source>
|
||||
<translation>The password contains more than %1 characters of the same class consecutively</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="238"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="237"/>
|
||||
<source>The password contains too many characters of the same class consecutively</source>
|
||||
<translation>The password contains too many characters of the same class consecutively</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="243"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="242"/>
|
||||
<source>The password contains monotonic sequence longer than %1 characters</source>
|
||||
<translation>The password contains monotonic sequence longer than %1 characters</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="247"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="246"/>
|
||||
<source>The password contains too long of a monotonic character sequence</source>
|
||||
<translation>The password contains too long of a monotonic character sequence</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="250"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="249"/>
|
||||
<source>No password supplied</source>
|
||||
<translation>No password supplied</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="252"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="251"/>
|
||||
<source>Cannot obtain random numbers from the RNG device</source>
|
||||
<translation>Cannot obtain random numbers from the RNG device</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="254"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="253"/>
|
||||
<source>Password generation failed - required entropy too low for settings</source>
|
||||
<translation>Password generation failed - required entropy too low for settings</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="260"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="259"/>
|
||||
<source>The password fails the dictionary check - %1</source>
|
||||
<translation>The password fails the dictionary check - %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="263"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="262"/>
|
||||
<source>The password fails the dictionary check</source>
|
||||
<translation>The password fails the dictionary check</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="267"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="266"/>
|
||||
<source>Unknown setting - %1</source>
|
||||
<translation>Unknown setting - %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="271"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="270"/>
|
||||
<source>Unknown setting</source>
|
||||
<translation>Unknown setting</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="275"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="274"/>
|
||||
<source>Bad integer value of setting - %1</source>
|
||||
<translation>Bad integer value of setting - %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="280"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="279"/>
|
||||
<source>Bad integer value</source>
|
||||
<translation>Bad integer value</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="284"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="283"/>
|
||||
<source>Setting %1 is not of integer type</source>
|
||||
<translation>Setting %1 is not of integer type</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="289"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="288"/>
|
||||
<source>Setting is not of integer type</source>
|
||||
<translation>Setting is not of integer type</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="293"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="292"/>
|
||||
<source>Setting %1 is not of string type</source>
|
||||
<translation>Setting %1 is not of string type</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="298"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="297"/>
|
||||
<source>Setting is not of string type</source>
|
||||
<translation>Setting is not of string type</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="300"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="299"/>
|
||||
<source>Opening the configuration file failed</source>
|
||||
<translation>Opening the configuration file failed</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="302"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="301"/>
|
||||
<source>The configuration file is malformed</source>
|
||||
<translation>The configuration file is malformed</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="304"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="303"/>
|
||||
<source>Fatal failure</source>
|
||||
<translation>Fatal failure</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="306"/>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="305"/>
|
||||
<source>Unknown error</source>
|
||||
<translation>Unknown error</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/UsersPage.cpp" line="377"/>
|
||||
<location filename="../src/modules/users/Config.cpp" line="522"/>
|
||||
<source>Password is empty</source>
|
||||
<translation>Password is empty</translation>
|
||||
</message>
|
||||
@ -2529,67 +2535,67 @@ The installer will quit and all changes will be lost.</translation>
|
||||
<context>
|
||||
<name>PartitionViewStep</name>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="77"/>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="78"/>
|
||||
<source>Gathering system information...</source>
|
||||
<translation>Gathering system information...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="132"/>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="133"/>
|
||||
<source>Partitions</source>
|
||||
<translation>Partitions</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="170"/>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="171"/>
|
||||
<source>Install %1 <strong>alongside</strong> another operating system.</source>
|
||||
<translation>Install %1 <strong>alongside</strong> another operating system.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="175"/>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="176"/>
|
||||
<source><strong>Erase</strong> disk and install %1.</source>
|
||||
<translation><strong>Erase</strong> disk and install %1.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="179"/>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="180"/>
|
||||
<source><strong>Replace</strong> a partition with %1.</source>
|
||||
<translation><strong>Replace</strong> a partition with %1.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="183"/>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="184"/>
|
||||
<source><strong>Manual</strong> partitioning.</source>
|
||||
<translation><strong>Manual</strong> partitioning.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="196"/>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="197"/>
|
||||
<source>Install %1 <strong>alongside</strong> another operating system on disk <strong>%2</strong> (%3).</source>
|
||||
<translation>Install %1 <strong>alongside</strong> another operating system on disk <strong>%2</strong> (%3).</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="203"/>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="204"/>
|
||||
<source><strong>Erase</strong> disk <strong>%2</strong> (%3) and install %1.</source>
|
||||
<translation><strong>Erase</strong> disk <strong>%2</strong> (%3) and install %1.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="209"/>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="210"/>
|
||||
<source><strong>Replace</strong> a partition on disk <strong>%2</strong> (%3) with %1.</source>
|
||||
<translation><strong>Replace</strong> a partition on disk <strong>%2</strong> (%3) with %1.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="216"/>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="217"/>
|
||||
<source><strong>Manual</strong> partitioning on disk <strong>%1</strong> (%2).</source>
|
||||
<translation><strong>Manual</strong> partitioning on disk <strong>%1</strong> (%2).</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="225"/>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="226"/>
|
||||
<source>Disk <strong>%1</strong> (%2)</source>
|
||||
<translation>Disk <strong>%1</strong> (%2)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="251"/>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="252"/>
|
||||
<source>Current:</source>
|
||||
<translation>Current:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="268"/>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="269"/>
|
||||
<source>After:</source>
|
||||
<translation>After:</translation>
|
||||
</message>
|
||||
@ -2634,12 +2640,12 @@ The installer will quit and all changes will be lost.</translation>
|
||||
<translation>A separate boot partition was set up together with an encrypted root partition, but the boot partition is not encrypted.<br/><br/>There are security concerns with this kind of setup, because important system files are kept on an unencrypted partition.<br/>You may continue if you wish, but filesystem unlocking will happen later during system startup.<br/>To encrypt the boot partition, go back and recreate it, selecting <strong>Encrypt</strong> in the partition creation window.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="723"/>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="634"/>
|
||||
<source>has at least one disk device available.</source>
|
||||
<translation>has at least one disk device available.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="724"/>
|
||||
<location filename="../src/modules/partition/gui/PartitionViewStep.cpp" line="635"/>
|
||||
<source>There are no partitions to install on.</source>
|
||||
<translation>There are no partitions to install on.</translation>
|
||||
</message>
|
||||
@ -3547,17 +3553,17 @@ Output:
|
||||
<context>
|
||||
<name>UsersPage</name>
|
||||
<message>
|
||||
<location filename="../src/modules/users/UsersPage.cpp" line="170"/>
|
||||
<location filename="../src/modules/users/UsersPage.cpp" line="174"/>
|
||||
<source><small>If more than one person will use this computer, you can create multiple accounts after setup.</small></source>
|
||||
<translation><small>If more than one person will use this computer, you can create multiple accounts after setup.</small></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/UsersPage.cpp" line="176"/>
|
||||
<location filename="../src/modules/users/UsersPage.cpp" line="180"/>
|
||||
<source><small>If more than one person will use this computer, you can create multiple accounts after installation.</small></source>
|
||||
<translation><small>If more than one person will use this computer, you can create multiple accounts after installation.</small></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/UsersPage.cpp" line="277"/>
|
||||
<location filename="../src/modules/users/UsersPage.cpp" line="255"/>
|
||||
<source>Your passwords do not match!</source>
|
||||
<translation>Your passwords do not match!</translation>
|
||||
</message>
|
||||
@ -3565,7 +3571,7 @@ Output:
|
||||
<context>
|
||||
<name>UsersViewStep</name>
|
||||
<message>
|
||||
<location filename="../src/modules/users/UsersViewStep.cpp" line="77"/>
|
||||
<location filename="../src/modules/users/UsersViewStep.cpp" line="58"/>
|
||||
<source>Users</source>
|
||||
<translation>Users</translation>
|
||||
</message>
|
||||
@ -3856,7 +3862,7 @@ Output:
|
||||
<context>
|
||||
<name>localeq</name>
|
||||
<message>
|
||||
<location filename="../src/modules/localeq/localeq.qml" line="82"/>
|
||||
<location filename="../src/modules/localeq/localeq.qml" line="90"/>
|
||||
<source>Change</source>
|
||||
<translation>Change</translation>
|
||||
</message>
|
||||
|
@ -530,7 +530,7 @@ The installer will quit and all changes will be lost.</source>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="334"/>
|
||||
<source><strong>Manual partitioning</strong><br/>You can create or resize partitions yourself.</source>
|
||||
<translation><strong>मैनुअल विभाजन</strong><br/> आप स्वयं भी विभाजन बना व उनका आकार बदल सकते है।</translation>
|
||||
<translation><strong>मैनुअल विभाजन</strong><br/> स्वयं विभाजन बनाएँ या उनका आकार बदलें।</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/partition/gui/ChoicePage.cpp" line="831"/>
|
||||
@ -717,7 +717,7 @@ The installer will quit and all changes will be lost.</source>
|
||||
<message>
|
||||
<location filename="../src/modules/locale/Config.cpp" line="333"/>
|
||||
<source>Set timezone to %1/%2.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>समय क्षेत्र %1%2 सेट करें।</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/locale/Config.cpp" line="348"/>
|
||||
@ -797,42 +797,42 @@ The installer will quit and all changes will be lost.</source>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="125"/>
|
||||
<source>Your username is too long.</source>
|
||||
<translation>आपका उपयोक्ता नाम बहुत लंबा है।</translation>
|
||||
<translation>उपयोक्ता नाम बहुत लंबा है।</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="131"/>
|
||||
<source>'%1' is not allowed as username.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>उपयोक्ता नाम के रूप में '%1' का उपयोग अस्वीकार्य है।</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="141"/>
|
||||
<source>Your username must start with a lowercase letter or underscore.</source>
|
||||
<translation>आपके उपयोक्ता नाम का आरंभ lowercase अक्षर या अंडरस्कोर(_) से ही होना चाहिए।</translation>
|
||||
<translation>उपयोक्ता नाम का आरंभ केवल लोअरकेस अक्षर या अंडरस्कोर(-) से ही करें।</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="145"/>
|
||||
<source>Only lowercase letters, numbers, underscore and hyphen are allowed.</source>
|
||||
<translation>केवल lowercase अक्षर, अंक, अंडरस्कोर(_) व हाइफ़न(-) का उपयोग ही मान्य है।</translation>
|
||||
<translation>केवल लोअरकेस अक्षर, अंक, अंडरस्कोर(_) व हाइफ़न(-) ही स्वीकार्य हैं।</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="191"/>
|
||||
<source>Your hostname is too short.</source>
|
||||
<translation>आपका होस्ट नाम बहुत छोटा है।</translation>
|
||||
<translation>होस्ट नाम बहुत छोटा है।</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="195"/>
|
||||
<source>Your hostname is too long.</source>
|
||||
<translation>आपका होस्ट नाम बहुत लंबा है।</translation>
|
||||
<translation>होस्ट नाम बहुत लंबा है।</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="201"/>
|
||||
<source>'%1' is not allowed as hostname.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>होस्ट नाम के रूप में '%1' का उपयोग अस्वीकार्य है।</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="211"/>
|
||||
<source>Only letters, numbers, underscore and hyphen are allowed.</source>
|
||||
<translation>केवल अक्षर, अंक, अंडरस्कोर(_) व हाइफ़न(-) का उपयोग ही मान्य है।</translation>
|
||||
<translation>केवल अक्षर, अंक, अंडरस्कोर(_) व हाइफ़न(-) ही स्वीकार्य हैं।</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -3799,7 +3799,8 @@ Output:
|
||||
<location filename="../src/modules/localeq/i18n.qml" line="115"/>
|
||||
<source><h1>Locales</h1> </br>
|
||||
The system locale setting affects the numbers and dates format. The current setting is <strong>%1</strong>.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><h1>स्थानिकी</h1> </br>
|
||||
सिस्टम स्थानिकी सेटिंग संख्या व दिनांक के प्रारूप को प्रभावित करती है। वर्तमान सेटिंग <strong>%1</strong> है।</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/localeq/i18n.qml" line="167"/>
|
||||
|
@ -715,7 +715,7 @@ The installer will quit and all changes will be lost.</source>
|
||||
<message>
|
||||
<location filename="../src/modules/locale/Config.cpp" line="333"/>
|
||||
<source>Set timezone to %1/%2.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>タイムゾーンを %1/%2 に設定します。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/locale/Config.cpp" line="348"/>
|
||||
@ -725,7 +725,7 @@ The installer will quit and all changes will be lost.</source>
|
||||
<message>
|
||||
<location filename="../src/modules/locale/Config.cpp" line="355"/>
|
||||
<source>The numbers and dates locale will be set to %1.</source>
|
||||
<translation>数字と日付のロケールを %1 に設定します。</translation>
|
||||
<translation>数値と日付のロケールを %1 に設定します。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/netinstall/Config.cpp" line="47"/>
|
||||
@ -800,7 +800,7 @@ The installer will quit and all changes will be lost.</source>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="131"/>
|
||||
<source>'%1' is not allowed as username.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>'%1' はユーザー名として許可されていません。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="141"/>
|
||||
@ -825,7 +825,7 @@ The installer will quit and all changes will be lost.</source>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="201"/>
|
||||
<source>'%1' is not allowed as hostname.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>'%1' はホスト名として許可されていません。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="211"/>
|
||||
@ -3799,7 +3799,8 @@ Output:
|
||||
<location filename="../src/modules/localeq/i18n.qml" line="115"/>
|
||||
<source><h1>Locales</h1> </br>
|
||||
The system locale setting affects the numbers and dates format. The current setting is <strong>%1</strong>.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><h1>ロケール</h1> </br>
|
||||
システムのロケール設定は、数値と日付の形式に影響を及ぼします。現在の設定は <strong>%1</strong> です。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/localeq/i18n.qml" line="167"/>
|
||||
|
@ -137,7 +137,7 @@
|
||||
<message>
|
||||
<location filename="../src/libcalamares/JobExample.cpp" line="43"/>
|
||||
<source>Programmed job failure was explicitly requested.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Programmerat jobbfel begärdes uttryckligen.</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -222,7 +222,7 @@
|
||||
<message>
|
||||
<location filename="../src/libcalamaresui/viewpages/QmlViewStep.cpp" line="277"/>
|
||||
<source>Loading failed.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Laddning misslyckades.</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -716,7 +716,7 @@ Alla ändringar kommer att gå förlorade.</translation>
|
||||
<message>
|
||||
<location filename="../src/modules/locale/Config.cpp" line="333"/>
|
||||
<source>Set timezone to %1/%2.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Sätt tidszon till %1/%2.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/locale/Config.cpp" line="348"/>
|
||||
@ -776,22 +776,22 @@ Alla ändringar kommer att gå förlorade.</translation>
|
||||
<message>
|
||||
<location filename="../src/modules/welcome/Config.cpp" line="245"/>
|
||||
<source><h1>Welcome to the Calamares setup program for %1</h1></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><h1>Välkommen till Calamares installationsprogram för %1</h1></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/welcome/Config.cpp" line="246"/>
|
||||
<source><h1>Welcome to %1 setup</h1></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><h1>Välkommen till %1 installation</h1></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/welcome/Config.cpp" line="251"/>
|
||||
<source><h1>Welcome to the Calamares installer for %1</h1></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><h1>Välkommen till Calamares installationsprogram för %1</h1></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/welcome/Config.cpp" line="252"/>
|
||||
<source><h1>Welcome to the %1 installer</h1></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><h1>Välkommen till %1-installeraren</h1></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="125"/>
|
||||
@ -801,7 +801,7 @@ Alla ändringar kommer att gå förlorade.</translation>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="131"/>
|
||||
<source>'%1' is not allowed as username.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>'%1' är inte tillåtet som användarnamn.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="141"/>
|
||||
@ -826,7 +826,7 @@ Alla ändringar kommer att gå förlorade.</translation>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="201"/>
|
||||
<source>'%1' is not allowed as hostname.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>'%1' är inte tillåtet som värdnamn.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/Config.cpp" line="211"/>
|
||||
@ -839,7 +839,7 @@ Alla ändringar kommer att gå förlorade.</translation>
|
||||
<message>
|
||||
<location filename="../src/modules/contextualprocess/ContextualProcessJob.cpp" line="128"/>
|
||||
<source>Contextual Processes Job</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Kontextuellt processjobb</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -1476,7 +1476,7 @@ Alla ändringar kommer att gå förlorade.</translation>
|
||||
<location filename="../src/modules/oemid/IDJob.cpp" line="59"/>
|
||||
<location filename="../src/modules/oemid/IDJob.cpp" line="67"/>
|
||||
<source>OEM Batch Identifier</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>OEM-batchidentifierare</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/oemid/IDJob.cpp" line="48"/>
|
||||
@ -1795,7 +1795,10 @@ Alla ändringar kommer att gå förlorade.</translation>
|
||||
<source>Please select your preferred location on the map so the installer can suggest the locale
|
||||
and timezone settings for you. You can fine-tune the suggested settings below. Search the map by dragging
|
||||
to move and using the +/- buttons to zoom in/out or use mouse scrolling for zooming.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Snälla välj din föredragna plats på kartan så installationsprogrammet kan föreslå nationella inställningar
|
||||
och tidszons inställningar åt dig. Du kan finjustera de föreslagna inställningarna nedan.
|
||||
Sök på kartan genom att dra
|
||||
för att flytta och använd +/- knapparna för att zooma in/ut eller så använder du musens scrollhjul för att zooma.</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -1910,12 +1913,12 @@ Alla ändringar kommer att gå förlorade.</translation>
|
||||
<message>
|
||||
<location filename="../src/modules/oemid/OEMPage.ui" line="28"/>
|
||||
<source>Ba&tch:</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Gr&upp:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/oemid/OEMPage.ui" line="38"/>
|
||||
<source><html><head/><body><p>Enter a batch-identifier here. This will be stored in the target system.</p></body></html></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><html><head/><body><p>Ange en batch-identifierare här. Den kommer lagras på målsystemet.</p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/oemid/OEMPage.ui" line="48"/>
|
||||
@ -1933,7 +1936,7 @@ Alla ändringar kommer att gå förlorade.</translation>
|
||||
<message>
|
||||
<location filename="../src/modules/oemid/OEMViewStep.cpp" line="126"/>
|
||||
<source>Set the OEM Batch Identifier to <code>%1</code>.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Sätt OEM-batchidentifierare till <code>%1</code>.</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -1946,7 +1949,7 @@ Alla ändringar kommer att gå förlorade.</translation>
|
||||
<message>
|
||||
<location filename="../src/modules/localeq/Offline.qml" line="77"/>
|
||||
<source>To be able to select a timezone, make sure you are connected to the internet. Restart the installer after connecting. You can fine-tune Language and Locale settings below.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>För att kunna välja en tidszon, se till att du är ansluten till internet. Starta om installationsprogrammet efter anslutningen. Du kan finjustera språk och nationella inställningar nedan.</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -1969,7 +1972,7 @@ Alla ändringar kommer att gå förlorade.</translation>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="157"/>
|
||||
<source>Memory allocation error when setting '%1'</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Minnesallokerings fel då '%1' skulle ställas in</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="162"/>
|
||||
@ -2144,7 +2147,7 @@ Alla ändringar kommer att gå förlorade.</translation>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="275"/>
|
||||
<source>Bad integer value of setting - %1</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Dåligt heltals värde på inställning - %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/users/CheckPWQuality.cpp" line="280"/>
|
||||
@ -2851,7 +2854,8 @@ Utdata:
|
||||
<location filename="../src/modules/welcomeq/Recommended.qml" line="49"/>
|
||||
<source><p>This computer does not satisfy some of the recommended requirements for setting up %1.<br/>
|
||||
Setup can continue, but some features might be disabled.</p></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><p>Denna dator uppfyller inte alla rekommenderade krav för att installera %1.
|
||||
<br/>Installationen kan fortsätta, men alla alternativ och funktioner kanske inte kan användas.</p></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -2962,13 +2966,15 @@ Utdata:
|
||||
<location filename="../src/modules/welcomeq/Requirements.qml" line="47"/>
|
||||
<source><p>This computer does not satisfy the minimum requirements for installing %1.<br/>
|
||||
Installation cannot continue.</p></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><p>Denna dator uppfyller inte minimikraven för att installera %1.<br/>
|
||||
Installationen kan inte fortsätta.</p></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/welcomeq/Requirements.qml" line="49"/>
|
||||
<source><p>This computer does not satisfy some of the recommended requirements for setting up %1.<br/>
|
||||
Setup can continue, but some features might be disabled.</p></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><p>Denna dator uppfyller inte alla rekommenderade krav för att installera %1.
|
||||
<br/>Installationen kan fortsätta, men alla alternativ och funktioner kanske inte kan användas.</p></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -3411,17 +3417,17 @@ Utdata:
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/TrackingJobs.cpp" line="46"/>
|
||||
<source>Installation feedback</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Installationsåterkoppling</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/TrackingJobs.cpp" line="58"/>
|
||||
<source>Sending installation feedback.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Skickar installationsåterkoppling</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/TrackingJobs.cpp" line="75"/>
|
||||
<source>Internal error in install-tracking.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Internt fel i install-tracking.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/TrackingJobs.cpp" line="76"/>
|
||||
@ -3434,28 +3440,28 @@ Utdata:
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/TrackingJobs.cpp" line="143"/>
|
||||
<source>KDE user feedback</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>KDE användarfeedback </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/TrackingJobs.cpp" line="155"/>
|
||||
<source>Configuring KDE user feedback.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Konfigurerar KDE användarfeedback.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/TrackingJobs.cpp" line="177"/>
|
||||
<location filename="../src/modules/tracking/TrackingJobs.cpp" line="183"/>
|
||||
<source>Error in KDE user feedback configuration.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Fel vid konfigurering av KDE användarfeedback.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/TrackingJobs.cpp" line="178"/>
|
||||
<source>Could not configure KDE user feedback correctly, script error %1.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Kunde inte konfigurera KDE användarfeedback korrekt, script fel %1.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/TrackingJobs.cpp" line="184"/>
|
||||
<source>Could not configure KDE user feedback correctly, Calamares error %1.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Kunde inte konfigurera KDE användarfeedback korrekt, Calamares fel %1.</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -3474,7 +3480,7 @@ Utdata:
|
||||
<location filename="../src/modules/tracking/TrackingJobs.cpp" line="121"/>
|
||||
<location filename="../src/modules/tracking/TrackingJobs.cpp" line="127"/>
|
||||
<source>Error in machine feedback configuration.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Fel vid konfigurering av maskin feedback</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/TrackingJobs.cpp" line="122"/>
|
||||
@ -3502,32 +3508,32 @@ Utdata:
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/page_trackingstep.ui" line="72"/>
|
||||
<source><html><head/><body><p>Click here to send <span style=" font-weight:600;">no information at all</span> about your installation.</p></body></html></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><html><head/><body><p>Klicka här för att inte <span style=" font-weight:600;"> skicka någon information alls om din installation.</p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/page_trackingstep.ui" line="271"/>
|
||||
<source><html><head/><body><p><a href="placeholder"><span style=" text-decoration: underline; color:#2980b9;">Click here for more information about user feedback</span></a></p></body></html></source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><html><head/><body><p><a href="placeholder"><span style=" text-decoration: underline; color:#2980b9;"> Klicka här för information om användarfeedback </span></a></p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/TrackingPage.cpp" line="95"/>
|
||||
<source>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.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Spårning hjälper %1 att se hur ofta den är installerad, vilken hårdvara den är installerad på och vilka program som används. För att se vad som skickas, Klicka på hjälp ikonen vad sidan av varje område för att se vad som skickas.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/TrackingPage.cpp" line="100"/>
|
||||
<source>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.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Genom att välja detta, kommer du skicka information om din installation och hårdvara. Denna information kommer <b>enbart skickas en gång</b> efter att installationen slutförts.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/TrackingPage.cpp" line="103"/>
|
||||
<source>By selecting this you will periodically send information about your <b>machine</b> installation, hardware and applications, to %1.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Genom att välja detta, kommer du periodiskt skicka information om din <b>maskin</b>installation, hårdvara och program, till %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/tracking/TrackingPage.cpp" line="107"/>
|
||||
<source>By selecting this you will regularly send information about your <b>user</b> installation, hardware, applications and application usage patterns, to %1.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Genom att välja detta, kommer du regelbundet skicka information om din <b>användar</b>installation, hårdvara, program och dina program användningsmönster till %1.</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -3786,13 +3792,15 @@ Utdata:
|
||||
<location filename="../src/modules/localeq/i18n.qml" line="55"/>
|
||||
<source><h1>Languages</h1> </br>
|
||||
The system locale setting affects the language and character set for some command line user interface elements. The current setting is <strong>%1</strong>.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><h1>Språk</h1> </br>
|
||||
Systemspråket påverkar vilket språk och teckenuppsättning somliga kommandoradsprogram använder. Den nuvarande inställningen är <strong>%1</strong>.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/localeq/i18n.qml" line="115"/>
|
||||
<source><h1>Locales</h1> </br>
|
||||
The system locale setting affects the numbers and dates format. The current setting is <strong>%1</strong>.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation><h1>Nationella inställningar</h1> </br>
|
||||
Systems nationella inställningar påverkar nummer och datumformat. Den nuvarande inställningen är <strong>%3</strong>.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/modules/localeq/i18n.qml" line="167"/>
|
||||
|
153
lang/python.pot
153
lang/python.pot
@ -8,23 +8,23 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-07-29 11:03+0200\n"
|
||||
"POT-Creation-Date: 2020-08-09 20:56+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/grubcfg/main.py:37
|
||||
msgid "Configure GRUB."
|
||||
msgstr "Configure GRUB."
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/mount/main.py:38
|
||||
msgid "Mounting partitions."
|
||||
msgstr "Mounting partitions."
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/mount/main.py:150 src/modules/initcpiocfg/main.py:205
|
||||
#: src/modules/initcpiocfg/main.py:209
|
||||
@ -36,179 +36,172 @@ msgstr "Mounting partitions."
|
||||
#: src/modules/fstab/main.py:338 src/modules/localecfg/main.py:144
|
||||
#: src/modules/networkcfg/main.py:48
|
||||
msgid "Configuration Error"
|
||||
msgstr "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 "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/umount/main.py:40
|
||||
msgid "Unmount file systems."
|
||||
msgstr "Unmount file systems."
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/unpackfs/main.py:44
|
||||
msgid "Filling up filesystems."
|
||||
msgstr "Filling up filesystems."
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/unpackfs/main.py:257
|
||||
msgid "rsync failed with error code {}."
|
||||
msgstr "rsync failed with error code {}."
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/unpackfs/main.py:302
|
||||
msgid "Unpacking image {}/{}, file {}/{}"
|
||||
msgstr "Unpacking image {}/{}, file {}/{}"
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/unpackfs/main.py:317
|
||||
msgid "Starting to unpack {}"
|
||||
msgstr "Starting to unpack {}"
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/unpackfs/main.py:326 src/modules/unpackfs/main.py:448
|
||||
msgid "Failed to unpack image \"{}\""
|
||||
msgstr "Failed to unpack image \"{}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/unpackfs/main.py:415
|
||||
msgid "No mount point for root partition"
|
||||
msgstr "No mount point for root partition"
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/unpackfs/main.py:416
|
||||
msgid "globalstorage does not contain a \"rootMountPoint\" key, doing nothing"
|
||||
msgstr "globalstorage does not contain a \"rootMountPoint\" key, doing nothing"
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/unpackfs/main.py:421
|
||||
msgid "Bad mount point for root partition"
|
||||
msgstr "Bad mount point for root partition"
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/unpackfs/main.py:422
|
||||
msgid "rootMountPoint is \"{}\", which does not exist, doing nothing"
|
||||
msgstr "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 "Bad unsquash configuration"
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/unpackfs/main.py:439
|
||||
msgid "The filesystem for \"{}\" ({}) is not supported by your current kernel"
|
||||
msgstr "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 "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 ""
|
||||
"Failed to find unsquashfs, make sure you have the squashfs-tools package "
|
||||
"installed"
|
||||
|
||||
#: src/modules/unpackfs/main.py:463
|
||||
msgid "The destination \"{}\" in the target system is not a directory"
|
||||
msgstr "The destination \"{}\" in the target system is not a directory"
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/displaymanager/main.py:523
|
||||
msgid "Cannot write KDM configuration file"
|
||||
msgstr "Cannot write KDM configuration file"
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/displaymanager/main.py:524
|
||||
msgid "KDM config file {!s} does not exist"
|
||||
msgstr "KDM config file {!s} does not exist"
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/displaymanager/main.py:585
|
||||
msgid "Cannot write LXDM configuration file"
|
||||
msgstr "Cannot write LXDM configuration file"
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/displaymanager/main.py:586
|
||||
msgid "LXDM config file {!s} does not exist"
|
||||
msgstr "LXDM config file {!s} does not exist"
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/displaymanager/main.py:669
|
||||
msgid "Cannot write LightDM configuration file"
|
||||
msgstr "Cannot write LightDM configuration file"
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/displaymanager/main.py:670
|
||||
msgid "LightDM config file {!s} does not exist"
|
||||
msgstr "LightDM config file {!s} does not exist"
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/displaymanager/main.py:744
|
||||
msgid "Cannot configure LightDM"
|
||||
msgstr "Cannot configure LightDM"
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/displaymanager/main.py:745
|
||||
msgid "No LightDM greeter installed."
|
||||
msgstr "No LightDM greeter installed."
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/displaymanager/main.py:776
|
||||
msgid "Cannot write SLIM configuration file"
|
||||
msgstr "Cannot write SLIM configuration file"
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/displaymanager/main.py:777
|
||||
msgid "SLIM config file {!s} does not exist"
|
||||
msgstr "SLIM config file {!s} does not exist"
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/displaymanager/main.py:903
|
||||
msgid "No display managers selected for the displaymanager module."
|
||||
msgstr "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 ""
|
||||
"The displaymanagers list is empty or undefined in bothglobalstorage and "
|
||||
"displaymanager.conf."
|
||||
|
||||
#: src/modules/displaymanager/main.py:986
|
||||
msgid "Display manager configuration was incomplete"
|
||||
msgstr "Display manager configuration was incomplete"
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/initcpiocfg/main.py:37
|
||||
msgid "Configuring mkinitcpio."
|
||||
msgstr "Configuring mkinitcpio."
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/initcpiocfg/main.py:210
|
||||
#: src/modules/luksopenswaphookcfg/main.py:100
|
||||
@ -216,139 +209,131 @@ msgstr "Configuring mkinitcpio."
|
||||
#: 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 "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/rawfs/main.py:35
|
||||
msgid "Installing data."
|
||||
msgstr "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/plymouthcfg/main.py:36
|
||||
msgid "Configure Plymouth theme"
|
||||
msgstr "Configure Plymouth theme"
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/packages/main.py:59 src/modules/packages/main.py:68
|
||||
#: src/modules/packages/main.py:78
|
||||
msgid "Install packages."
|
||||
msgstr "Install packages."
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/packages/main.py:66
|
||||
#, python-format
|
||||
msgid "Processing packages (%(count)d / %(total)d)"
|
||||
msgstr "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] "Installing one package."
|
||||
msgstr[1] "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] "Removing one package."
|
||||
msgstr[1] "Removing %(num)d packages."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: src/modules/bootloader/main.py:51
|
||||
msgid "Install bootloader."
|
||||
msgstr "Install bootloader."
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/hwclock/main.py:35
|
||||
msgid "Setting hardware clock."
|
||||
msgstr "Setting hardware clock."
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/dracut/main.py:36
|
||||
msgid "Creating initramfs with dracut."
|
||||
msgstr "Creating initramfs with dracut."
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/dracut/main.py:58
|
||||
msgid "Failed to run dracut on the target"
|
||||
msgstr "Failed to run dracut on the target"
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/dracut/main.py:59
|
||||
msgid "The exit code was {}"
|
||||
msgstr "The exit code was {}"
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/initramfscfg/main.py:41
|
||||
msgid "Configuring initramfs."
|
||||
msgstr "Configuring initramfs."
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/openrcdmcryptcfg/main.py:34
|
||||
msgid "Configuring OpenRC dmcrypt service."
|
||||
msgstr "Configuring OpenRC dmcrypt service."
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/fstab/main.py:38
|
||||
msgid "Writing fstab."
|
||||
msgstr "Writing fstab."
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/dummypython/main.py:44
|
||||
msgid "Dummy python job."
|
||||
msgstr "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 "Dummy python step {}"
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/localecfg/main.py:39
|
||||
msgid "Configuring locales."
|
||||
msgstr "Configuring locales."
|
||||
msgstr ""
|
||||
|
||||
#: src/modules/networkcfg/main.py:37
|
||||
msgid "Saving network configuration."
|
||||
msgstr "Saving network configuration."
|
||||
msgstr ""
|
||||
|
Binary file not shown.
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Translators:
|
||||
# 김지현 <potatogim@potatogim.net>, 2018
|
||||
# MarongHappy <daemul72@gmail.com>, 2020
|
||||
# JungHee Lee <daemul72@gmail.com>, 2020
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
@ -14,7 +14,7 @@ msgstr ""
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-07-29 11:03+0200\n"
|
||||
"PO-Revision-Date: 2017-08-09 10:34+0000\n"
|
||||
"Last-Translator: MarongHappy <daemul72@gmail.com>, 2020\n"
|
||||
"Last-Translator: JungHee Lee <daemul72@gmail.com>, 2020\n"
|
||||
"Language-Team: Korean (https://www.transifex.com/calamares/teams/20061/ko/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
|
@ -1,6 +1,7 @@
|
||||
# === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2020 Adriaan de Groot <groot@kde.org>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# Calamares is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -15,12 +16,12 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# License-Filename: LICENSE
|
||||
#
|
||||
|
||||
#
|
||||
# libcalamares is the non-GUI part of Calamares, which includes handling
|
||||
# translations, configurations, logging, utilities, global storage, and (non-GUI) jobs.
|
||||
# translations, configurations, logging, utilities, global storage, and
|
||||
# (non-GUI) jobs.
|
||||
#
|
||||
|
||||
add_definitions( -DDLLEXPORT_PRO )
|
||||
include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} )
|
||||
@ -56,6 +57,7 @@ set( libSources
|
||||
locale/Lookup.cpp
|
||||
locale/TimeZone.cpp
|
||||
locale/TranslatableConfiguration.cpp
|
||||
locale/TranslatableString.cpp
|
||||
|
||||
# Modules
|
||||
modulesystem/InstanceKey.cpp
|
||||
@ -217,18 +219,24 @@ endforeach()
|
||||
#
|
||||
calamares_add_test(
|
||||
libcalamarestest
|
||||
SOURCES
|
||||
Tests.cpp
|
||||
)
|
||||
|
||||
calamares_add_test(
|
||||
libcalamaresutilstest
|
||||
SOURCES
|
||||
utils/Tests.cpp
|
||||
)
|
||||
|
||||
calamares_add_test(
|
||||
libcalamarestestpaths
|
||||
libcalamaresutilspathstest
|
||||
SOURCES
|
||||
utils/TestPaths.cpp
|
||||
)
|
||||
|
||||
calamares_add_test(
|
||||
geoiptest
|
||||
libcalamaresgeoiptest
|
||||
SOURCES
|
||||
geoip/GeoIPTests.cpp
|
||||
${geoip_src}
|
||||
|
@ -2,6 +2,7 @@
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac <teo@kde.org>
|
||||
* SPDX-FileCopyrightText: 2017-2018 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* Calamares is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -16,13 +17,9 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* License-Filename: LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GlobalStorage.h"
|
||||
#include "JobQueue.h"
|
||||
|
||||
#include "utils/Logger.h"
|
||||
#include "utils/Units.h"
|
||||
@ -30,12 +27,35 @@
|
||||
|
||||
#include <QFile>
|
||||
#include <QJsonDocument>
|
||||
#include <QMutexLocker>
|
||||
|
||||
using CalamaresUtils::operator""_MiB;
|
||||
|
||||
namespace Calamares
|
||||
{
|
||||
|
||||
class GlobalStorage::ReadLock : public QMutexLocker
|
||||
{
|
||||
public:
|
||||
ReadLock( const GlobalStorage* gs )
|
||||
: QMutexLocker( &gs->m_mutex )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class GlobalStorage::WriteLock : public QMutexLocker
|
||||
{
|
||||
public:
|
||||
WriteLock( GlobalStorage* gs )
|
||||
: QMutexLocker( &gs->m_mutex )
|
||||
, m_gs( gs )
|
||||
{
|
||||
}
|
||||
~WriteLock() { m_gs->changed(); }
|
||||
|
||||
GlobalStorage* m_gs;
|
||||
};
|
||||
|
||||
GlobalStorage::GlobalStorage( QObject* parent )
|
||||
: QObject( parent )
|
||||
{
|
||||
@ -45,6 +65,7 @@ GlobalStorage::GlobalStorage( QObject* parent )
|
||||
bool
|
||||
GlobalStorage::contains( const QString& key ) const
|
||||
{
|
||||
ReadLock l( this );
|
||||
return m.contains( key );
|
||||
}
|
||||
|
||||
@ -52,6 +73,7 @@ GlobalStorage::contains( const QString& key ) const
|
||||
int
|
||||
GlobalStorage::count() const
|
||||
{
|
||||
ReadLock l( this );
|
||||
return m.count();
|
||||
}
|
||||
|
||||
@ -59,14 +81,15 @@ GlobalStorage::count() const
|
||||
void
|
||||
GlobalStorage::insert( const QString& key, const QVariant& value )
|
||||
{
|
||||
WriteLock l( this );
|
||||
m.insert( key, value );
|
||||
emit changed();
|
||||
}
|
||||
|
||||
|
||||
QStringList
|
||||
GlobalStorage::keys() const
|
||||
{
|
||||
ReadLock l( this );
|
||||
return m.keys();
|
||||
}
|
||||
|
||||
@ -74,8 +97,8 @@ GlobalStorage::keys() const
|
||||
int
|
||||
GlobalStorage::remove( const QString& key )
|
||||
{
|
||||
WriteLock l( this );
|
||||
int nItems = m.remove( key );
|
||||
emit changed();
|
||||
return nItems;
|
||||
}
|
||||
|
||||
@ -83,21 +106,25 @@ GlobalStorage::remove( const QString& key )
|
||||
QVariant
|
||||
GlobalStorage::value( const QString& key ) const
|
||||
{
|
||||
ReadLock l( this );
|
||||
return m.value( key );
|
||||
}
|
||||
|
||||
void
|
||||
GlobalStorage::debugDump() const
|
||||
{
|
||||
ReadLock l( this );
|
||||
cDebug() << "GlobalStorage" << Logger::Pointer( this ) << m.count() << "items";
|
||||
for ( auto it = m.cbegin(); it != m.cend(); ++it )
|
||||
{
|
||||
cDebug() << it.key() << '\t' << it.value();
|
||||
cDebug() << Logger::SubEntry << it.key() << '\t' << it.value();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
GlobalStorage::save( const QString& filename )
|
||||
GlobalStorage::saveJson( const QString& filename ) const
|
||||
{
|
||||
ReadLock l( this );
|
||||
QFile f( filename );
|
||||
if ( !f.open( QFile::WriteOnly ) )
|
||||
{
|
||||
@ -110,7 +137,7 @@ GlobalStorage::save( const QString& filename )
|
||||
}
|
||||
|
||||
bool
|
||||
GlobalStorage::load( const QString& filename )
|
||||
GlobalStorage::loadJson( const QString& filename )
|
||||
{
|
||||
QFile f( filename );
|
||||
if ( !f.open( QFile::ReadOnly ) )
|
||||
@ -130,10 +157,14 @@ GlobalStorage::load( const QString& filename )
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteLock l( this );
|
||||
// Do **not** use method insert() here, because it would
|
||||
// recursively lock the mutex, leading to deadlock. Also,
|
||||
// that would emit changed() for each key.
|
||||
auto map = d.toVariant().toMap();
|
||||
for ( auto i = map.constBegin(); i != map.constEnd(); ++i )
|
||||
{
|
||||
insert( i.key(), *i );
|
||||
m.insert( i.key(), *i );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -141,8 +172,9 @@ GlobalStorage::load( const QString& filename )
|
||||
}
|
||||
|
||||
bool
|
||||
GlobalStorage::saveYaml( const QString& filename )
|
||||
GlobalStorage::saveYaml( const QString& filename ) const
|
||||
{
|
||||
ReadLock l( this );
|
||||
return CalamaresUtils::saveYaml( filename, m );
|
||||
}
|
||||
|
||||
@ -150,12 +182,20 @@ bool
|
||||
GlobalStorage::loadYaml( const QString& filename )
|
||||
{
|
||||
bool ok = false;
|
||||
auto gs = CalamaresUtils::loadYaml( filename, &ok );
|
||||
auto map = CalamaresUtils::loadYaml( filename, &ok );
|
||||
if ( ok )
|
||||
{
|
||||
m = gs;
|
||||
WriteLock l( this );
|
||||
// Do **not** use method insert() here, because it would
|
||||
// recursively lock the mutex, leading to deadlock. Also,
|
||||
// that would emit changed() for each key.
|
||||
for ( auto i = map.constBegin(); i != map.constEnd(); ++i )
|
||||
{
|
||||
m.insert( i.key(), *i );
|
||||
}
|
||||
return ok;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac <teo@kde.org>
|
||||
* SPDX-FileCopyrightText: 2017-2018 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* Calamares is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -16,16 +17,12 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* License-Filename: LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CALAMARES_GLOBALSTORAGE_H
|
||||
#define CALAMARES_GLOBALSTORAGE_H
|
||||
|
||||
#include "CalamaresConfig.h"
|
||||
|
||||
#include <QMutex>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QVariantMap>
|
||||
@ -33,67 +30,146 @@
|
||||
namespace Calamares
|
||||
{
|
||||
|
||||
class DebugWindow;
|
||||
|
||||
/** @brief Storage for data that passes between Calamares modules.
|
||||
*
|
||||
* The Global Storage is global to the Calamars JobQueue and
|
||||
* everything that depends on that: all of its modules use the
|
||||
* same instance of the JobQueue, and so of the Global Storage.
|
||||
*
|
||||
* GS is used to pass data between modules; there is only convention
|
||||
* about what keys are used, and individual modules should document
|
||||
* what they put in to GS or what they expect to find in it.
|
||||
*
|
||||
* GS behaves as a basic key-value store, with a QVariantMap behind
|
||||
* it. Any QVariant can be put into the storage, and the signal
|
||||
* changed() is emitted when any data is modified.
|
||||
*
|
||||
* In general, see QVariantMap (possibly after calling data()) for details.
|
||||
*
|
||||
* This class is thread-safe -- most accesses go through JobQueue, which
|
||||
* handles threading itself, but because modules load in parallel and can
|
||||
* have asynchronous tasks like GeoIP lookups, the storage itself also
|
||||
* has locking. All methods are thread-safe, use data() to make a snapshot
|
||||
* copy for use outside of the thread-safe API.
|
||||
*/
|
||||
class GlobalStorage : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/** @brief Create a GS object
|
||||
*
|
||||
* **Generally** there is only one GS object (hence, "global") which
|
||||
* is owned by the JobQueue instance (which is a singleton). However,
|
||||
* it is possible to create more GS objects.
|
||||
*/
|
||||
explicit GlobalStorage( QObject* parent = nullptr );
|
||||
|
||||
//NOTE: thread safety is guaranteed by JobQueue, which executes jobs one by one.
|
||||
// If at any time jobs become concurrent, this class must be made thread-safe.
|
||||
/** @brief Insert a key and value into the store
|
||||
*
|
||||
* The @p value is added to the store with key @p key. If @p key
|
||||
* already exists in the store, its existing value is overwritten.
|
||||
* The changed() signal is emitted regardless.
|
||||
*/
|
||||
void insert( const QString& key, const QVariant& value );
|
||||
/** @brief Removes a key and its value
|
||||
*
|
||||
* The @p key is removed from the store. If the @p key does not
|
||||
* exist, nothing happens. changed() is emitted regardless.
|
||||
*
|
||||
* @return the number of keys remaining
|
||||
*/
|
||||
int remove( const QString& key );
|
||||
|
||||
/// @brief dump keys and values to the debug log
|
||||
/** @brief dump keys and values to the debug log
|
||||
*
|
||||
* All the keys and their values are written to the debug log.
|
||||
* See save() for caveats: this can leak sensitive information.
|
||||
*/
|
||||
void debugDump() const;
|
||||
|
||||
/** @brief write as JSON to the given filename
|
||||
*
|
||||
* The file named @p filename is overwritten with a JSON representation
|
||||
* of the entire global storage (this may be structured, for instance
|
||||
* if maps or lists have been inserted).
|
||||
*
|
||||
* No tidying, sanitization, or censoring is done -- for instance,
|
||||
* the user module sets a slightly-obscured password in global storage,
|
||||
* and this JSON file will contain that password in-the-only-slightly-
|
||||
* obscured form.
|
||||
*/
|
||||
bool save( const QString& filename );
|
||||
bool saveJson( const QString& filename ) const;
|
||||
|
||||
/** @brief Adds the keys from the given JSON file
|
||||
*
|
||||
* No tidying, sanitization, or censoring is done.
|
||||
* The JSON file is read and each key is added as a value to
|
||||
* the global storage.
|
||||
* the global storage. The storage is not cleared first: existing
|
||||
* keys will remain; keys that also occur in the JSON file are overwritten.
|
||||
*/
|
||||
bool load( const QString& filename );
|
||||
bool loadJson( const QString& filename );
|
||||
|
||||
/** @brief write as YAML to the given filename
|
||||
*
|
||||
* See also save(), above.
|
||||
*/
|
||||
bool saveYaml( const QString& filename );
|
||||
bool saveYaml( const QString& filename ) const;
|
||||
|
||||
/// @brief reads settings from the given filename
|
||||
/** @brief reads settings from the given filename
|
||||
*
|
||||
* See also load(), above.
|
||||
*/
|
||||
bool loadYaml( const QString& filename );
|
||||
|
||||
/** @brief Get internal mapping as a constant object
|
||||
/** @brief Make a complete copy of the data
|
||||
*
|
||||
* Note that the VariantMap underneath may change, because
|
||||
* it's not constant in itself. Connect to the changed()
|
||||
* signal for notifications.
|
||||
* Provides a snapshot of the data at a given time.
|
||||
*/
|
||||
const QVariantMap& data() const { return m; }
|
||||
QVariantMap data() const { return m; }
|
||||
|
||||
public Q_SLOTS:
|
||||
/** @brief Does the store contain the given key?
|
||||
*
|
||||
* This can distinguish an explicitly-inserted QVariant() from
|
||||
* a no-value-exists QVariant. See value() for details.
|
||||
*/
|
||||
bool contains( const QString& key ) const;
|
||||
/** @brief The number of keys in the store
|
||||
*
|
||||
* This should be unsigned, but the underlying QMap uses signed as well.
|
||||
* Equal to keys().length(), in theory.
|
||||
*/
|
||||
int count() const;
|
||||
/** @brief The keys in the store
|
||||
*
|
||||
* This makes a copy of all the keys currently in the store, which
|
||||
* could be used for iterating over all the values in the store.
|
||||
*/
|
||||
QStringList keys() const;
|
||||
/** @brief Gets a value from the store
|
||||
*
|
||||
* If a value has been previously inserted, returns that value.
|
||||
* If @p key does not exist in the store, returns a QVariant()
|
||||
* (an invalid QVariant, which boolean-converts to false). Since
|
||||
* QVariant() van also be inserted explicitly, use contains()
|
||||
* to check for the presence of a key if you need that.
|
||||
*/
|
||||
QVariant value( const QString& key ) const;
|
||||
|
||||
signals:
|
||||
/** @brief Emitted any time the store changes
|
||||
*
|
||||
* Also emitted sometimes when the store does not change, e.g.
|
||||
* when removing a non-existent key or inserting a value that
|
||||
* is already present.
|
||||
*/
|
||||
void changed();
|
||||
|
||||
private:
|
||||
class ReadLock;
|
||||
class WriteLock;
|
||||
QVariantMap m;
|
||||
mutable QMutex m_mutex;
|
||||
};
|
||||
|
||||
} // namespace Calamares
|
||||
|
185
src/libcalamares/Tests.cpp
Normal file
185
src/libcalamares/Tests.cpp
Normal file
@ -0,0 +1,185 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2018-2020 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
*
|
||||
* 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 "GlobalStorage.h"
|
||||
|
||||
#include "utils/Logger.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QSignalSpy>
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
class TestLibCalamares : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TestLibCalamares() {}
|
||||
virtual ~TestLibCalamares() {}
|
||||
|
||||
private Q_SLOTS:
|
||||
void testGSModify();
|
||||
void testGSLoadSave();
|
||||
void testGSLoadSave2();
|
||||
void testGSLoadSaveYAMLStringList();
|
||||
};
|
||||
|
||||
void
|
||||
TestLibCalamares::testGSModify()
|
||||
{
|
||||
Calamares::GlobalStorage gs;
|
||||
QSignalSpy spy( &gs, &Calamares::GlobalStorage::changed );
|
||||
|
||||
const QString key( "derp" );
|
||||
|
||||
QCOMPARE( gs.count(), 0 );
|
||||
QVERIFY( !gs.contains( key ) );
|
||||
|
||||
const int value = 17;
|
||||
gs.insert( key, value );
|
||||
QCOMPARE( gs.count(), 1 );
|
||||
QVERIFY( gs.contains( key ) );
|
||||
QCOMPARE( gs.value( key ).type(), QVariant::Int );
|
||||
QCOMPARE( gs.value( key ).toString(), QString( "17" ) ); // It isn't a string, but does convert
|
||||
QCOMPARE( gs.value( key ).toInt(), value );
|
||||
|
||||
gs.remove( key );
|
||||
QCOMPARE( gs.count(), 0 );
|
||||
QVERIFY( !gs.contains( key ) );
|
||||
|
||||
QCOMPARE( spy.count(), 2 ); // one insert, one remove
|
||||
}
|
||||
|
||||
void
|
||||
TestLibCalamares::testGSLoadSave()
|
||||
{
|
||||
Calamares::GlobalStorage gs;
|
||||
const QString jsonfilename( "gs.test.json" );
|
||||
const QString yamlfilename( "gs.test.yaml" );
|
||||
|
||||
gs.insert( "derp", 17 );
|
||||
gs.insert( "cow", "moo" );
|
||||
|
||||
QVariantList l;
|
||||
for ( const auto& s : QStringList { "dopey", "sneezy" } )
|
||||
{
|
||||
l.append( s );
|
||||
}
|
||||
gs.insert( "dwarfs", l );
|
||||
|
||||
QCOMPARE( gs.count(), 3 );
|
||||
|
||||
QVERIFY( gs.saveJson( jsonfilename ) );
|
||||
Calamares::GlobalStorage gs2;
|
||||
QCOMPARE( gs2.count(), 0 );
|
||||
QVERIFY( gs2.loadJson( jsonfilename ) );
|
||||
QCOMPARE( gs2.count(), 3 );
|
||||
QCOMPARE( gs2.data(), gs.data() );
|
||||
|
||||
QVERIFY( gs.saveYaml( yamlfilename ) );
|
||||
Calamares::GlobalStorage gs3;
|
||||
QCOMPARE( gs3.count(), 0 );
|
||||
QVERIFY( gs3.loadYaml( jsonfilename ) );
|
||||
QCOMPARE( gs3.count(), 3 );
|
||||
QCOMPARE( gs3.data(), gs.data() );
|
||||
|
||||
// YAML can load as JSON!
|
||||
QVERIFY( gs3.loadYaml( jsonfilename ) );
|
||||
QCOMPARE( gs3.count(), 3 );
|
||||
QCOMPARE( gs3.data(), gs.data() );
|
||||
|
||||
// Failures in loading
|
||||
QVERIFY( !gs3.loadJson( yamlfilename ) );
|
||||
|
||||
Calamares::GlobalStorage gs4;
|
||||
gs4.insert( "derp", 32 );
|
||||
gs4.insert( "dorp", "Varsseveld" );
|
||||
QCOMPARE( gs4.count(), 2 );
|
||||
QVERIFY( gs4.contains( "dorp" ) );
|
||||
QCOMPARE( gs4.value( "derp" ).toInt(), 32 );
|
||||
QVERIFY( gs4.loadJson( jsonfilename ) );
|
||||
// 3 keys from the file, but one overwrite
|
||||
QCOMPARE( gs4.count(), 4 );
|
||||
QVERIFY( gs4.contains( "dorp" ) );
|
||||
QCOMPARE( gs4.value( "derp" ).toInt(), 17 ); // This one was overwritten
|
||||
}
|
||||
|
||||
void
|
||||
TestLibCalamares::testGSLoadSave2()
|
||||
{
|
||||
Logger::setupLogLevel( Logger::LOGDEBUG );
|
||||
|
||||
const QString filename( "../src/libcalamares/testdata/yaml-list.conf" );
|
||||
if ( !QFile::exists( filename ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Calamares::GlobalStorage gs1;
|
||||
const QString key( "dwarfs" );
|
||||
|
||||
QVERIFY( gs1.loadYaml( filename ) );
|
||||
QCOMPARE( gs1.count(), 3 ); // From examining the file
|
||||
QVERIFY( gs1.contains( key ) );
|
||||
cDebug() << gs1.value( key ).type() << gs1.value( key );
|
||||
QCOMPARE( gs1.value( key ).type(), QVariant::List );
|
||||
|
||||
const QString yamlfilename( "gs.test.yaml" );
|
||||
QVERIFY( gs1.saveYaml( yamlfilename ) );
|
||||
|
||||
Calamares::GlobalStorage gs2;
|
||||
QVERIFY( gs2.loadYaml( yamlfilename ) );
|
||||
QVERIFY( gs2.contains( key ) );
|
||||
QCOMPARE( gs2.value( key ).type(), QVariant::List );
|
||||
}
|
||||
|
||||
void
|
||||
TestLibCalamares::testGSLoadSaveYAMLStringList()
|
||||
{
|
||||
Calamares::GlobalStorage gs;
|
||||
const QString yamlfilename( "gs.test.yaml" );
|
||||
|
||||
gs.insert( "derp", 17 );
|
||||
gs.insert( "cow", "moo" );
|
||||
gs.insert( "dwarfs", QStringList { "happy", "dopey", "sleepy", "sneezy", "doc", "thorin", "balin" } );
|
||||
|
||||
QCOMPARE( gs.count(), 3 );
|
||||
QCOMPARE( gs.value( "dwarfs" ).toList().count(), 7 ); // There's seven dwarfs, right?
|
||||
QVERIFY( gs.value( "dwarfs" ).toStringList().contains( "thorin" ) );
|
||||
QVERIFY( !gs.value( "dwarfs" ).toStringList().contains( "gimli" ) );
|
||||
|
||||
|
||||
QVERIFY( gs.saveYaml( yamlfilename ) );
|
||||
|
||||
Calamares::GlobalStorage gs2;
|
||||
QCOMPARE( gs2.count(), 0 );
|
||||
QVERIFY( gs2.loadYaml( yamlfilename ) );
|
||||
QCOMPARE( gs2.count(), 3 );
|
||||
QEXPECT_FAIL( "", "QStringList doesn't write out nicely", Continue );
|
||||
QCOMPARE( gs2.value( "dwarfs" ).toList().count(), 7 ); // There's seven dwarfs, right?
|
||||
QCOMPARE( gs2.value( "dwarfs" ).toString(), QStringLiteral( "<QStringList>" ) ); // .. they're gone
|
||||
}
|
||||
|
||||
|
||||
QTEST_GUILESS_MAIN( TestLibCalamares )
|
||||
|
||||
#include "utils/moc-warnings.h"
|
||||
|
||||
#include "Tests.moc"
|
@ -47,7 +47,6 @@ splitTZString( const QString& tz )
|
||||
QStringList tzParts = timezoneString.split( '/', SplitSkipEmptyParts );
|
||||
if ( tzParts.size() >= 2 )
|
||||
{
|
||||
cDebug() << "GeoIP reporting" << timezoneString;
|
||||
QString region = tzParts.takeFirst();
|
||||
QString zone = tzParts.join( '/' );
|
||||
return RegionZonePair( region, zone );
|
||||
|
@ -2,7 +2,13 @@
|
||||
*
|
||||
* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* This file is derived from CLDR data from Unicode, Inc. Applicable terms:
|
||||
* SPDX-FileCopyrightText: 1991-2019 Unicode, Inc.
|
||||
* SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: CC0
|
||||
*
|
||||
* This file is derived from CLDR data from Unicode, Inc. Applicable terms
|
||||
* are listed at http://unicode.org/copyright.html , of which the most
|
||||
* important are:
|
||||
*
|
||||
* A. Unicode Copyright
|
||||
* 1. Copyright © 1991-2019 Unicode, Inc. All rights reserved.
|
||||
@ -10,6 +16,11 @@
|
||||
* Unicode Data Files ("DATA FILES") include all data files under the directories:
|
||||
* https://www.unicode.org/Public/
|
||||
* C. Terms of Use
|
||||
* 1. Certain documents and files on this website contain a legend indicating
|
||||
* that "Modification is permitted." Any person is hereby authorized,
|
||||
* without fee, to modify such documents and files to create derivative
|
||||
* works conforming to the Unicode® Standard, subject to Terms and
|
||||
* Conditions herein.
|
||||
* 2. Any person is hereby authorized, without fee, to view, use, reproduce,
|
||||
* and distribute all documents and files, subject to the Terms and
|
||||
* Conditions herein.
|
||||
|
@ -2,6 +2,7 @@
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac <teo@kde.org>
|
||||
* SPDX-FileCopyrightText: 2017-2019 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* Calamares is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -16,9 +17,6 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* License-Filename: LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Label.h"
|
||||
|
@ -2,6 +2,7 @@
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac <teo@kde.org>
|
||||
* SPDX-FileCopyrightText: 2017-2019 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* Calamares is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -16,9 +17,6 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* License-Filename: LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LOCALE_LABEL_H
|
||||
|
@ -2,6 +2,7 @@
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2019 Camilo Higuita <milo.h@aol.com>
|
||||
* SPDX-FileCopyrightText: 2019-2020 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* Calamares is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -16,9 +17,6 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* License-Filename: LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
#include "LabelModel.h"
|
||||
|
@ -2,6 +2,7 @@
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2019 Camilo Higuita <milo.h@aol.com>
|
||||
* SPDX-FileCopyrightText: 2019-2020 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* Calamares is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -16,9 +17,6 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* License-Filename: LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LOCALE_LABELMODEL_H
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* Calamares is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -15,9 +16,6 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* License-Filename: LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Lookup.h"
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* Calamares is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -15,9 +16,6 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* License-Filename: LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LOCALE_LOOKUP_H
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* Calamares is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -15,13 +16,8 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* License-Filename: LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Tests.h"
|
||||
|
||||
#include "locale/LabelModel.h"
|
||||
#include "locale/TimeZone.h"
|
||||
#include "locale/TranslatableConfiguration.h"
|
||||
@ -31,7 +27,35 @@
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
QTEST_GUILESS_MAIN( LocaleTests )
|
||||
class LocaleTests : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
LocaleTests();
|
||||
~LocaleTests() override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
|
||||
void testLanguageModelCount();
|
||||
void testTranslatableLanguages();
|
||||
void testTranslatableConfig1();
|
||||
void testTranslatableConfig2();
|
||||
void testLanguageScripts();
|
||||
|
||||
void testEsperanto();
|
||||
void testInterlingue();
|
||||
|
||||
// TimeZone testing
|
||||
void testRegions();
|
||||
void testSimpleZones();
|
||||
void testComplexZones();
|
||||
void testTZLookup();
|
||||
void testTZIterator();
|
||||
void testLocationLookup_data();
|
||||
void testLocationLookup();
|
||||
void testLocationLookup2();
|
||||
};
|
||||
|
||||
LocaleTests::LocaleTests() {}
|
||||
|
||||
@ -40,6 +64,8 @@ LocaleTests::~LocaleTests() {}
|
||||
void
|
||||
LocaleTests::initTestCase()
|
||||
{
|
||||
Logger::setupLogLevel( Logger::LOGDEBUG );
|
||||
|
||||
// Otherwise plain get() is dubious in the TranslatableConfiguration tests
|
||||
QLocale::setDefault( QLocale( QStringLiteral( "en_US" ) ) );
|
||||
QVERIFY( ( QLocale().name() == "C" ) || ( QLocale().name() == "en_US" ) );
|
||||
@ -65,10 +91,8 @@ LocaleTests::testLanguageModelCount()
|
||||
}
|
||||
|
||||
void
|
||||
LocaleTests::testEsperanto()
|
||||
LocaleTests::testLanguageScripts()
|
||||
{
|
||||
Logger::setupLogLevel( Logger::LOGDEBUG );
|
||||
|
||||
const auto* m = CalamaresUtils::Locale::availableTranslations();
|
||||
|
||||
QVERIFY( m );
|
||||
@ -89,13 +113,34 @@ LocaleTests::testEsperanto()
|
||||
QVERIFY( locale.language() == QLocale::Lithuanian ? locale.country() == QLocale::Lithuania : true );
|
||||
QVERIFY( locale.language() != QLocale::C );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LocaleTests::testEsperanto()
|
||||
{
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 5, 12, 2 )
|
||||
QCOMPARE( QLocale( "eo" ).language(), QLocale::C );
|
||||
QCOMPARE( QLocale( QLocale::Esperanto ).language(), QLocale::English );
|
||||
#else
|
||||
QCOMPARE( QLocale( "eo" ).language(), QLocale::Esperanto );
|
||||
QCOMPARE( QLocale( QLocale::Esperanto ).language(), QLocale::Esperanto ); // Probably fails on 5.12, too
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
LocaleTests::testInterlingue()
|
||||
{
|
||||
// ie / Interlingue is borked (is "ie" even the right name?)
|
||||
QCOMPARE( QLocale( "ie" ).language(), QLocale::C );
|
||||
QCOMPARE( QLocale( QLocale::Interlingue ).language(), QLocale::English );
|
||||
|
||||
// "ia" exists (post-war variant of Interlingue)
|
||||
QCOMPARE( QLocale( "ia" ).language(), QLocale::Interlingua );
|
||||
// "bork" does not exist
|
||||
QCOMPARE( QLocale( "bork" ).language(), QLocale::C );
|
||||
}
|
||||
|
||||
|
||||
static const QStringList&
|
||||
someLanguages()
|
||||
{
|
||||
@ -206,54 +251,214 @@ LocaleTests::testTranslatableConfig2()
|
||||
QCOMPARE( ts3.count(), 1 ); // The empty string
|
||||
}
|
||||
|
||||
void
|
||||
LocaleTests::testRegions()
|
||||
{
|
||||
using namespace CalamaresUtils::Locale;
|
||||
RegionsModel regions;
|
||||
|
||||
QVERIFY( regions.rowCount( QModelIndex() ) > 3 ); // Africa, America, Asia
|
||||
|
||||
QStringList names;
|
||||
for ( int i = 0; i < regions.rowCount( QModelIndex() ); ++i )
|
||||
{
|
||||
QVariant name = regions.data( regions.index( i ), RegionsModel::NameRole );
|
||||
QVERIFY( name.isValid() );
|
||||
QVERIFY( !name.toString().isEmpty() );
|
||||
names.append( name.toString() );
|
||||
}
|
||||
|
||||
QVERIFY( names.contains( "America" ) );
|
||||
QVERIFY( !names.contains( "UTC" ) );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
displayedNames( QAbstractItemModel& model, QStringList& names )
|
||||
{
|
||||
names.clear();
|
||||
for ( int i = 0; i < model.rowCount( QModelIndex() ); ++i )
|
||||
{
|
||||
QVariant name = model.data( model.index( i, 0 ), Qt::DisplayRole );
|
||||
QVERIFY( name.isValid() );
|
||||
QVERIFY( !name.toString().isEmpty() );
|
||||
names.append( name.toString() );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LocaleTests::testSimpleZones()
|
||||
{
|
||||
using namespace CalamaresUtils::Locale;
|
||||
ZonesModel zones;
|
||||
|
||||
QVERIFY( zones.rowCount( QModelIndex() ) > 24 );
|
||||
|
||||
QStringList names;
|
||||
displayedNames( zones, names );
|
||||
QVERIFY( names.contains( "Amsterdam" ) );
|
||||
if ( !names.contains( "New York" ) )
|
||||
{
|
||||
TZRegion r;
|
||||
QVERIFY( r.tr().isEmpty() );
|
||||
}
|
||||
for ( const auto& s : names )
|
||||
{
|
||||
TZZone n;
|
||||
QVERIFY( n.tr().isEmpty() );
|
||||
}
|
||||
if ( s.startsWith( 'N' ) )
|
||||
{
|
||||
TZZone r0( "xAmsterdam" );
|
||||
QCOMPARE( r0.tr(), QStringLiteral( "xAmsterdam" ) );
|
||||
TZZone r1( r0 );
|
||||
QCOMPARE( r0.tr(), QStringLiteral( "xAmsterdam" ) );
|
||||
QCOMPARE( r1.tr(), QStringLiteral( "xAmsterdam" ) );
|
||||
TZZone r2( std::move( r0 ) );
|
||||
QCOMPARE( r2.tr(), QStringLiteral( "xAmsterdam" ) );
|
||||
QCOMPARE( r0.tr(), QString() );
|
||||
cDebug() << s;
|
||||
}
|
||||
{
|
||||
TZZone r0( nullptr );
|
||||
QVERIFY( r0.tr().isEmpty() );
|
||||
TZZone r1( r0 );
|
||||
QVERIFY( r1.tr().isEmpty() );
|
||||
TZZone r2( std::move( r0 ) );
|
||||
QVERIFY( r2.tr().isEmpty() );
|
||||
}
|
||||
}
|
||||
QVERIFY( names.contains( "New York" ) );
|
||||
QVERIFY( !names.contains( "America" ) );
|
||||
QVERIFY( !names.contains( "New_York" ) );
|
||||
}
|
||||
|
||||
void
|
||||
LocaleTests::testComplexZones()
|
||||
{
|
||||
using namespace CalamaresUtils::Locale;
|
||||
ZonesModel zones;
|
||||
RegionalZonesModel europe( &zones );
|
||||
|
||||
{
|
||||
TZZone r0( "America/New_York" );
|
||||
TZZone r1( "America/New York" );
|
||||
QStringList names;
|
||||
displayedNames( zones, names );
|
||||
QVERIFY( names.contains( "New York" ) );
|
||||
QVERIFY( names.contains( "Prague" ) );
|
||||
QVERIFY( names.contains( "Abidjan" ) );
|
||||
|
||||
QCOMPARE( r0.tr(), r1.tr() );
|
||||
QCOMPARE( r0.tr(), QStringLiteral( "America/New York" ) );
|
||||
// No region set
|
||||
displayedNames( europe, names );
|
||||
QVERIFY( names.contains( "New York" ) );
|
||||
QVERIFY( names.contains( "Prague" ) );
|
||||
QVERIFY( names.contains( "Abidjan" ) );
|
||||
|
||||
// Now filter
|
||||
europe.setRegion( "Europe" );
|
||||
displayedNames( europe, names );
|
||||
QVERIFY( !names.contains( "New York" ) );
|
||||
QVERIFY( names.contains( "Prague" ) );
|
||||
QVERIFY( !names.contains( "Abidjan" ) );
|
||||
|
||||
europe.setRegion( "America" );
|
||||
displayedNames( europe, names );
|
||||
QVERIFY( names.contains( "New York" ) );
|
||||
QVERIFY( !names.contains( "Prague" ) );
|
||||
QVERIFY( !names.contains( "Abidjan" ) );
|
||||
|
||||
europe.setRegion( "Africa" );
|
||||
displayedNames( europe, names );
|
||||
QVERIFY( !names.contains( "New York" ) );
|
||||
QVERIFY( !names.contains( "Prague" ) );
|
||||
QVERIFY( names.contains( "Abidjan" ) );
|
||||
}
|
||||
|
||||
void
|
||||
LocaleTests::testTZLookup()
|
||||
{
|
||||
TZZone r( "zxc,;*_vm" );
|
||||
QVERIFY( !r.tr().isEmpty() );
|
||||
QCOMPARE( r.tr(), QStringLiteral( "zxc,;* vm" ) ); // Only _ is special
|
||||
using namespace CalamaresUtils::Locale;
|
||||
ZonesModel zones;
|
||||
|
||||
QVERIFY( zones.find( "America", "New_York" ) );
|
||||
QCOMPARE( zones.find( "America", "New_York" )->zone(), QStringLiteral( "New_York" ) );
|
||||
QCOMPARE( zones.find( "America", "New_York" )->tr(), QStringLiteral( "New York" ) );
|
||||
|
||||
QVERIFY( !zones.find( "Europe", "New_York" ) );
|
||||
QVERIFY( !zones.find( "America", "New York" ) );
|
||||
}
|
||||
|
||||
void
|
||||
LocaleTests::testTZIterator()
|
||||
{
|
||||
using namespace CalamaresUtils::Locale;
|
||||
const ZonesModel zones;
|
||||
|
||||
QVERIFY( zones.find( "Europe", "Rome" ) );
|
||||
|
||||
int count = 0;
|
||||
bool seenRome = false;
|
||||
bool seenGnome = false;
|
||||
for ( auto it = zones.begin(); it; ++it )
|
||||
{
|
||||
QVERIFY( *it );
|
||||
QVERIFY( !( *it )->zone().isEmpty() );
|
||||
seenRome |= ( *it )->zone() == QStringLiteral( "Rome" );
|
||||
seenGnome |= ( *it )->zone() == QStringLiteral( "Gnome" );
|
||||
count++;
|
||||
}
|
||||
|
||||
QVERIFY( seenRome );
|
||||
QVERIFY( !seenGnome );
|
||||
QCOMPARE( count, zones.rowCount( QModelIndex() ) );
|
||||
|
||||
QCOMPARE( zones.data( zones.index( 0 ), ZonesModel::RegionRole ).toString(), QStringLiteral( "Africa" ) );
|
||||
QCOMPARE( ( *zones.begin() )->zone(), QStringLiteral( "Abidjan" ) );
|
||||
}
|
||||
|
||||
void
|
||||
LocaleTests::testLocationLookup_data()
|
||||
{
|
||||
QTest::addColumn< double >( "latitude" );
|
||||
QTest::addColumn< double >( "longitude" );
|
||||
QTest::addColumn< QString >( "name" );
|
||||
|
||||
QTest::newRow( "London" ) << 50.0 << 0.0 << QString( "London" );
|
||||
QTest::newRow( "Tarawa E" ) << 0.0 << 179.0 << QString( "Tarawa" );
|
||||
QTest::newRow( "Tarawa W" ) << 0.0 << -179.0 << QString( "Tarawa" );
|
||||
|
||||
QTest::newRow( "Johannesburg" ) << -26.0 << 28.0 << QString( "Johannesburg" ); // South Africa
|
||||
QTest::newRow( "Maseru" ) << -29.0 << 27.0 << QString( "Maseru" ); // Lesotho
|
||||
QTest::newRow( "Windhoek" ) << -22.0 << 17.0 << QString( "Windhoek" ); // Namibia
|
||||
QTest::newRow( "Port Elisabeth" ) << -33.0 << 25.0 << QString( "Johannesburg" ); // South Africa
|
||||
QTest::newRow( "Cape Town" ) << -33.0 << 18.0 << QString( "Johannesburg" ); // South Africa
|
||||
}
|
||||
|
||||
void
|
||||
LocaleTests::testLocationLookup()
|
||||
{
|
||||
const CalamaresUtils::Locale::ZonesModel zones;
|
||||
|
||||
QFETCH( double, latitude );
|
||||
QFETCH( double, longitude );
|
||||
QFETCH( QString, name );
|
||||
|
||||
const auto* zone = zones.find( latitude, longitude );
|
||||
QVERIFY( zone );
|
||||
QCOMPARE( zone->zone(), name );
|
||||
}
|
||||
|
||||
void
|
||||
LocaleTests::testLocationLookup2()
|
||||
{
|
||||
// Official
|
||||
// ZA -2615+02800 Africa/Johannesburg
|
||||
// Spot patch
|
||||
// "ZA -3230+02259 Africa/Johannesburg\n";
|
||||
|
||||
const CalamaresUtils::Locale::ZonesModel zones;
|
||||
const auto* zone = zones.find( -26.15, 28.00 );
|
||||
QCOMPARE( zone->zone(), QString( "Johannesburg" ) );
|
||||
// The TZ data sources use minutes-and-seconds notation,
|
||||
// so "2615" is 26 degrees, 15 minutes, and 15 minutes is
|
||||
// one-quarter of a degree.
|
||||
QCOMPARE( zone->latitude(), -26.25 );
|
||||
QCOMPARE( zone->longitude(), 28.00 );
|
||||
|
||||
// Elsewhere in South Africa
|
||||
const auto* altzone = zones.find( -32.0, 22.0 );
|
||||
QCOMPARE( altzone, zone ); // same pointer
|
||||
QCOMPARE( altzone->zone(), QString( "Johannesburg" ) );
|
||||
QCOMPARE( altzone->latitude(), -26.25 );
|
||||
QCOMPARE( altzone->longitude(), 28.00 );
|
||||
|
||||
altzone = zones.find( -29.0, 27.0 );
|
||||
QCOMPARE( altzone->zone(), QString( "Maseru" ) );
|
||||
// -2928, that's -29 and 28/60 of a degree, is almost half, but we don't want
|
||||
// to fall foul of variations in double-precision
|
||||
QCOMPARE( trunc( altzone->latitude() * 1000.0 ), -29466 );
|
||||
}
|
||||
|
||||
|
||||
QTEST_GUILESS_MAIN( LocaleTests )
|
||||
|
||||
#include "utils/moc-warnings.h"
|
||||
|
||||
#include "Tests.moc"
|
||||
|
@ -1,49 +0,0 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2019 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/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* License-Filename: LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LIBCALAMARES_LOCALE_TESTS_H
|
||||
#define LIBCALAMARES_LOCALE_TESTS_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class LocaleTests : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
LocaleTests();
|
||||
~LocaleTests() override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
|
||||
void testLanguageModelCount();
|
||||
void testEsperanto();
|
||||
void testTranslatableLanguages();
|
||||
void testTranslatableConfig1();
|
||||
void testTranslatableConfig2();
|
||||
|
||||
// TimeZone testing
|
||||
void testSimpleZones();
|
||||
void testComplexZones();
|
||||
};
|
||||
|
||||
#endif
|
@ -1,6 +1,7 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* Calamares is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -15,24 +16,32 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* License-Filename: LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
#include "TimeZone.h"
|
||||
|
||||
#include "locale/TranslatableString.h"
|
||||
#include "utils/Logger.h"
|
||||
#include "utils/String.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QStringList>
|
||||
#include <QTextStream>
|
||||
|
||||
#include <cstring>
|
||||
#include <QString>
|
||||
|
||||
static const char TZ_DATA_FILE[] = "/usr/share/zoneinfo/zone.tab";
|
||||
|
||||
namespace CalamaresUtils
|
||||
{
|
||||
namespace Locale
|
||||
{
|
||||
class RegionData;
|
||||
using RegionVector = QVector< RegionData* >;
|
||||
using ZoneVector = QVector< TimeZoneData* >;
|
||||
|
||||
/** @brief Turns a string longitude or latitude notation into a double
|
||||
*
|
||||
* This handles strings like "+4230+00131" from zone.tab,
|
||||
* which is degrees-and-minutes notation, and + means north or east.
|
||||
*/
|
||||
static double
|
||||
getRightGeoLocation( QString str )
|
||||
{
|
||||
@ -62,99 +71,45 @@ getRightGeoLocation( QString str )
|
||||
}
|
||||
|
||||
|
||||
namespace CalamaresUtils
|
||||
TimeZoneData::TimeZoneData( const QString& region,
|
||||
const QString& zone,
|
||||
const QString& country,
|
||||
double latitude,
|
||||
double longitude )
|
||||
: TranslatableString( zone )
|
||||
, m_region( region )
|
||||
, m_country( country )
|
||||
, m_latitude( latitude )
|
||||
, m_longitude( longitude )
|
||||
{
|
||||
namespace Locale
|
||||
{
|
||||
|
||||
|
||||
CStringPair::CStringPair( CStringPair&& t )
|
||||
: m_human( nullptr )
|
||||
, m_key()
|
||||
{
|
||||
// My pointers are initialized to nullptr
|
||||
std::swap( m_human, t.m_human );
|
||||
std::swap( m_key, t.m_key );
|
||||
setObjectName( region + '/' + zone );
|
||||
}
|
||||
|
||||
CStringPair::CStringPair( const CStringPair& t )
|
||||
: m_human( t.m_human ? strdup( t.m_human ) : nullptr )
|
||||
, m_key( t.m_key )
|
||||
{
|
||||
}
|
||||
|
||||
/** @brief Massage an identifier into a human-readable form
|
||||
*
|
||||
* Makes a copy of @p s, caller must free() it.
|
||||
*/
|
||||
static char*
|
||||
munge( const char* s )
|
||||
{
|
||||
char* t = strdup( s );
|
||||
if ( !t )
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// replace("_"," ") in the Python script
|
||||
char* p = t;
|
||||
while ( *p )
|
||||
{
|
||||
if ( ( *p ) == '_' )
|
||||
{
|
||||
*p = ' ';
|
||||
}
|
||||
++p;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
CStringPair::CStringPair( const char* s1 )
|
||||
: m_human( s1 ? munge( s1 ) : nullptr )
|
||||
, m_key( s1 ? QString( s1 ) : QString() )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
CStringPair::~CStringPair()
|
||||
{
|
||||
free( m_human );
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
TZRegion::tr() const
|
||||
TimeZoneData::tr() const
|
||||
{
|
||||
// NOTE: context name must match what's used in zone-extractor.py
|
||||
return QObject::tr( m_human, "tz_names" );
|
||||
}
|
||||
|
||||
|
||||
class RegionData : public TranslatableString
|
||||
{
|
||||
public:
|
||||
using TranslatableString::TranslatableString;
|
||||
QString tr() const override;
|
||||
};
|
||||
|
||||
QString
|
||||
RegionData::tr() const
|
||||
{
|
||||
// NOTE: context name must match what's used in zone-extractor.py
|
||||
return QObject::tr( m_human, "tz_regions" );
|
||||
}
|
||||
|
||||
TZRegion::~TZRegion()
|
||||
static void
|
||||
loadTZData( RegionVector& regions, ZoneVector& zones, QTextStream& in )
|
||||
{
|
||||
qDeleteAll( m_zones );
|
||||
}
|
||||
|
||||
const CStringPairList&
|
||||
TZRegion::fromZoneTab()
|
||||
{
|
||||
static CStringPairList zoneTab = TZRegion::fromFile( TZ_DATA_FILE );
|
||||
return zoneTab;
|
||||
}
|
||||
|
||||
CStringPairList
|
||||
TZRegion::fromFile( const char* fileName )
|
||||
{
|
||||
CStringPairList model;
|
||||
|
||||
QFile file( fileName );
|
||||
if ( !file.open( QIODevice::ReadOnly | QIODevice::Text ) )
|
||||
{
|
||||
return model;
|
||||
}
|
||||
|
||||
TZRegion* thisRegion = nullptr;
|
||||
QTextStream in( &file );
|
||||
while ( !in.atEnd() )
|
||||
{
|
||||
QString line = in.readLine().trimmed().split( '#', SplitKeepEmptyParts ).first().trimmed();
|
||||
@ -181,18 +136,6 @@ TZRegion::fromFile( const char* fileName )
|
||||
continue;
|
||||
}
|
||||
|
||||
auto keyMatch = [®ion]( const CStringPair* r ) { return r->key() == region; };
|
||||
auto it = std::find_if( model.begin(), model.end(), keyMatch );
|
||||
if ( it != model.end() )
|
||||
{
|
||||
thisRegion = dynamic_cast< TZRegion* >( *it );
|
||||
}
|
||||
else
|
||||
{
|
||||
thisRegion = new TZRegion( region.toUtf8().data() );
|
||||
model.append( thisRegion );
|
||||
}
|
||||
|
||||
QString countryCode = list.at( 0 ).trimmed();
|
||||
if ( countryCode.size() != 2 )
|
||||
{
|
||||
@ -200,114 +143,365 @@ TZRegion::fromFile( const char* fileName )
|
||||
}
|
||||
|
||||
timezoneParts.removeFirst();
|
||||
thisRegion->m_zones.append(
|
||||
new TZZone( region, timezoneParts.join( '/' ).toUtf8().constData(), countryCode, list.at( 1 ) ) );
|
||||
QString zone = timezoneParts.join( '/' );
|
||||
if ( zone.length() < 2 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto sorter = []( const CStringPair* l, const CStringPair* r ) { return *l < *r; };
|
||||
std::sort( model.begin(), model.end(), sorter );
|
||||
for ( auto& it : model )
|
||||
{
|
||||
TZRegion* r = dynamic_cast< TZRegion* >( it );
|
||||
if ( r )
|
||||
{
|
||||
std::sort( r->m_zones.begin(), r->m_zones.end(), sorter );
|
||||
}
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
TZZone::TZZone( const QString& region, const char* zoneName, const QString& country, QString position )
|
||||
: CStringPair( zoneName )
|
||||
, m_region( region )
|
||||
, m_country( country )
|
||||
{
|
||||
QString position = list.at( 1 );
|
||||
int cooSplitPos = position.indexOf( QRegExp( "[-+]" ), 1 );
|
||||
double latitude;
|
||||
double longitude;
|
||||
if ( cooSplitPos > 0 )
|
||||
{
|
||||
m_latitude = getRightGeoLocation( position.mid( 0, cooSplitPos ) );
|
||||
m_longitude = getRightGeoLocation( position.mid( cooSplitPos ) );
|
||||
latitude = getRightGeoLocation( position.mid( 0, cooSplitPos ) );
|
||||
longitude = getRightGeoLocation( position.mid( cooSplitPos ) );
|
||||
}
|
||||
}
|
||||
|
||||
QString
|
||||
TZZone::tr() const
|
||||
else
|
||||
{
|
||||
// NOTE: context name must match what's used in zone-extractor.py
|
||||
return QObject::tr( m_human, "tz_names" );
|
||||
continue;
|
||||
}
|
||||
|
||||
// Now we have region, zone, country, lat and longitude
|
||||
const RegionData* existingRegion = nullptr;
|
||||
for ( const auto* p : regions )
|
||||
{
|
||||
if ( p->key() == region )
|
||||
{
|
||||
existingRegion = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !existingRegion )
|
||||
{
|
||||
regions.append( new RegionData( region ) );
|
||||
}
|
||||
zones.append( new TimeZoneData( region, zone, countryCode, latitude, longitude ) );
|
||||
}
|
||||
}
|
||||
|
||||
CStringListModel::CStringListModel( CStringPairList l )
|
||||
: m_list( l )
|
||||
/** @brief Extra, fake, timezones
|
||||
*
|
||||
* The timezone locations in zone.tab are not always very useful,
|
||||
* given Calamares's standard "nearest zone" algorithm: for instance,
|
||||
* in most locations physically in the country of South Africa,
|
||||
* Maseru (the capital of Lesotho, and location for timezone Africa/Maseru)
|
||||
* is closer than Johannesburg (the location for timezone Africa/Johannesburg).
|
||||
*
|
||||
* The algorithm picks the wrong place. This is for instance annoying
|
||||
* when clicking on Cape Town, you get Maseru, and to get Johannesburg
|
||||
* you need to click somewhere very carefully north of Maserru.
|
||||
*
|
||||
* These alternate zones are used to introduce "extra locations"
|
||||
* into the timezone database, in order to influence the closest-location
|
||||
* algorithm. Lines are formatted just like in zone.tab: remember the \n
|
||||
*/
|
||||
static const char altZones[] =
|
||||
/* This extra zone is north-east of Karoo National park,
|
||||
* and means that Western Cape province and a good chunk of
|
||||
* Northern- and Eastern- Cape provinces get pulled in to Johannesburg.
|
||||
* Bloemfontein is still closer to Maseru than either correct zone,
|
||||
* but this is a definite improvement.
|
||||
*/
|
||||
"ZA -3230+02259 Africa/Johannesburg\n";
|
||||
|
||||
class Private : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
RegionVector m_regions;
|
||||
ZoneVector m_zones;
|
||||
ZoneVector m_altZones; //< Extra locations for zones
|
||||
|
||||
Private()
|
||||
{
|
||||
m_regions.reserve( 12 ); // reasonable guess
|
||||
m_zones.reserve( 452 ); // wc -l /usr/share/zoneinfo/zone.tab
|
||||
|
||||
// Load the official timezones
|
||||
{
|
||||
QFile file( TZ_DATA_FILE );
|
||||
if ( file.open( QIODevice::ReadOnly | QIODevice::Text ) )
|
||||
{
|
||||
QTextStream in( &file );
|
||||
loadTZData( m_regions, m_zones, in );
|
||||
}
|
||||
}
|
||||
// Load the alternate zones (see documentation at altZones)
|
||||
{
|
||||
QTextStream in( altZones );
|
||||
loadTZData( m_regions, m_altZones, in );
|
||||
}
|
||||
|
||||
std::sort( m_regions.begin(), m_regions.end(), []( const RegionData* lhs, const RegionData* rhs ) {
|
||||
return lhs->key() < rhs->key();
|
||||
} );
|
||||
std::sort( m_zones.begin(), m_zones.end(), []( const TimeZoneData* lhs, const TimeZoneData* rhs ) {
|
||||
if ( lhs->region() == rhs->region() )
|
||||
{
|
||||
return lhs->zone() < rhs->zone();
|
||||
}
|
||||
return lhs->region() < rhs->region();
|
||||
} );
|
||||
|
||||
for ( auto* z : m_zones )
|
||||
{
|
||||
z->setParent( this );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static Private*
|
||||
privateInstance()
|
||||
{
|
||||
static Private* s_p = new Private;
|
||||
return s_p;
|
||||
}
|
||||
|
||||
RegionsModel::RegionsModel( QObject* parent )
|
||||
: QAbstractListModel( parent )
|
||||
, m_private( privateInstance() )
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
CStringListModel::setList( CalamaresUtils::Locale::CStringPairList l )
|
||||
{
|
||||
beginResetModel();
|
||||
m_list = l;
|
||||
endResetModel();
|
||||
}
|
||||
RegionsModel::~RegionsModel() {}
|
||||
|
||||
int
|
||||
CStringListModel::rowCount( const QModelIndex& ) const
|
||||
RegionsModel::rowCount( const QModelIndex& ) const
|
||||
{
|
||||
return m_list.count();
|
||||
return m_private->m_regions.count();
|
||||
}
|
||||
|
||||
QVariant
|
||||
CStringListModel::data( const QModelIndex& index, int role ) const
|
||||
RegionsModel::data( const QModelIndex& index, int role ) const
|
||||
{
|
||||
if ( ( role != Qt::DisplayRole ) && ( role != Qt::UserRole ) )
|
||||
if ( !index.isValid() || index.row() < 0 || index.row() >= m_private->m_regions.count() )
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
if ( !index.isValid() )
|
||||
const auto& region = m_private->m_regions[ index.row() ];
|
||||
if ( role == NameRole )
|
||||
{
|
||||
return region->tr();
|
||||
}
|
||||
if ( role == KeyRole )
|
||||
{
|
||||
return region->key();
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
const auto* item = m_list.at( index.row() );
|
||||
return item ? ( role == Qt::DisplayRole ? item->tr() : item->key() ) : QVariant();
|
||||
}
|
||||
|
||||
void
|
||||
CStringListModel::setCurrentIndex( int index )
|
||||
{
|
||||
if ( ( index < 0 ) || ( index >= m_list.count() ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_currentIndex = index;
|
||||
emit currentIndexChanged();
|
||||
}
|
||||
|
||||
int
|
||||
CStringListModel::currentIndex() const
|
||||
{
|
||||
return m_currentIndex;
|
||||
}
|
||||
|
||||
QHash< int, QByteArray >
|
||||
CStringListModel::roleNames() const
|
||||
RegionsModel::roleNames() const
|
||||
{
|
||||
return { { Qt::DisplayRole, "label" }, { Qt::UserRole, "key" } };
|
||||
return { { NameRole, "name" }, { KeyRole, "key" } };
|
||||
}
|
||||
|
||||
const CStringPair*
|
||||
CStringListModel::item( int index ) const
|
||||
QString
|
||||
RegionsModel::tr( const QString& region ) const
|
||||
{
|
||||
if ( ( index < 0 ) || ( index >= m_list.count() ) )
|
||||
for ( const auto* p : m_private->m_regions )
|
||||
{
|
||||
if ( p->key() == region )
|
||||
{
|
||||
return p->tr();
|
||||
}
|
||||
}
|
||||
return region;
|
||||
}
|
||||
|
||||
ZonesModel::ZonesModel( QObject* parent )
|
||||
: QAbstractListModel( parent )
|
||||
, m_private( privateInstance() )
|
||||
{
|
||||
}
|
||||
|
||||
ZonesModel::~ZonesModel() {}
|
||||
|
||||
int
|
||||
ZonesModel::rowCount( const QModelIndex& ) const
|
||||
{
|
||||
return m_private->m_zones.count();
|
||||
}
|
||||
|
||||
QVariant
|
||||
ZonesModel::data( const QModelIndex& index, int role ) const
|
||||
{
|
||||
if ( !index.isValid() || index.row() < 0 || index.row() >= m_private->m_zones.count() )
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
const auto* zone = m_private->m_zones[ index.row() ];
|
||||
switch ( role )
|
||||
{
|
||||
case NameRole:
|
||||
return zone->tr();
|
||||
case KeyRole:
|
||||
return zone->key();
|
||||
case RegionRole:
|
||||
return zone->region();
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
QHash< int, QByteArray >
|
||||
ZonesModel::roleNames() const
|
||||
{
|
||||
return { { NameRole, "name" }, { KeyRole, "key" } };
|
||||
}
|
||||
|
||||
const TimeZoneData*
|
||||
ZonesModel::find( const QString& region, const QString& zone ) const
|
||||
{
|
||||
for ( const auto* p : m_private->m_zones )
|
||||
{
|
||||
if ( p->region() == region && p->zone() == zone )
|
||||
{
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
return m_list[ index ];
|
||||
|
||||
STATICTEST const TimeZoneData*
|
||||
find( double startingDistance, const ZoneVector& zones, const std::function< double( const TimeZoneData* ) >& distanceFunc )
|
||||
{
|
||||
double smallestDistance = startingDistance;
|
||||
const TimeZoneData* closest = nullptr;
|
||||
|
||||
for ( const auto* zone : zones )
|
||||
{
|
||||
double thisDistance = distanceFunc( zone );
|
||||
if ( thisDistance < smallestDistance )
|
||||
{
|
||||
closest = zone;
|
||||
smallestDistance = thisDistance;
|
||||
}
|
||||
}
|
||||
return closest;
|
||||
}
|
||||
|
||||
const TimeZoneData*
|
||||
ZonesModel::find( const std::function< double( const TimeZoneData* ) >& distanceFunc ) const
|
||||
{
|
||||
const auto* officialZone = CalamaresUtils::Locale::find( 1000000.0, m_private->m_zones, distanceFunc );
|
||||
const auto* altZone = CalamaresUtils::Locale::find( distanceFunc( officialZone ), m_private->m_altZones, distanceFunc );
|
||||
|
||||
// If nothing was closer than the official zone already was, altZone is
|
||||
// nullptr; but if there is a spot-patch, then we need to re-find
|
||||
// the zone by name, since we want to always return pointers into
|
||||
// m_zones, not into the alternative spots.
|
||||
return altZone ? find( altZone->region(), altZone->zone() ) : officialZone;
|
||||
}
|
||||
|
||||
const TimeZoneData*
|
||||
ZonesModel::find( double latitude, double longitude ) const
|
||||
{
|
||||
/* This is a somewhat derpy way of finding "closest",
|
||||
* in that it considers one degree of separation
|
||||
* either N/S or E/W equal to any other; this obviously
|
||||
* falls apart at the poles.
|
||||
*/
|
||||
auto distance = [&]( const TimeZoneData* zone ) -> double {
|
||||
// Latitude doesn't wrap around: there is nothing north of 90
|
||||
double latitudeDifference = abs( zone->latitude() - latitude );
|
||||
|
||||
// Longitude **does** wrap around, so consider the case of -178 and 178
|
||||
// which differ by 4 degrees.
|
||||
double westerly = qMin( zone->longitude(), longitude );
|
||||
double easterly = qMax( zone->longitude(), longitude );
|
||||
double longitudeDifference = 0.0;
|
||||
if ( westerly < 0.0 && !( easterly < 0.0 ) )
|
||||
{
|
||||
// Only if they're different signs can we have wrap-around.
|
||||
longitudeDifference = qMin( abs( westerly - easterly ), abs( 360.0 + westerly - easterly ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
longitudeDifference = abs( westerly - easterly );
|
||||
}
|
||||
|
||||
return latitudeDifference + longitudeDifference;
|
||||
};
|
||||
|
||||
return find( distance );
|
||||
}
|
||||
|
||||
QObject*
|
||||
ZonesModel::lookup( double latitude, double longitude ) const
|
||||
{
|
||||
const auto* p = find( latitude, longitude );
|
||||
if ( !p )
|
||||
{
|
||||
p = find( "America", "New_York" );
|
||||
}
|
||||
if ( !p )
|
||||
{
|
||||
cWarning() << "No zone (not even New York) found, expect crashes.";
|
||||
}
|
||||
return const_cast< QObject* >( reinterpret_cast< const QObject* >( p ) );
|
||||
}
|
||||
|
||||
|
||||
ZonesModel::Iterator::operator bool() const
|
||||
{
|
||||
return 0 <= m_index && m_index < m_p->m_zones.count();
|
||||
}
|
||||
|
||||
const TimeZoneData* ZonesModel::Iterator::operator*() const
|
||||
{
|
||||
if ( *this )
|
||||
{
|
||||
return m_p->m_zones[ m_index ];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RegionalZonesModel::RegionalZonesModel( CalamaresUtils::Locale::ZonesModel* source, QObject* parent )
|
||||
: QSortFilterProxyModel( parent )
|
||||
, m_private( privateInstance() )
|
||||
{
|
||||
setSourceModel( source );
|
||||
}
|
||||
|
||||
RegionalZonesModel::~RegionalZonesModel() {}
|
||||
|
||||
void
|
||||
RegionalZonesModel::setRegion( const QString& r )
|
||||
{
|
||||
if ( r != m_region )
|
||||
{
|
||||
m_region = r;
|
||||
invalidateFilter();
|
||||
emit regionChanged( r );
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
RegionalZonesModel::filterAcceptsRow( int sourceRow, const QModelIndex& ) const
|
||||
{
|
||||
if ( m_region.isEmpty() )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( sourceRow < 0 || sourceRow >= m_private->m_zones.count() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto& zone = m_private->m_zones[ sourceRow ];
|
||||
return ( zone->m_region == m_region );
|
||||
}
|
||||
|
||||
|
||||
} // namespace Locale
|
||||
} // namespace CalamaresUtils
|
||||
|
||||
#include "utils/moc-warnings.h"
|
||||
|
||||
#include "TimeZone.moc"
|
||||
|
@ -16,192 +16,230 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file Timezone data and models to go with it
|
||||
*
|
||||
* The TimeZoneData class holds information from zone.tab, about
|
||||
* TZ names and locations (latitude and longitude) for geographic
|
||||
* lookups.
|
||||
*
|
||||
* The RegionModel lists the regions of the world (about 12) and
|
||||
* ZonesModel lists all the timezones; the RegionalZonesModel provides
|
||||
* a way to restrict the view of timezones to those of a specific region.
|
||||
*
|
||||
*/
|
||||
#ifndef LOCALE_TIMEZONE_H
|
||||
#define LOCALE_TIMEZONE_H
|
||||
|
||||
#include "DllMacro.h"
|
||||
|
||||
#include "utils/Logger.h"
|
||||
#include "locale/TranslatableString.h"
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
#include <memory>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QVariant>
|
||||
|
||||
namespace CalamaresUtils
|
||||
{
|
||||
namespace Locale
|
||||
{
|
||||
class Private;
|
||||
class RegionalZonesModel;
|
||||
class ZonesModel;
|
||||
|
||||
/** @brief A pair of strings, one human-readable, one a key
|
||||
*
|
||||
* Given an identifier-like string (e.g. "New_York"), makes
|
||||
* a human-readable version of that and keeps a copy of the
|
||||
* identifier itself.
|
||||
*
|
||||
* This explicitly uses const char* instead of just being
|
||||
* QPair<QString, QString> because there is API that needs
|
||||
* C-style strings.
|
||||
*/
|
||||
class CStringPair : public QObject
|
||||
class TimeZoneData : public QObject, TranslatableString
|
||||
{
|
||||
friend class RegionalZonesModel;
|
||||
friend class ZonesModel;
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY( QString region READ region CONSTANT )
|
||||
Q_PROPERTY( QString zone READ zone CONSTANT )
|
||||
Q_PROPERTY( QString name READ tr CONSTANT )
|
||||
Q_PROPERTY( QString countryCode READ country CONSTANT )
|
||||
|
||||
public:
|
||||
/// @brief An empty pair
|
||||
CStringPair() {}
|
||||
/// @brief Given an identifier, create the pair
|
||||
explicit CStringPair( const char* s1 );
|
||||
CStringPair( CStringPair&& t );
|
||||
CStringPair( const CStringPair& );
|
||||
virtual ~CStringPair();
|
||||
TimeZoneData( const QString& region,
|
||||
const QString& zone,
|
||||
const QString& country,
|
||||
double latitude,
|
||||
double longitude );
|
||||
TimeZoneData( const TimeZoneData& ) = delete;
|
||||
TimeZoneData( TimeZoneData&& ) = delete;
|
||||
|
||||
/// @brief Give the localized human-readable form
|
||||
virtual QString tr() const = 0;
|
||||
QString key() const { return m_key; }
|
||||
|
||||
bool operator<( const CStringPair& other ) const { return m_key < other.m_key; }
|
||||
|
||||
protected:
|
||||
char* m_human = nullptr;
|
||||
QString m_key;
|
||||
};
|
||||
|
||||
class CStringPairList : public QList< CStringPair* >
|
||||
{
|
||||
public:
|
||||
template < typename T >
|
||||
T* find( const QString& key ) const
|
||||
{
|
||||
for ( auto* p : *this )
|
||||
{
|
||||
if ( p->key() == key )
|
||||
{
|
||||
return dynamic_cast< T* >( p );
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
/** @brief Timezone regions (e.g. "America")
|
||||
*
|
||||
* A region has a key and a human-readable name, but also
|
||||
* a collection of associated timezone zones (TZZone, below).
|
||||
* This class is not usually constructed, but uses fromFile()
|
||||
* to load a complete tree structure of timezones.
|
||||
*/
|
||||
class TZRegion : public CStringPair
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
using CStringPair::CStringPair;
|
||||
virtual ~TZRegion() override;
|
||||
TZRegion( const TZRegion& ) = delete;
|
||||
QString tr() const override;
|
||||
|
||||
QString region() const { return key(); }
|
||||
|
||||
/** @brief Create list from a zone.tab-like file
|
||||
*
|
||||
* Returns a list of all the regions; each region has a list
|
||||
* of zones within that region. Dyamically, the items in the
|
||||
* returned list are TZRegions; their zones dynamically are
|
||||
* TZZones even though all those lists have type CStringPairList.
|
||||
*
|
||||
* The list owns the regions, and the regions own their own list of zones.
|
||||
* When getting rid of the list, remember to qDeleteAll() on it.
|
||||
*/
|
||||
static CStringPairList fromFile( const char* fileName );
|
||||
/// @brief Calls fromFile with the standard zone.tab name
|
||||
static const CStringPairList& fromZoneTab();
|
||||
|
||||
const CStringPairList& zones() const { return m_zones; }
|
||||
|
||||
private:
|
||||
CStringPairList m_zones;
|
||||
};
|
||||
|
||||
/** @brief Specific timezone zones (e.g. "New_York", "New York")
|
||||
*
|
||||
* A timezone zone lives in a region, and has some associated
|
||||
* data like the country (used to map likely languages) and latitude
|
||||
* and longitude information.
|
||||
*/
|
||||
class TZZone : public CStringPair
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
using CStringPair::CStringPair;
|
||||
QString tr() const override;
|
||||
|
||||
TZZone( const QString& region, const char* zoneName, const QString& country, QString position );
|
||||
|
||||
QString region() const { return m_region; }
|
||||
QString zone() const { return key(); }
|
||||
|
||||
QString country() const { return m_country; }
|
||||
double latitude() const { return m_latitude; }
|
||||
double longitude() const { return m_longitude; }
|
||||
|
||||
protected:
|
||||
private:
|
||||
QString m_region;
|
||||
QString m_country;
|
||||
double m_latitude = 0.0, m_longitude = 0.0;
|
||||
double m_latitude;
|
||||
double m_longitude;
|
||||
};
|
||||
|
||||
class CStringListModel : public QAbstractListModel
|
||||
|
||||
/** @brief The list of timezone regions
|
||||
*
|
||||
* The regions are a short list of global areas (Africa, America, India ..)
|
||||
* which contain zones.
|
||||
*/
|
||||
class DLLEXPORT RegionsModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY( int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged )
|
||||
|
||||
public:
|
||||
/// @brief Create empty model
|
||||
CStringListModel() {}
|
||||
/// @brief Create model from list (non-owning)
|
||||
CStringListModel( CStringPairList );
|
||||
enum Roles
|
||||
{
|
||||
NameRole = Qt::DisplayRole,
|
||||
KeyRole = Qt::UserRole // So that currentData() will get the key
|
||||
};
|
||||
|
||||
RegionsModel( QObject* parent = nullptr );
|
||||
virtual ~RegionsModel() override;
|
||||
|
||||
int rowCount( const QModelIndex& parent ) const override;
|
||||
|
||||
QVariant data( const QModelIndex& index, int role ) const override;
|
||||
|
||||
const CStringPair* item( int index ) const;
|
||||
QHash< int, QByteArray > roleNames() const override;
|
||||
|
||||
void setCurrentIndex( int index );
|
||||
int currentIndex() const;
|
||||
|
||||
void setList( CStringPairList );
|
||||
|
||||
inline int indexOf( const QString& key )
|
||||
{
|
||||
const auto it = std::find_if(
|
||||
m_list.constBegin(), m_list.constEnd(), [&]( const CalamaresUtils::Locale::CStringPair* item ) -> bool {
|
||||
return item->key() == key;
|
||||
} );
|
||||
|
||||
if ( it != m_list.constEnd() )
|
||||
{
|
||||
// distance() is usually a long long
|
||||
return int( std::distance( m_list.constBegin(), it ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public Q_SLOTS:
|
||||
/** @brief Provides a human-readable version of the region
|
||||
*
|
||||
* Returns @p region unchanged if there is no such region
|
||||
* or no translation for the region's name.
|
||||
*/
|
||||
QString tr( const QString& region ) const;
|
||||
|
||||
private:
|
||||
CStringPairList m_list;
|
||||
int m_currentIndex = -1;
|
||||
Private* m_private;
|
||||
};
|
||||
|
||||
class DLLEXPORT ZonesModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Roles
|
||||
{
|
||||
NameRole = Qt::DisplayRole,
|
||||
KeyRole = Qt::UserRole, // So that currentData() will get the key
|
||||
RegionRole = Qt::UserRole + 1
|
||||
};
|
||||
|
||||
ZonesModel( QObject* parent = nullptr );
|
||||
virtual ~ZonesModel() override;
|
||||
|
||||
int rowCount( const QModelIndex& parent ) const override;
|
||||
QVariant data( const QModelIndex& index, int role ) const override;
|
||||
|
||||
QHash< int, QByteArray > roleNames() const override;
|
||||
|
||||
/** @brief Iterator for the underlying list of zones
|
||||
*
|
||||
* Iterates over all the zones in the model. Operator * may return
|
||||
* a @c nullptr when the iterator is not valid. Typical usage:
|
||||
*
|
||||
* ```
|
||||
* for( auto it = model.begin(); it; ++it )
|
||||
* {
|
||||
* const auto* zonedata = *it;
|
||||
* ...
|
||||
* }
|
||||
*/
|
||||
class Iterator
|
||||
{
|
||||
friend class ZonesModel;
|
||||
Iterator( const Private* m )
|
||||
: m_index( 0 )
|
||||
, m_p( m )
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
operator bool() const;
|
||||
void operator++() { ++m_index; }
|
||||
const TimeZoneData* operator*() const;
|
||||
int index() const { return m_index; }
|
||||
|
||||
private:
|
||||
int m_index;
|
||||
const Private* m_p;
|
||||
};
|
||||
|
||||
Iterator begin() const { return Iterator( m_private ); }
|
||||
|
||||
/** @brief Look up TZ data based on an arbitrary distance function
|
||||
*
|
||||
* This is a generic method that can define distance in whatever
|
||||
* coordinate system is wanted; returns the zone with the smallest
|
||||
* distance. The @p distanceFunc must return "the distance" for
|
||||
* each zone. It would be polite to return something non-negative.
|
||||
*
|
||||
* Note: not a slot, because the parameter isn't moc-able.
|
||||
*/
|
||||
const TimeZoneData* find( const std::function< double( const TimeZoneData* ) >& distanceFunc ) const;
|
||||
|
||||
public Q_SLOTS:
|
||||
/** @brief Look up TZ data based on its name.
|
||||
*
|
||||
* Returns @c nullptr if not found.
|
||||
*/
|
||||
const TimeZoneData* find( const QString& region, const QString& zone ) const;
|
||||
|
||||
/** @brief Look up TZ data based on the location.
|
||||
*
|
||||
* Returns the nearest zone to the given lat and lon. This is a
|
||||
* convenience function for calling find(), below, with a standard
|
||||
* distance function based on the distance between the given
|
||||
* location (lat and lon) and each zone's given location.
|
||||
*/
|
||||
const TimeZoneData* find( double latitude, double longitude ) const;
|
||||
|
||||
/** @brief Look up TZ data based on the location.
|
||||
*
|
||||
* Returns the nearest zone, or New York. This is non-const for QML
|
||||
* purposes, but the object should be considered const anyway.
|
||||
*/
|
||||
QObject* lookup( double latitude, double longitude ) const;
|
||||
|
||||
private:
|
||||
Private* m_private;
|
||||
};
|
||||
|
||||
class DLLEXPORT RegionalZonesModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY( QString region READ region WRITE setRegion NOTIFY regionChanged )
|
||||
|
||||
public:
|
||||
RegionalZonesModel( ZonesModel* source, QObject* parent = nullptr );
|
||||
~RegionalZonesModel() override;
|
||||
|
||||
bool filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const override;
|
||||
|
||||
QString region() const { return m_region; }
|
||||
|
||||
public Q_SLOTS:
|
||||
void setRegion( const QString& r );
|
||||
|
||||
signals:
|
||||
void currentIndexChanged();
|
||||
void regionChanged( const QString& );
|
||||
|
||||
private:
|
||||
Private* m_private;
|
||||
QString m_region;
|
||||
};
|
||||
|
||||
|
||||
} // namespace Locale
|
||||
} // namespace CalamaresUtils
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* Calamares is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -15,9 +16,6 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* License-Filename: LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
#include "TranslatableConfiguration.h"
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* Calamares is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -15,11 +16,16 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* License-Filename: LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file Run-time translation of strings from configuration files
|
||||
*
|
||||
* The TranslatedString class provides a way of doing run-time
|
||||
* lookups of human-readable strings, from data provided in
|
||||
* the configuration files (*.conf) for Calamares. This acts
|
||||
* like "normal" translation through tr() calls, as far as the
|
||||
* user-visible part goes.
|
||||
*/
|
||||
#ifndef LOCALE_TRANSLATABLECONFIGURATION_H
|
||||
#define LOCALE_TRANSLATABLECONFIGURATION_H
|
||||
|
||||
|
89
src/libcalamares/locale/TranslatableString.cpp
Normal file
89
src/libcalamares/locale/TranslatableString.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* 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 "TranslatableString.h"
|
||||
|
||||
|
||||
/** @brief Massage an identifier into a human-readable form
|
||||
*
|
||||
* Makes a copy of @p s, caller must free() it.
|
||||
*/
|
||||
static char*
|
||||
munge( const char* s )
|
||||
{
|
||||
char* t = strdup( s );
|
||||
if ( !t )
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// replace("_"," ") in the Python script
|
||||
char* p = t;
|
||||
while ( *p )
|
||||
{
|
||||
if ( ( *p ) == '_' )
|
||||
{
|
||||
*p = ' ';
|
||||
}
|
||||
++p;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
namespace CalamaresUtils
|
||||
{
|
||||
namespace Locale
|
||||
{
|
||||
|
||||
TranslatableString::TranslatableString( TranslatableString&& t )
|
||||
: m_human( nullptr )
|
||||
, m_key()
|
||||
{
|
||||
// My pointers are initialized to nullptr
|
||||
std::swap( m_human, t.m_human );
|
||||
std::swap( m_key, t.m_key );
|
||||
}
|
||||
|
||||
TranslatableString::TranslatableString( const TranslatableString& t )
|
||||
: m_human( t.m_human ? strdup( t.m_human ) : nullptr )
|
||||
, m_key( t.m_key )
|
||||
{
|
||||
}
|
||||
|
||||
TranslatableString::TranslatableString( const char* s1 )
|
||||
: m_human( s1 ? munge( s1 ) : nullptr )
|
||||
, m_key( s1 ? QString( s1 ) : QString() )
|
||||
{
|
||||
}
|
||||
|
||||
TranslatableString::TranslatableString( const QString& s )
|
||||
: m_human( munge( s.toUtf8().constData() ) )
|
||||
, m_key( s )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
TranslatableString::~TranslatableString()
|
||||
{
|
||||
free( m_human );
|
||||
}
|
||||
|
||||
} // namespace Locale
|
||||
} // namespace CalamaresUtils
|
68
src/libcalamares/locale/TranslatableString.h
Normal file
68
src/libcalamares/locale/TranslatableString.h
Normal file
@ -0,0 +1,68 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* 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 LOCALE_TRANSLATABLESTRING_H
|
||||
#define LOCALE_TRANSLATABLESTRING_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
namespace CalamaresUtils
|
||||
{
|
||||
namespace Locale
|
||||
{
|
||||
|
||||
/** @brief A pair of strings, one human-readable, one a key
|
||||
*
|
||||
* Given an identifier-like string (e.g. "New_York"), makes
|
||||
* a human-readable version of that and keeps a copy of the
|
||||
* identifier itself.
|
||||
*
|
||||
* This explicitly uses const char* instead of just being
|
||||
* QPair<QString, QString> because the human-readable part
|
||||
* may need to be translated through tr(), and that takes a char*
|
||||
* C-style strings.
|
||||
*/
|
||||
class TranslatableString
|
||||
{
|
||||
public:
|
||||
/// @brief An empty pair
|
||||
TranslatableString() {}
|
||||
/// @brief Given an identifier, create the pair
|
||||
explicit TranslatableString( const char* s1 );
|
||||
explicit TranslatableString( const QString& s );
|
||||
TranslatableString( TranslatableString&& t );
|
||||
TranslatableString( const TranslatableString& );
|
||||
virtual ~TranslatableString();
|
||||
|
||||
/// @brief Give the localized human-readable form
|
||||
virtual QString tr() const = 0;
|
||||
QString key() const { return m_key; }
|
||||
|
||||
bool operator==( const TranslatableString& other ) const { return m_key == other.m_key; }
|
||||
bool operator<( const TranslatableString& other ) const { return m_key < other.m_key; }
|
||||
|
||||
protected:
|
||||
char* m_human = nullptr;
|
||||
QString m_key;
|
||||
};
|
||||
|
||||
} // namespace Locale
|
||||
} // namespace CalamaresUtils
|
||||
|
||||
#endif
|
@ -1,26 +1,8 @@
|
||||
/* GENERATED FILE DO NOT EDIT
|
||||
*
|
||||
* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2009 Arthur David Olson
|
||||
* SPDX-FileCopyrightText: 2019 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/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* License-Filename: LICENSE
|
||||
*
|
||||
*
|
||||
* SPDX-License-Identifier: CC0
|
||||
*
|
||||
* This file is derived from zone.tab, which has its own copyright statement:
|
||||
*
|
||||
|
@ -3,43 +3,7 @@
|
||||
# === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
# License-Filename: LICENSES/BSD2
|
||||
#
|
||||
#
|
||||
#
|
||||
# Python3 script to scrape some data out of ICU CLDR supplemental data.
|
||||
#
|
||||
### BEGIN LICENSES
|
||||
#
|
||||
# Copyright 2019 Adriaan de Groot <groot@kde.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
### END LICENSES
|
||||
|
||||
### BEGIN USAGE
|
||||
#
|
||||
"""
|
||||
Python3 script to scrape some data out of ICU CLDR supplemental data.
|
||||
@ -224,7 +188,13 @@ cpp_header_comment = """/* GENERATED FILE DO NOT EDIT
|
||||
*
|
||||
* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* This file is derived from CLDR data from Unicode, Inc. Applicable terms:
|
||||
* SPDX-FileCopyrightText: 1991-2019 Unicode, Inc.
|
||||
* SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: CC0
|
||||
*
|
||||
* This file is derived from CLDR data from Unicode, Inc. Applicable terms
|
||||
* are listed at http://unicode.org/copyright.html , of which the most
|
||||
* important are:
|
||||
*
|
||||
* A. Unicode Copyright
|
||||
* 1. Copyright © 1991-2019 Unicode, Inc. All rights reserved.
|
||||
@ -232,6 +202,11 @@ cpp_header_comment = """/* GENERATED FILE DO NOT EDIT
|
||||
* Unicode Data Files ("DATA FILES") include all data files under the directories:
|
||||
* https://www.unicode.org/Public/
|
||||
* C. Terms of Use
|
||||
* 1. Certain documents and files on this website contain a legend indicating
|
||||
* that "Modification is permitted." Any person is hereby authorized,
|
||||
* without fee, to modify such documents and files to create derivative
|
||||
* works conforming to the Unicode® Standard, subject to Terms and
|
||||
* Conditions herein.
|
||||
* 2. Any person is hereby authorized, without fee, to view, use, reproduce,
|
||||
* and distribute all documents and files, subject to the Terms and
|
||||
* Conditions herein.
|
||||
|
@ -3,42 +3,7 @@
|
||||
# === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
# License-Filename: LICENSES/BSD2
|
||||
#
|
||||
#
|
||||
# Python3 script to scrape some data out of zoneinfo/zone.tab.
|
||||
#
|
||||
### BEGIN LICENSES
|
||||
#
|
||||
# Copyright 2019 Adriaan de Groot <groot@kde.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
### END LICENSES
|
||||
|
||||
### BEGIN USAGE
|
||||
#
|
||||
"""
|
||||
Python3 script to scrape some data out of zoneinfo/zone.tab.
|
||||
@ -81,6 +46,10 @@ cpp_header_comment = """/* GENERATED FILE DO NOT EDIT
|
||||
*
|
||||
* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2009 Arthur David Olson
|
||||
* SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: CC0
|
||||
*
|
||||
* This file is derived from zone.tab, which has its own copyright statement:
|
||||
*
|
||||
* This file is in the public domain, so clarified as of
|
||||
|
@ -74,5 +74,17 @@ prettyNameForFileSystemType( FileSystem::Type t )
|
||||
}
|
||||
}
|
||||
|
||||
QString
|
||||
untranslatedFS( FileSystem::Type t )
|
||||
{
|
||||
switch ( t )
|
||||
{
|
||||
case FileSystem::Type::ReiserFS:
|
||||
return QStringLiteral( "reiserfs" );
|
||||
default:
|
||||
return FileSystem::nameForType( t, { QStringLiteral( "C" ) } );
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Partition
|
||||
} // namespace CalamaresUtils
|
||||
|
@ -3,6 +3,7 @@
|
||||
* SPDX-FileCopyrightText: 2014 Aurélien Gâteau <agateau@kde.org>
|
||||
* SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac <teo@kde.org>
|
||||
* SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* Calamares is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -17,9 +18,6 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* License-Filename: LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -30,20 +28,40 @@
|
||||
#ifndef PARTITION_FILESYSTEM_H
|
||||
#define PARTITION_FILESYSTEM_H
|
||||
|
||||
#include "DllMacro.h"
|
||||
|
||||
#include <kpmcore/fs/filesystem.h>
|
||||
|
||||
namespace CalamaresUtils
|
||||
{
|
||||
namespace Partition
|
||||
{
|
||||
QString prettyNameForFileSystemType( FileSystem::Type t );
|
||||
QString DLLEXPORT prettyNameForFileSystemType( FileSystem::Type t );
|
||||
|
||||
/** @brief Returns a machine-readable identifier for the filesystem type
|
||||
*
|
||||
* This identifier is used in filesystem manipulation --
|
||||
* e.g. when mounting the filesystem, or in /etc/fstab. It
|
||||
* is almost always just what KPMCore says it is, with
|
||||
* the following exceptions:
|
||||
* - reiserfs is called "reiser" by KPMCore, "reiserfs" by Calamares
|
||||
*/
|
||||
QString DLLEXPORT untranslatedFS( FileSystem::Type t );
|
||||
|
||||
/** @brief Returns the machine-readable identifier for the given @p fs
|
||||
*
|
||||
* See notes for untranslatedFS(), above.
|
||||
*/
|
||||
static inline QString
|
||||
untranslatedFS( FileSystem& fs )
|
||||
{
|
||||
return fs.name( { QStringLiteral( "C" ) } );
|
||||
return untranslatedFS( fs.type() );
|
||||
}
|
||||
|
||||
/** @brief Returns a machine-readable identifier for the given @p fs
|
||||
*
|
||||
* Returns an empty string is the @p fs is not valid (e.g. nullptr).
|
||||
*/
|
||||
static inline QString
|
||||
untranslatedFS( FileSystem* fs )
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* Calamares is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -15,14 +16,14 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* License-Filename: LICENSE
|
||||
*
|
||||
*/
|
||||
|
||||
#include "utils/Logger.h"
|
||||
|
||||
#include "FileSystem.h"
|
||||
|
||||
#include <kpmcore/core/partitiontable.h>
|
||||
#include <kpmcore/fs/filesystem.h>
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
@ -36,6 +37,7 @@ private Q_SLOTS:
|
||||
void initTestCase();
|
||||
|
||||
void testFlagNames();
|
||||
void testFSNames();
|
||||
};
|
||||
|
||||
KPMTests::KPMTests() {}
|
||||
@ -51,12 +53,13 @@ KPMTests::initTestCase()
|
||||
void
|
||||
KPMTests::testFlagNames()
|
||||
{
|
||||
cDebug() << "Partition flags according to KPMCore:";
|
||||
int f = 1;
|
||||
QStringList names;
|
||||
QString s;
|
||||
while ( !( s = PartitionTable::flagName( static_cast< PartitionTable::Flag >( f ) ) ).isEmpty() )
|
||||
{
|
||||
cDebug() << f << s;
|
||||
cDebug() << Logger::SubEntry << f << s;
|
||||
names.append( s );
|
||||
|
||||
f <<= 1;
|
||||
@ -78,6 +81,53 @@ KPMTests::testFlagNames()
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
KPMTests::testFSNames()
|
||||
{
|
||||
cDebug() << "FileSystem names according to KPMCore:";
|
||||
|
||||
// This uses KPMCore directly, rather than Calamares partition/FileSystem.h
|
||||
// which doesn't wrap nameForType() -- it just provides more meaningful
|
||||
// names for FS naming on FileSystem objects.
|
||||
QStringList fsNames;
|
||||
const auto fstypes = FileSystem::types();
|
||||
fsNames.reserve( fstypes.count() );
|
||||
for ( const auto t : fstypes )
|
||||
{
|
||||
QString s = FileSystem::nameForType( t, { "C" } ); // Untranslated
|
||||
cDebug() << Logger::SubEntry << s;
|
||||
fsNames.append( s );
|
||||
}
|
||||
|
||||
QVERIFY( fsNames.contains( "ext2" ) );
|
||||
QVERIFY( fsNames.contains( "ext4" ) );
|
||||
QVERIFY( fsNames.contains( "reiser" ) );
|
||||
|
||||
QStringList calaFSNames;
|
||||
calaFSNames.reserve( fstypes.count() );
|
||||
for ( const auto t : fstypes )
|
||||
{
|
||||
QString s = CalamaresUtils::Partition::untranslatedFS( t );
|
||||
calaFSNames.append( s );
|
||||
}
|
||||
|
||||
QVERIFY( calaFSNames.contains( "ext2" ) );
|
||||
QVERIFY( calaFSNames.contains( "ext4" ) );
|
||||
QVERIFY( !calaFSNames.contains( "reiser" ) );
|
||||
QVERIFY( calaFSNames.contains( "reiserfs" ) ); // whole point of Cala's own implementation
|
||||
|
||||
// Lists are the same except for .. the exceptions
|
||||
QStringList exceptionalNames { "reiser", "reiserfs" };
|
||||
for ( const auto& s : fsNames )
|
||||
{
|
||||
QVERIFY( exceptionalNames.contains( s ) || calaFSNames.contains( s ) );
|
||||
}
|
||||
for ( const auto& s : calaFSNames )
|
||||
{
|
||||
QVERIFY( exceptionalNames.contains( s ) || fsNames.contains( s ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QTEST_GUILESS_MAIN( KPMTests )
|
||||
|
||||
|
8
src/libcalamares/testdata/yaml-list.conf
vendored
Normal file
8
src/libcalamares/testdata/yaml-list.conf
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# YAML dump
|
||||
---
|
||||
"cow": "moo"
|
||||
"derp": 17
|
||||
"dwarfs":
|
||||
- "sleepy"
|
||||
- "sneezy"
|
||||
- "doc"
|
@ -148,6 +148,7 @@ LibCalamaresTests::recursiveCompareMap( const QVariantMap& a, const QVariantMap&
|
||||
void
|
||||
LibCalamaresTests::testLoadSaveYamlExtended()
|
||||
{
|
||||
Logger::setupLogLevel( Logger::LOGDEBUG );
|
||||
bool loaded_ok;
|
||||
for ( const auto& confname : findConf( QDir( "../src" ) ) )
|
||||
{
|
||||
|
@ -4,13 +4,17 @@ $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 }
|
||||
displaymanagers:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
enum: [slim, sddm, lightdm, gdm, mdm, lxdm, kdm]
|
||||
minItems: 1 # Must be non-empty, if present at all
|
||||
defaultDesktopEnvironment:
|
||||
type: object
|
||||
properties:
|
||||
executable: { type: string }
|
||||
desktopFile: { type: string }
|
||||
required: [ executable, desktopFile ]
|
||||
basicSetup: { type: boolean, default: false }
|
||||
sysconfigSetup: { type: boolean, default: false }
|
||||
|
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-06-18 15:42+0200\n"
|
||||
"POT-Creation-Date: 2020-08-09 20:56+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"
|
||||
|
@ -17,6 +17,11 @@
|
||||
# already existed. If set to false, edits the existing file instead.
|
||||
overwrite: false
|
||||
|
||||
# If set to true, prefer to write files in /etc/default/grub.d/
|
||||
# rather than the single file /etc/default/grub. If this is set,
|
||||
# Calamares will write /etc/default/grub.d/00Calamares instead.
|
||||
prefer_grub_d: false
|
||||
|
||||
# If set to true, an **existing** setting for GRUB_DISTRIBUTOR is
|
||||
# kept, not updated to the *bootloaderEntryName* from the branding file.
|
||||
# Use this if the GRUB_DISTRIBUTOR setting in the file is "smart" in
|
||||
|
@ -4,12 +4,16 @@ $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 }
|
||||
overwrite: { type: boolean, default: false }
|
||||
keepDistributor: { type: boolean, default: false }
|
||||
prefer_grub_d: { type: boolean, default: false }
|
||||
defaults:
|
||||
type: object
|
||||
additionalProperties: true # Other fields are acceptable
|
||||
properties:
|
||||
GRUB_TIMEOUT: { type: integer }
|
||||
GRUB_DEFAULT: { type: string }
|
||||
GRUB_DISABLE_SUBMENU: { type: boolean, default: true }
|
||||
GRUB_TERMINAL_OUTPUT: { type: string }
|
||||
GRUB_DISABLE_RECOVERY: { type: boolean, default: true }
|
||||
required: [ GRUB_TIMEOUT, GRUB_DEFAULT, GRUB_TERMINAL_OUTPUT ]
|
||||
|
@ -37,6 +37,33 @@ def pretty_name():
|
||||
return _("Configure GRUB.")
|
||||
|
||||
|
||||
def get_grub_config_path(root_mount_point):
|
||||
"""
|
||||
Figures out where to put the grub config files. Returns
|
||||
a the full path of a file inside that
|
||||
directory, as "the config file".
|
||||
|
||||
Returns a path into @p root_mount_point.
|
||||
"""
|
||||
default_dir = os.path.join(root_mount_point, "etc/default")
|
||||
default_config_file = "grub"
|
||||
|
||||
if "prefer_grub_d" in libcalamares.job.configuration and libcalamares.job.configuration["prefer_grub_d"]:
|
||||
possible_dir = os.path.join(root_mount_point, "etc/default/grub.d")
|
||||
if os.path.exists(possible_dir) and os.path.isdir(possible_dir):
|
||||
default_dir = possible_dir
|
||||
default_config_file = "00calamares"
|
||||
|
||||
if not os.path.exists(default_dir):
|
||||
try:
|
||||
os.mkdir(default_dir)
|
||||
except:
|
||||
libcalamares.utils.debug("Failed to create '%r'" % default_dir)
|
||||
raise
|
||||
|
||||
return os.path.join(default_dir, default_config_file)
|
||||
|
||||
|
||||
def modify_grub_default(partitions, root_mount_point, distributor):
|
||||
"""
|
||||
Configures '/etc/default/grub' for hibernation and plymouth.
|
||||
@ -54,8 +81,7 @@ def modify_grub_default(partitions, root_mount_point, distributor):
|
||||
is always updated to set this value.
|
||||
:return:
|
||||
"""
|
||||
default_dir = os.path.join(root_mount_point, "etc/default")
|
||||
default_grub = os.path.join(default_dir, "grub")
|
||||
default_grub = get_grub_config_path(root_mount_point)
|
||||
distributor_replace = distributor.replace("'", "'\\''")
|
||||
dracut_bin = libcalamares.utils.target_env_call(
|
||||
["sh", "-c", "which dracut"]
|
||||
@ -142,9 +168,6 @@ def modify_grub_default(partitions, root_mount_point, distributor):
|
||||
|
||||
distributor_line = "GRUB_DISTRIBUTOR='{!s}'".format(distributor_replace)
|
||||
|
||||
if not os.path.exists(default_dir):
|
||||
os.mkdir(default_dir)
|
||||
|
||||
have_kernel_cmd = False
|
||||
have_distributor_line = False
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
bogus: true
|
||||
firmwareType: bios
|
||||
bootLoader: grub
|
||||
rootMountPoint: /tmp/calamares
|
||||
rootMountPoint: /tmp/calamares/grubcfg-test-2
|
||||
|
||||
branding:
|
||||
bootloaderEntryName: generic
|
||||
|
10
src/modules/grubcfg/tests/3.global
Normal file
10
src/modules/grubcfg/tests/3.global
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
bogus: true
|
||||
firmwareType: bios
|
||||
bootLoader: grub
|
||||
rootMountPoint: /tmp/calamares/grubcfg-test-3
|
||||
|
||||
branding:
|
||||
bootloaderEntryName: generic
|
||||
partitions: []
|
||||
|
10
src/modules/grubcfg/tests/3.job
Normal file
10
src/modules/grubcfg/tests/3.job
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
overwrite: true
|
||||
prefer_grub_d: true # But it doesn't exist
|
||||
keepDistributor: false
|
||||
defaults:
|
||||
GRUB_TIMEOUT: 5
|
||||
GRUB_DEFAULT: "saved"
|
||||
GRUB_DISABLE_SUBMENU: true
|
||||
GRUB_TERMINAL_OUTPUT: "console"
|
||||
GRUB_DISABLE_RECOVERY: true
|
10
src/modules/grubcfg/tests/4.global
Normal file
10
src/modules/grubcfg/tests/4.global
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
bogus: true
|
||||
firmwareType: bios
|
||||
bootLoader: grub
|
||||
rootMountPoint: /tmp/calamares/grubcfg-test-4
|
||||
|
||||
branding:
|
||||
bootloaderEntryName: generic
|
||||
partitions: []
|
||||
|
10
src/modules/grubcfg/tests/4.job
Normal file
10
src/modules/grubcfg/tests/4.job
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
overwrite: true
|
||||
prefer_grub_d: true
|
||||
keepDistributor: false
|
||||
defaults:
|
||||
GRUB_TIMEOUT: 5
|
||||
GRUB_DEFAULT: "saved"
|
||||
GRUB_DISABLE_SUBMENU: true
|
||||
GRUB_TERMINAL_OUTPUT: "console"
|
||||
GRUB_DISABLE_RECOVERY: true
|
@ -2,11 +2,15 @@
|
||||
# - 2.global specifies /tmp/calamares as the rootMountPath,
|
||||
# so we end up editing files there. Create the directory
|
||||
# beforehand, so the test doesn't blow up.
|
||||
set(_grub_root /tmp/calamares/etc/default)
|
||||
set(_grub_file ${_grub_root}/bogus)
|
||||
|
||||
add_test(
|
||||
NAME make-grubcfg-dirs
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${_grub_root}
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory
|
||||
/tmp/calamares/grubcfg-test-2/etc/default
|
||||
/tmp/calamares/grubcfg-test-3/etc/default
|
||||
/tmp/calamares/grubcfg-test-4/etc/default/grub.d
|
||||
)
|
||||
set_tests_properties(load-grubcfg-2 PROPERTIES DEPENDS make-grubcfg-dirs)
|
||||
set_tests_properties(load-grubcfg-3 PROPERTIES DEPENDS make-grubcfg-dirs)
|
||||
set_tests_properties(load-grubcfg-4 PROPERTIES DEPENDS make-grubcfg-dirs)
|
||||
|
||||
|
@ -91,6 +91,17 @@ hostCPUmatch( const QString& s )
|
||||
return QString();
|
||||
}
|
||||
|
||||
static QString
|
||||
hostCPUmatchARM( const QString& s )
|
||||
{
|
||||
// Both Rock64 and Raspberry pi mention 0x41
|
||||
if ( s.contains( ": 0x41" ) )
|
||||
{
|
||||
return QStringLiteral( "ARM" );
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
#if defined( Q_OS_FREEBSD )
|
||||
QString
|
||||
hostCPU_FreeBSD()
|
||||
@ -127,6 +138,10 @@ hostCPU_Linux()
|
||||
{
|
||||
return hostCPUmatch( line );
|
||||
}
|
||||
if ( line.startsWith( "CPU implementer" ) )
|
||||
{
|
||||
return hostCPUmatchARM( line );
|
||||
}
|
||||
}
|
||||
}
|
||||
return QString(); // Not open, or not found
|
||||
|
@ -59,7 +59,33 @@ HostInfoTests::testHostOS()
|
||||
|
||||
QCOMPARE( expect, hostOS() );
|
||||
QCOMPARE( expect, hostOSName() ); // Might be the same
|
||||
QCOMPARE( QStringLiteral( "Intel" ), hostCPU() ); // On all my developer machines
|
||||
|
||||
// This is a lousy test, too: the implementation reads /proc/cpuinfo
|
||||
// and that's the only way we could use, too, to find what the "right"
|
||||
// answer is.
|
||||
QStringList x86cpunames{ QStringLiteral( "Intel" ), QStringLiteral( "AMD" ) };
|
||||
QStringList armcpunames{ QStringLiteral( "ARM" ) };
|
||||
const QString cpu = hostCPU();
|
||||
QVERIFY( x86cpunames.contains( cpu ) || armcpunames.contains( cpu ) );
|
||||
|
||||
// Try to detect family in a different way
|
||||
QFile modalias( "/sys/devices/system/cpu/modalias" );
|
||||
if ( modalias.open( QIODevice::ReadOnly ) )
|
||||
{
|
||||
QString cpumodalias = modalias.readLine();
|
||||
if ( cpumodalias.contains( "type:x86" ) )
|
||||
{
|
||||
QVERIFY( x86cpunames.contains( cpu ) );
|
||||
}
|
||||
else if ( cpumodalias.contains( "type:aarch64" ) )
|
||||
{
|
||||
QVERIFY( armcpunames.contains( cpu ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
QCOMPARE( cpu, QString( "Unknown CPU modalias '%1'" ).arg(cpumodalias) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -36,7 +36,9 @@ calamares_add_test(
|
||||
localetest
|
||||
SOURCES
|
||||
Tests.cpp
|
||||
Config.cpp
|
||||
LocaleConfiguration.cpp
|
||||
SetTimezoneJob.cpp
|
||||
timezonewidget/TimeZoneImage.cpp
|
||||
DEFINITIONS
|
||||
SOURCE_DIR="${CMAKE_CURRENT_LIST_DIR}/images"
|
||||
|
@ -148,17 +148,50 @@ loadLocales( const QString& localeGenPath )
|
||||
return localeGenLines;
|
||||
}
|
||||
|
||||
static inline const CalamaresUtils::Locale::CStringPairList&
|
||||
timezoneData()
|
||||
static bool
|
||||
updateGSLocation( Calamares::GlobalStorage* gs, const CalamaresUtils::Locale::TimeZoneData* location )
|
||||
{
|
||||
return CalamaresUtils::Locale::TZRegion::fromZoneTab();
|
||||
const QString regionKey = QStringLiteral( "locationRegion" );
|
||||
const QString zoneKey = QStringLiteral( "locationZone" );
|
||||
|
||||
if ( !location )
|
||||
{
|
||||
if ( gs->contains( regionKey ) || gs->contains( zoneKey ) )
|
||||
{
|
||||
gs->remove( regionKey );
|
||||
gs->remove( zoneKey );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update the GS region and zone (and possibly the live timezone)
|
||||
bool locationChanged
|
||||
= ( location->region() != gs->value( regionKey ) ) || ( location->zone() != gs->value( zoneKey ) );
|
||||
|
||||
gs->insert( regionKey, location->region() );
|
||||
gs->insert( zoneKey, location->zone() );
|
||||
|
||||
return locationChanged;
|
||||
}
|
||||
|
||||
static void
|
||||
updateGSLocale( Calamares::GlobalStorage* gs, const LocaleConfiguration& locale )
|
||||
{
|
||||
auto map = locale.toMap();
|
||||
QVariantMap vm;
|
||||
for ( auto it = map.constBegin(); it != map.constEnd(); ++it )
|
||||
{
|
||||
vm.insert( it.key(), it.value() );
|
||||
}
|
||||
gs->insert( "localeConf", vm );
|
||||
}
|
||||
|
||||
Config::Config( QObject* parent )
|
||||
: QObject( parent )
|
||||
, m_regionModel( std::make_unique< CalamaresUtils::Locale::CStringListModel >( ::timezoneData() ) )
|
||||
, m_zonesModel( std::make_unique< CalamaresUtils::Locale::CStringListModel >() )
|
||||
, m_regionModel( std::make_unique< CalamaresUtils::Locale::RegionsModel >() )
|
||||
, m_zonesModel( std::make_unique< CalamaresUtils::Locale::ZonesModel >() )
|
||||
, m_regionalZonesModel( std::make_unique< CalamaresUtils::Locale::RegionalZonesModel >( m_zonesModel.get() ) )
|
||||
{
|
||||
// Slightly unusual: connect to our *own* signals. Wherever the language
|
||||
// or the location is changed, these signals are emitted, so hook up to
|
||||
@ -172,32 +205,21 @@ Config::Config( QObject* parent )
|
||||
} );
|
||||
|
||||
connect( this, &Config::currentLCCodeChanged, [&]() {
|
||||
auto* gs = Calamares::JobQueue::instance()->globalStorage();
|
||||
// Update GS localeConf (the LC_ variables)
|
||||
auto map = localeConfiguration().toMap();
|
||||
QVariantMap vm;
|
||||
for ( auto it = map.constBegin(); it != map.constEnd(); ++it )
|
||||
{
|
||||
vm.insert( it.key(), it.value() );
|
||||
}
|
||||
gs->insert( "localeConf", vm );
|
||||
updateGSLocale( Calamares::JobQueue::instance()->globalStorage(), localeConfiguration() );
|
||||
} );
|
||||
|
||||
connect( this, &Config::currentLocationChanged, [&]() {
|
||||
auto* gs = Calamares::JobQueue::instance()->globalStorage();
|
||||
const bool locationChanged
|
||||
= updateGSLocation( Calamares::JobQueue::instance()->globalStorage(), currentLocation() );
|
||||
|
||||
// Update the GS region and zone (and possibly the live timezone)
|
||||
const auto* location = currentLocation();
|
||||
bool locationChanged = ( location->region() != gs->value( "locationRegion" ) )
|
||||
|| ( location->zone() != gs->value( "locationZone" ) );
|
||||
|
||||
gs->insert( "locationRegion", location->region() );
|
||||
gs->insert( "locationZone", location->zone() );
|
||||
if ( locationChanged && m_adjustLiveTimezone )
|
||||
{
|
||||
QProcess::execute( "timedatectl", // depends on systemd
|
||||
{ "set-timezone", location->region() + '/' + location->zone() } );
|
||||
{ "set-timezone", currentTimezoneCode() } );
|
||||
}
|
||||
|
||||
emit currentTimezoneCodeChanged( currentTimezoneCode() );
|
||||
emit currentTimezoneNameChanged( currentTimezoneName() );
|
||||
} );
|
||||
|
||||
auto prettyStatusNotify = [&]() { emit prettyStatusChanged( prettyStatus() ); };
|
||||
@ -208,12 +230,6 @@ Config::Config( QObject* parent )
|
||||
|
||||
Config::~Config() {}
|
||||
|
||||
const CalamaresUtils::Locale::CStringPairList&
|
||||
Config::timezoneData() const
|
||||
{
|
||||
return ::timezoneData();
|
||||
}
|
||||
|
||||
void
|
||||
Config::setCurrentLocation()
|
||||
{
|
||||
@ -223,7 +239,8 @@ Config::setCurrentLocation()
|
||||
}
|
||||
}
|
||||
|
||||
void Config::setCurrentLocation(const QString& regionzone)
|
||||
void
|
||||
Config::setCurrentLocation( const QString& regionzone )
|
||||
{
|
||||
auto r = CalamaresUtils::GeoIP::splitTZString( regionzone );
|
||||
if ( r.isValid() )
|
||||
@ -236,8 +253,7 @@ void
|
||||
Config::setCurrentLocation( const QString& regionName, const QString& zoneName )
|
||||
{
|
||||
using namespace CalamaresUtils::Locale;
|
||||
auto* region = timezoneData().find< TZRegion >( regionName );
|
||||
auto* zone = region ? region->zones().find< TZZone >( zoneName ) : nullptr;
|
||||
auto* zone = m_zonesModel->find( regionName, zoneName );
|
||||
if ( zone )
|
||||
{
|
||||
setCurrentLocation( zone );
|
||||
@ -250,7 +266,7 @@ Config::setCurrentLocation( const QString& regionName, const QString& zoneName )
|
||||
}
|
||||
|
||||
void
|
||||
Config::setCurrentLocation( const CalamaresUtils::Locale::TZZone* location )
|
||||
Config::setCurrentLocation( const CalamaresUtils::Locale::TimeZoneData* location )
|
||||
{
|
||||
if ( location != m_currentLocation )
|
||||
{
|
||||
@ -277,6 +293,7 @@ Config::setCurrentLocation( const CalamaresUtils::Locale::TZZone* location )
|
||||
emit currentLCStatusChanged( currentLCStatus() );
|
||||
}
|
||||
emit currentLocationChanged( m_currentLocation );
|
||||
// Other signals come from the LocationChanged signal
|
||||
}
|
||||
}
|
||||
|
||||
@ -330,9 +347,32 @@ Config::setLCLocaleExplicitly( const QString& locale )
|
||||
QString
|
||||
Config::currentLocationStatus() const
|
||||
{
|
||||
return tr( "Set timezone to %1/%2." ).arg( m_currentLocation->region(), m_currentLocation->zone() );
|
||||
return tr( "Set timezone to %1/%2." )
|
||||
.arg( m_currentLocation ? m_currentLocation->region() : QString(),
|
||||
m_currentLocation ? m_currentLocation->zone() : QString() );
|
||||
}
|
||||
|
||||
QString
|
||||
Config::currentTimezoneCode() const
|
||||
{
|
||||
if ( m_currentLocation )
|
||||
{
|
||||
return m_currentLocation->region() + '/' + m_currentLocation->zone();
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString
|
||||
Config::currentTimezoneName() const
|
||||
{
|
||||
if ( m_currentLocation )
|
||||
{
|
||||
return m_regionModel->tr( m_currentLocation->region() ) + '/' + m_currentLocation->tr();
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
|
||||
static inline QString
|
||||
localeLabel( const QString& s )
|
||||
{
|
||||
@ -380,7 +420,7 @@ getAdjustLiveTimezone( const QVariantMap& configurationMap, bool& adjustLiveTime
|
||||
adjustLiveTimezone = CalamaresUtils::getBool(
|
||||
configurationMap, "adjustLiveTimezone", Calamares::Settings::instance()->doChroot() );
|
||||
#ifdef DEBUG_TIMEZONES
|
||||
if ( m_adjustLiveTimezone )
|
||||
if ( adjustLiveTimezone )
|
||||
{
|
||||
cWarning() << "Turning off live-timezone adjustments because debugging is on.";
|
||||
adjustLiveTimezone = false;
|
||||
@ -448,18 +488,20 @@ Config::setConfigurationMap( const QVariantMap& configurationMap )
|
||||
getStartingTimezone( configurationMap, m_startingTimezone );
|
||||
getGeoIP( configurationMap, m_geoip );
|
||||
|
||||
#ifndef BUILD_AS_TEST
|
||||
if ( m_geoip && m_geoip->isValid() )
|
||||
{
|
||||
connect(
|
||||
Calamares::ModuleManager::instance(), &Calamares::ModuleManager::modulesLoaded, this, &Config::startGeoIP );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Calamares::JobList
|
||||
Config::createJobs()
|
||||
{
|
||||
Calamares::JobList list;
|
||||
const CalamaresUtils::Locale::TZZone* location = currentLocation();
|
||||
const auto* location = currentLocation();
|
||||
|
||||
if ( location )
|
||||
{
|
||||
@ -470,6 +512,15 @@ Config::createJobs()
|
||||
return list;
|
||||
}
|
||||
|
||||
void
|
||||
Config::finalizeGlobalStorage() const
|
||||
{
|
||||
auto* gs = Calamares::JobQueue::instance()->globalStorage();
|
||||
updateGSLocale( gs, localeConfiguration() );
|
||||
updateGSLocation( gs, currentLocation() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Config::startGeoIP()
|
||||
{
|
||||
|
@ -37,18 +37,25 @@ class Config : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY( const QStringList& supportedLocales READ supportedLocales CONSTANT FINAL )
|
||||
Q_PROPERTY( CalamaresUtils::Locale::CStringListModel* zonesModel READ zonesModel CONSTANT FINAL )
|
||||
Q_PROPERTY( CalamaresUtils::Locale::CStringListModel* regionModel READ regionModel CONSTANT FINAL )
|
||||
Q_PROPERTY( CalamaresUtils::Locale::RegionsModel* regionModel READ regionModel CONSTANT FINAL )
|
||||
Q_PROPERTY( CalamaresUtils::Locale::ZonesModel* zonesModel READ zonesModel CONSTANT FINAL )
|
||||
Q_PROPERTY( QAbstractItemModel* regionalZonesModel READ regionalZonesModel CONSTANT FINAL )
|
||||
|
||||
Q_PROPERTY( const CalamaresUtils::Locale::TZZone* currentLocation READ currentLocation WRITE setCurrentLocation
|
||||
NOTIFY currentLocationChanged )
|
||||
Q_PROPERTY(
|
||||
CalamaresUtils::Locale::TimeZoneData* currentLocation READ currentLocation_c NOTIFY currentLocationChanged )
|
||||
|
||||
// Status are complete, human-readable, messages
|
||||
Q_PROPERTY( QString currentLocationStatus READ currentLocationStatus NOTIFY currentLanguageStatusChanged )
|
||||
Q_PROPERTY( QString currentLanguageStatus READ currentLanguageStatus NOTIFY currentLanguageStatusChanged )
|
||||
Q_PROPERTY( QString currentLCStatus READ currentLCStatus NOTIFY currentLCStatusChanged )
|
||||
// Name are shorter human-readable names
|
||||
// .. main difference is that status is a full sentence, like "Timezone is America/New York"
|
||||
// while name is just "America/New York" (and the code, below, is "America/New_York")
|
||||
Q_PROPERTY( QString currentTimezoneName READ currentTimezoneName NOTIFY currentTimezoneNameChanged )
|
||||
// Code are internal identifiers, like "en_US.UTF-8"
|
||||
Q_PROPERTY( QString currentLanguageCode READ currentLanguageCode WRITE setLanguageExplicitly NOTIFY currentLanguageCodeChanged )
|
||||
Q_PROPERTY( QString currentTimezoneCode READ currentTimezoneCode NOTIFY currentTimezoneCodeChanged )
|
||||
Q_PROPERTY( QString currentLanguageCode READ currentLanguageCode WRITE setLanguageExplicitly NOTIFY
|
||||
currentLanguageCodeChanged )
|
||||
Q_PROPERTY( QString currentLCCode READ currentLCCode WRITE setLCLocaleExplicitly NOTIFY currentLCCodeChanged )
|
||||
|
||||
// This is a long human-readable string with all three statuses
|
||||
@ -59,17 +66,9 @@ public:
|
||||
~Config();
|
||||
|
||||
void setConfigurationMap( const QVariantMap& );
|
||||
void finalizeGlobalStorage() const;
|
||||
Calamares::JobList createJobs();
|
||||
|
||||
// Underlying data for the models
|
||||
const CalamaresUtils::Locale::CStringPairList& timezoneData() const;
|
||||
|
||||
/** @brief The currently selected location (timezone)
|
||||
*
|
||||
* The location is a pointer into the date that timezoneData() returns.
|
||||
*/
|
||||
const CalamaresUtils::Locale::TZZone* currentLocation() const { return m_currentLocation; }
|
||||
|
||||
/// locale configuration (LC_* and LANG) based solely on the current location.
|
||||
LocaleConfiguration automaticLocaleConfiguration() const;
|
||||
/// locale configuration that takes explicit settings into account
|
||||
@ -85,13 +84,27 @@ public:
|
||||
/// The human-readable summary of what the module will do
|
||||
QString prettyStatus() const;
|
||||
|
||||
// A long list of locale codes (e.g. en_US.UTF-8)
|
||||
const QStringList& supportedLocales() const { return m_localeGenLines; }
|
||||
CalamaresUtils::Locale::CStringListModel* regionModel() const { return m_regionModel.get(); }
|
||||
CalamaresUtils::Locale::CStringListModel* zonesModel() const { return m_zonesModel.get(); }
|
||||
// All the regions (Africa, America, ...)
|
||||
CalamaresUtils::Locale::RegionsModel* regionModel() const { return m_regionModel.get(); }
|
||||
// All of the timezones in the world, according to zone.tab
|
||||
CalamaresUtils::Locale::ZonesModel* zonesModel() const { return m_zonesModel.get(); }
|
||||
// This model can be filtered by region
|
||||
CalamaresUtils::Locale::RegionalZonesModel* regionalZonesModel() const { return m_regionalZonesModel.get(); }
|
||||
|
||||
const CalamaresUtils::Locale::TimeZoneData* currentLocation() const { return m_currentLocation; }
|
||||
|
||||
|
||||
/// Special case, set location from starting timezone if not already set
|
||||
void setCurrentLocation();
|
||||
|
||||
private:
|
||||
CalamaresUtils::Locale::TimeZoneData* currentLocation_c() const
|
||||
{
|
||||
return const_cast< CalamaresUtils::Locale::TimeZoneData* >( m_currentLocation );
|
||||
}
|
||||
|
||||
public Q_SLOTS:
|
||||
/// Set a language by user-choice, overriding future location changes
|
||||
void setLanguageExplicitly( const QString& language );
|
||||
@ -111,38 +124,38 @@ public Q_SLOTS:
|
||||
* names a zone within that region.
|
||||
*/
|
||||
void setCurrentLocation( const QString& region, const QString& zone );
|
||||
/** @brief Sets a location by pointer
|
||||
|
||||
/** @brief Sets a location by pointer to zone data.
|
||||
*
|
||||
* Pointer should be within the same model as the widget uses.
|
||||
* This can update the locale configuration -- the automatic one
|
||||
* follows the current location, and otherwise only explicitly-set
|
||||
* values will ignore changes to the location.
|
||||
*/
|
||||
void setCurrentLocation( const CalamaresUtils::Locale::TZZone* location );
|
||||
void setCurrentLocation( const CalamaresUtils::Locale::TimeZoneData* tz );
|
||||
|
||||
QString currentLanguageCode() const { return localeConfiguration().language(); }
|
||||
QString currentLCCode() const { return localeConfiguration().lc_numeric; }
|
||||
QString currentTimezoneName() const; // human-readable
|
||||
QString currentTimezoneCode() const;
|
||||
|
||||
signals:
|
||||
void currentLocationChanged( const CalamaresUtils::Locale::TZZone* location ) const;
|
||||
void currentLocationChanged( const CalamaresUtils::Locale::TimeZoneData* location ) const;
|
||||
void currentLocationStatusChanged( const QString& ) const;
|
||||
void currentLanguageStatusChanged( const QString& ) const;
|
||||
void currentLCStatusChanged( const QString& ) const;
|
||||
void prettyStatusChanged( const QString& ) const;
|
||||
void currentLanguageCodeChanged( const QString& ) const;
|
||||
void currentLCCodeChanged( const QString& ) const;
|
||||
void currentTimezoneCodeChanged( const QString& ) const;
|
||||
void currentTimezoneNameChanged( const QString& ) const;
|
||||
|
||||
private:
|
||||
/// A list of supported locale identifiers (e.g. "en_US.UTF-8")
|
||||
QStringList m_localeGenLines;
|
||||
|
||||
/// The regions (America, Asia, Europe ..)
|
||||
std::unique_ptr< CalamaresUtils::Locale::CStringListModel > m_regionModel;
|
||||
/// The zones for the current region (e.g. America/New_York)
|
||||
std::unique_ptr< CalamaresUtils::Locale::CStringListModel > m_zonesModel;
|
||||
std::unique_ptr< CalamaresUtils::Locale::RegionsModel > m_regionModel;
|
||||
std::unique_ptr< CalamaresUtils::Locale::ZonesModel > m_zonesModel;
|
||||
std::unique_ptr< CalamaresUtils::Locale::RegionalZonesModel > m_regionalZonesModel;
|
||||
|
||||
/// The location, points into the timezone data
|
||||
const CalamaresUtils::Locale::TZZone* m_currentLocation = nullptr;
|
||||
const CalamaresUtils::Locale::TimeZoneData* m_currentLocation = nullptr;
|
||||
|
||||
/** @brief Specific locale configurations
|
||||
*
|
||||
|
@ -1,7 +1,8 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2014-2016, Teo Mrnjavac <teo@kde.org>
|
||||
* Copyright 2017-2019, Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-FileCopyrightText: 2014-2016 Teo Mrnjavac <teo@kde.org>
|
||||
* SPDX-FileCopyrightText: 2017-2019 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* Calamares is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -42,7 +43,7 @@ LocalePage::LocalePage( Config* config, QWidget* parent )
|
||||
QBoxLayout* mainLayout = new QVBoxLayout;
|
||||
|
||||
QBoxLayout* tzwLayout = new QHBoxLayout;
|
||||
m_tzWidget = new TimeZoneWidget( config->timezoneData(), this );
|
||||
m_tzWidget = new TimeZoneWidget( m_config->zonesModel(), this );
|
||||
tzwLayout->addStretch();
|
||||
tzwLayout->addWidget( m_tzWidget );
|
||||
tzwLayout->addStretch();
|
||||
@ -101,6 +102,7 @@ LocalePage::LocalePage( Config* config, QWidget* parent )
|
||||
// Set up the location before connecting signals, to avoid a signal
|
||||
// storm as various parts interact.
|
||||
m_regionCombo->setModel( m_config->regionModel() );
|
||||
m_zoneCombo->setModel( m_config->regionalZonesModel() );
|
||||
locationChanged( m_config->currentLocation() ); // doesn't inform TZ widget
|
||||
m_tzWidget->setCurrentLocation( m_config->currentLocation() );
|
||||
|
||||
@ -111,7 +113,7 @@ LocalePage::LocalePage( Config* config, QWidget* parent )
|
||||
connect( m_tzWidget,
|
||||
&TimeZoneWidget::locationChanged,
|
||||
config,
|
||||
QOverload< const CalamaresUtils::Locale::TZZone* >::of( &Config::setCurrentLocation ) );
|
||||
QOverload< const CalamaresUtils::Locale::TimeZoneData* >::of( &Config::setCurrentLocation ) );
|
||||
|
||||
connect( m_regionCombo, QOverload< int >::of( &QComboBox::currentIndexChanged ), this, &LocalePage::regionChanged );
|
||||
connect( m_zoneCombo, QOverload< int >::of( &QComboBox::currentIndexChanged ), this, &LocalePage::zoneChanged );
|
||||
@ -151,35 +153,26 @@ LocalePage::regionChanged( int currentIndex )
|
||||
{
|
||||
using namespace CalamaresUtils::Locale;
|
||||
|
||||
Q_UNUSED( currentIndex )
|
||||
QString selectedRegion = m_regionCombo->currentData().toString();
|
||||
|
||||
TZRegion* region = m_config->timezoneData().find< TZRegion >( selectedRegion );
|
||||
if ( !region )
|
||||
QString selectedRegion = m_regionCombo->itemData( currentIndex ).toString();
|
||||
{
|
||||
return;
|
||||
cSignalBlocker z( m_zoneCombo );
|
||||
m_config->regionalZonesModel()->setRegion( selectedRegion );
|
||||
}
|
||||
|
||||
{
|
||||
cSignalBlocker b( m_zoneCombo );
|
||||
m_zoneCombo->setModel( new CStringListModel( region->zones() ) );
|
||||
}
|
||||
|
||||
m_zoneCombo->currentIndexChanged( m_zoneCombo->currentIndex() );
|
||||
m_zoneCombo->currentIndexChanged( 0 );
|
||||
}
|
||||
|
||||
void
|
||||
LocalePage::zoneChanged( int currentIndex )
|
||||
{
|
||||
Q_UNUSED( currentIndex )
|
||||
if ( !m_blockTzWidgetSet )
|
||||
{
|
||||
m_config->setCurrentLocation( m_regionCombo->currentData().toString(), m_zoneCombo->currentData().toString() );
|
||||
m_config->setCurrentLocation( m_regionCombo->currentData().toString(),
|
||||
m_zoneCombo->itemData( currentIndex ).toString() );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LocalePage::locationChanged( const CalamaresUtils::Locale::TZZone* location )
|
||||
LocalePage::locationChanged( const CalamaresUtils::Locale::TimeZoneData* location )
|
||||
{
|
||||
if ( !location )
|
||||
{
|
||||
|
@ -53,7 +53,7 @@ private:
|
||||
|
||||
void regionChanged( int currentIndex );
|
||||
void zoneChanged( int currentIndex );
|
||||
void locationChanged( const CalamaresUtils::Locale::TZZone* location );
|
||||
void locationChanged( const CalamaresUtils::Locale::TimeZoneData* location );
|
||||
void changeLocale();
|
||||
void changeFormats();
|
||||
|
||||
|
@ -138,6 +138,7 @@ LocaleViewStep::jobs() const
|
||||
void
|
||||
LocaleViewStep::onActivate()
|
||||
{
|
||||
m_config->setCurrentLocation(); // Finalize the location
|
||||
if ( !m_actualWidget )
|
||||
{
|
||||
setUpPage();
|
||||
@ -149,6 +150,7 @@ LocaleViewStep::onActivate()
|
||||
void
|
||||
LocaleViewStep::onLeave()
|
||||
{
|
||||
m_config->finalizeGlobalStorage();
|
||||
}
|
||||
|
||||
|
||||
|
@ -16,17 +16,40 @@
|
||||
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "Tests.h"
|
||||
#include "Config.h"
|
||||
#include "LocaleConfiguration.h"
|
||||
#include "timezonewidget/TimeZoneImage.h"
|
||||
|
||||
#include "locale/TimeZone.h"
|
||||
#include "utils/Logger.h"
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
#include <set>
|
||||
|
||||
class LocaleTests : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
LocaleTests();
|
||||
~LocaleTests() override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
// Check the sample config file is processed correctly
|
||||
void testEmptyLocaleConfiguration();
|
||||
void testDefaultLocaleConfiguration();
|
||||
void testSplitLocaleConfiguration();
|
||||
|
||||
// Check the TZ images for consistency
|
||||
void testTZImages(); // No overlaps in images
|
||||
void testTZLocations(); // No overlaps in locations
|
||||
void testSpecificLocations();
|
||||
|
||||
// Check the Config loading
|
||||
void testConfigInitialization();
|
||||
};
|
||||
|
||||
QTEST_MAIN( LocaleTests )
|
||||
|
||||
|
||||
@ -115,24 +138,23 @@ LocaleTests::testTZImages()
|
||||
//
|
||||
//
|
||||
using namespace CalamaresUtils::Locale;
|
||||
const CStringPairList& regions = TZRegion::fromZoneTab();
|
||||
const ZonesModel m;
|
||||
|
||||
int overlapcount = 0;
|
||||
for ( const auto* pr : regions )
|
||||
for ( auto it = m.begin(); it; ++it )
|
||||
{
|
||||
const TZRegion* region = dynamic_cast< const TZRegion* >( pr );
|
||||
QVERIFY( region );
|
||||
QString region = m.data( m.index( it.index() ), ZonesModel::RegionRole ).toString();
|
||||
QString zoneName = m.data( m.index( it.index() ), ZonesModel::KeyRole ).toString();
|
||||
QVERIFY( !region.isEmpty() );
|
||||
QVERIFY( !zoneName.isEmpty() );
|
||||
const auto* zone = m.find( region, zoneName );
|
||||
const auto* iterzone = *it;
|
||||
|
||||
Logger::setupLogLevel( Logger::LOGDEBUG );
|
||||
cDebug() << "Region" << region->region() << "zones #" << region->zones().count();
|
||||
Logger::setupLogLevel( Logger::LOGERROR );
|
||||
|
||||
const auto zones = region->zones();
|
||||
QVERIFY( zones.count() > 0 );
|
||||
for ( const auto* pz : zones )
|
||||
{
|
||||
const TZZone* zone = dynamic_cast< const TZZone* >( pz );
|
||||
QVERIFY( iterzone );
|
||||
QVERIFY( zone );
|
||||
QCOMPARE( zone, iterzone );
|
||||
QCOMPARE( zone->zone(), zoneName );
|
||||
QCOMPARE( zone->region(), region );
|
||||
|
||||
int overlap = 0;
|
||||
auto pos = images.getLocationPosition( zone->longitude(), zone->latitude() );
|
||||
@ -147,7 +169,6 @@ LocaleTests::testTZImages()
|
||||
overlapcount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QEXPECT_FAIL( "", "TZ Images not yet all fixed", Continue );
|
||||
QCOMPARE( overlapcount, 0 );
|
||||
@ -168,12 +189,17 @@ operator<( const QPoint& l, const QPoint& r )
|
||||
}
|
||||
|
||||
void
|
||||
listAll( const QPoint& p, const CalamaresUtils::Locale::CStringPairList& zones )
|
||||
listAll( const QPoint& p, const CalamaresUtils::Locale::ZonesModel& zones )
|
||||
{
|
||||
using namespace CalamaresUtils::Locale;
|
||||
for ( const auto* pz : zones )
|
||||
for ( auto it = zones.begin(); it; ++it )
|
||||
{
|
||||
const TZZone* zone = dynamic_cast< const TZZone* >( pz );
|
||||
const auto* zone = *it;
|
||||
if ( !zone )
|
||||
{
|
||||
cError() << Logger::SubEntry << "NULL zone";
|
||||
return;
|
||||
}
|
||||
if ( p == TimeZoneImageList::getLocationPosition( zone->longitude(), zone->latitude() ) )
|
||||
{
|
||||
cError() << Logger::SubEntry << zone->zone();
|
||||
@ -185,25 +211,15 @@ void
|
||||
LocaleTests::testTZLocations()
|
||||
{
|
||||
using namespace CalamaresUtils::Locale;
|
||||
const CStringPairList& regions = TZRegion::fromZoneTab();
|
||||
ZonesModel zones;
|
||||
|
||||
QVERIFY( zones.rowCount( QModelIndex() ) > 100 );
|
||||
|
||||
int overlapcount = 0;
|
||||
for ( const auto* pr : regions )
|
||||
{
|
||||
const TZRegion* region = dynamic_cast< const TZRegion* >( pr );
|
||||
QVERIFY( region );
|
||||
|
||||
Logger::setupLogLevel( Logger::LOGDEBUG );
|
||||
cDebug() << "Region" << region->region() << "zones #" << region->zones().count();
|
||||
Logger::setupLogLevel( Logger::LOGERROR );
|
||||
|
||||
std::set< QPoint > occupied;
|
||||
|
||||
const auto zones = region->zones();
|
||||
QVERIFY( zones.count() > 0 );
|
||||
for ( const auto* pz : zones )
|
||||
for ( auto it = zones.begin(); it; ++it )
|
||||
{
|
||||
const TZZone* zone = dynamic_cast< const TZZone* >( pz );
|
||||
const auto* zone = *it;
|
||||
QVERIFY( zone );
|
||||
|
||||
auto pos = TimeZoneImageList::getLocationPosition( zone->longitude(), zone->latitude() );
|
||||
@ -215,48 +231,17 @@ LocaleTests::testTZLocations()
|
||||
}
|
||||
occupied.insert( pos );
|
||||
}
|
||||
}
|
||||
|
||||
QEXPECT_FAIL( "", "TZ Images contain pixel-overlaps", Continue );
|
||||
QCOMPARE( overlapcount, 0 );
|
||||
}
|
||||
|
||||
const CalamaresUtils::Locale::TZZone*
|
||||
findZone( const QString& name )
|
||||
{
|
||||
using namespace CalamaresUtils::Locale;
|
||||
const CStringPairList& regions = TZRegion::fromZoneTab();
|
||||
|
||||
for ( const auto* pr : regions )
|
||||
{
|
||||
const TZRegion* region = dynamic_cast< const TZRegion* >( pr );
|
||||
if ( !region )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const auto zones = region->zones();
|
||||
for ( const auto* pz : zones )
|
||||
{
|
||||
const TZZone* zone = dynamic_cast< const TZZone* >( pz );
|
||||
if ( !zone )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( zone->zone() == name )
|
||||
{
|
||||
return zone;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
LocaleTests::testSpecificLocations()
|
||||
{
|
||||
const auto* gibraltar = findZone( "Gibraltar" );
|
||||
const auto* ceuta = findZone( "Ceuta" );
|
||||
CalamaresUtils::Locale::ZonesModel zones;
|
||||
const auto* gibraltar = zones.find( "Europe", "Gibraltar" );
|
||||
const auto* ceuta = zones.find( "Africa", "Ceuta" );
|
||||
QVERIFY( gibraltar );
|
||||
QVERIFY( ceuta );
|
||||
|
||||
@ -268,3 +253,17 @@ LocaleTests::testSpecificLocations()
|
||||
QEXPECT_FAIL( "", "Gibraltar and Ceuta are really close", Continue );
|
||||
QVERIFY( gpos.y() < cpos.y() ); // Gibraltar is north of Ceuta
|
||||
}
|
||||
|
||||
void
|
||||
LocaleTests::testConfigInitialization()
|
||||
{
|
||||
Config c;
|
||||
|
||||
QVERIFY( !c.currentLocation() );
|
||||
QVERIFY( !c.currentLocationStatus().isEmpty() );
|
||||
}
|
||||
|
||||
|
||||
#include "utils/moc-warnings.h"
|
||||
|
||||
#include "Tests.moc"
|
||||
|
@ -1,45 +0,0 @@
|
||||
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2019-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 TESTS_H
|
||||
#define TESTS_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class LocaleTests : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
LocaleTests();
|
||||
~LocaleTests() override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
// Check the sample config file is processed correctly
|
||||
void testEmptyLocaleConfiguration();
|
||||
void testDefaultLocaleConfiguration();
|
||||
void testSplitLocaleConfiguration();
|
||||
|
||||
// Check the TZ images for consistency
|
||||
void testTZImages(); // No overlaps in images
|
||||
void testTZLocations(); // No overlaps in locations
|
||||
void testSpecificLocations();
|
||||
};
|
||||
|
||||
#endif
|
@ -35,13 +35,13 @@
|
||||
#endif
|
||||
|
||||
static QPoint
|
||||
getLocationPosition( const CalamaresUtils::Locale::TZZone* l )
|
||||
getLocationPosition( const CalamaresUtils::Locale::TimeZoneData* l )
|
||||
{
|
||||
return TimeZoneImageList::getLocationPosition( l->longitude(), l->latitude() );
|
||||
}
|
||||
|
||||
|
||||
TimeZoneWidget::TimeZoneWidget( const CalamaresUtils::Locale::CStringPairList& zones, QWidget* parent )
|
||||
TimeZoneWidget::TimeZoneWidget( const CalamaresUtils::Locale::ZonesModel* zones, QWidget* parent )
|
||||
: QWidget( parent )
|
||||
, timeZoneImages( TimeZoneImageList::fromQRC() )
|
||||
, m_zonesData( zones )
|
||||
@ -65,7 +65,7 @@ TimeZoneWidget::TimeZoneWidget( const CalamaresUtils::Locale::CStringPairList& z
|
||||
|
||||
|
||||
void
|
||||
TimeZoneWidget::setCurrentLocation( const CalamaresUtils::Locale::TZZone* location )
|
||||
TimeZoneWidget::setCurrentLocation( const TimeZoneData* location )
|
||||
{
|
||||
if ( location == m_currentLocation )
|
||||
{
|
||||
@ -191,35 +191,14 @@ TimeZoneWidget::mousePressEvent( QMouseEvent* event )
|
||||
return;
|
||||
}
|
||||
|
||||
// Set nearest location
|
||||
int nX = 999999, mX = event->pos().x();
|
||||
int nY = 999999, mY = event->pos().y();
|
||||
|
||||
using namespace CalamaresUtils::Locale;
|
||||
const TZZone* closest = nullptr;
|
||||
for ( const auto* region_p : m_zonesData )
|
||||
{
|
||||
const auto* region = dynamic_cast< const TZRegion* >( region_p );
|
||||
if ( region )
|
||||
{
|
||||
for ( const auto* zone_p : region->zones() )
|
||||
{
|
||||
const auto* zone = dynamic_cast< const TZZone* >( zone_p );
|
||||
if ( zone )
|
||||
{
|
||||
int mX = event->pos().x();
|
||||
int mY = event->pos().y();
|
||||
auto distance = [&]( const CalamaresUtils::Locale::TimeZoneData* zone ) {
|
||||
QPoint locPos = TimeZoneImageList::getLocationPosition( zone->longitude(), zone->latitude() );
|
||||
return double( abs( mX - locPos.x() ) + abs( mY - locPos.y() ) );
|
||||
};
|
||||
|
||||
if ( ( abs( mX - locPos.x() ) + abs( mY - locPos.y() ) < abs( mX - nX ) + abs( mY - nY ) ) )
|
||||
{
|
||||
closest = zone;
|
||||
nX = locPos.x();
|
||||
nY = locPos.y();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const auto* closest = m_zonesData->find( distance );
|
||||
if ( closest )
|
||||
{
|
||||
// Set zone image and repaint widget
|
||||
|
@ -51,28 +51,28 @@ class TimeZoneWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
using TZZone = CalamaresUtils::Locale::TZZone;
|
||||
using TimeZoneData = CalamaresUtils::Locale::TimeZoneData;
|
||||
|
||||
explicit TimeZoneWidget( const CalamaresUtils::Locale::CStringPairList& zones, QWidget* parent = nullptr );
|
||||
explicit TimeZoneWidget( const CalamaresUtils::Locale::ZonesModel* zones, QWidget* parent = nullptr );
|
||||
|
||||
public Q_SLOTS:
|
||||
/** @brief Sets a location by pointer
|
||||
*
|
||||
* Pointer should be within the same model as the widget uses.
|
||||
*/
|
||||
void setCurrentLocation( const TZZone* location );
|
||||
void setCurrentLocation( const TimeZoneData* location );
|
||||
|
||||
signals:
|
||||
/** @brief The location has changed by mouse click */
|
||||
void locationChanged( const TZZone* location );
|
||||
void locationChanged( const TimeZoneData* location );
|
||||
|
||||
private:
|
||||
QFont font;
|
||||
QImage background, pin, currentZoneImage;
|
||||
TimeZoneImageList timeZoneImages;
|
||||
|
||||
const CalamaresUtils::Locale::CStringPairList& m_zonesData;
|
||||
const TZZone* m_currentLocation = nullptr; // Not owned by me
|
||||
const CalamaresUtils::Locale::ZonesModel* m_zonesData;
|
||||
const TimeZoneData* m_currentLocation = nullptr; // Not owned by me
|
||||
|
||||
void paintEvent( QPaintEvent* event );
|
||||
void mousePressEvent( QMouseEvent* event );
|
||||
|
@ -79,9 +79,22 @@ LocaleQmlViewStep::jobs() const
|
||||
return m_config->createJobs();
|
||||
}
|
||||
|
||||
void
|
||||
LocaleQmlViewStep::onActivate()
|
||||
{
|
||||
m_config->setCurrentLocation(); // Finalize the location
|
||||
QmlViewStep::onActivate();
|
||||
}
|
||||
|
||||
void
|
||||
LocaleQmlViewStep::onLeave()
|
||||
{
|
||||
m_config->finalizeGlobalStorage();
|
||||
}
|
||||
|
||||
void
|
||||
LocaleQmlViewStep::setConfigurationMap( const QVariantMap& configurationMap )
|
||||
{
|
||||
m_config->setConfigurationMap( configurationMap );
|
||||
Calamares::QmlViewStep::setConfigurationMap( configurationMap ); // call parent implementation last
|
||||
QmlViewStep::setConfigurationMap( configurationMap ); // call parent implementation last
|
||||
}
|
||||
|
@ -43,6 +43,9 @@ public:
|
||||
bool isAtBeginning() const override;
|
||||
bool isAtEnd() const override;
|
||||
|
||||
virtual void onActivate() override;
|
||||
virtual void onLeave() override;
|
||||
|
||||
Calamares::JobList jobs() const override;
|
||||
|
||||
void setConfigurationMap( const QVariantMap& configurationMap ) override;
|
||||
|
@ -29,19 +29,19 @@ import QtPositioning 5.14
|
||||
Column {
|
||||
width: parent.width
|
||||
|
||||
//Needs to come from .conf/geoip
|
||||
property var configCity: "New York"
|
||||
property var configCountry: "USA"
|
||||
property var configTimezone: "America/New York"
|
||||
property var geoipCity: "" //"Amsterdam"
|
||||
property var geoipCountry: "" //"Netherlands"
|
||||
property var geoipTimezone: "" //"Europe/Amsterdam"
|
||||
// vars that will stay once connected
|
||||
property var cityName: (geoipCity != "") ? geoipCity : configCity
|
||||
property var countryName: (geoipCountry != "") ? geoipCountry : configCountry
|
||||
property var timeZone: (geoipTimezone != "") ? geoipTimezone : configTimezone
|
||||
// These are used by the map query to initially center the
|
||||
// map on the user's likely location. They are updated by
|
||||
// getIp() which does a more accurate GeoIP lookup than
|
||||
// the default one in Calamares
|
||||
property var cityName: ""
|
||||
property var countryName: ""
|
||||
|
||||
function getIp() {
|
||||
/* This is an extra GeoIP lookup, which will find better-accuracy
|
||||
* location data for the user's IP, and then sets the current timezone
|
||||
* and map location. Call it from Component.onCompleted so that
|
||||
* it happens "on time" before the page is shown.
|
||||
*/
|
||||
function getIpOnline() {
|
||||
var xhr = new XMLHttpRequest
|
||||
|
||||
xhr.onreadystatechange = function() {
|
||||
@ -51,9 +51,10 @@ Column {
|
||||
var ct = responseJSON.city
|
||||
var cy = responseJSON.country
|
||||
|
||||
tzText.text = "Timezone: " + tz
|
||||
cityName = ct
|
||||
countryName = cy
|
||||
|
||||
config.setCurrentLocation(tz)
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,7 +64,25 @@ Column {
|
||||
xhr.send()
|
||||
}
|
||||
|
||||
function getTz() {
|
||||
/* This is an "offline" GeoIP lookup -- it just follows what
|
||||
* Calamares itself has figured out with its GeoIP or configuration.
|
||||
* Call it from the **Component** onActivate() -- in localeq.qml --
|
||||
* so it happens as the page is shown.
|
||||
*/
|
||||
function getIpOffline() {
|
||||
cityName = config.currentLocation.zone
|
||||
countryName = config.currentLocation.countryCode
|
||||
}
|
||||
|
||||
/* This is an **accurate** TZ lookup method: it queries an
|
||||
* online service for the TZ at the given coordinates. It
|
||||
* requires an internet connection, though, and the distribution
|
||||
* will need to have an account with geonames to not hit the
|
||||
* daily query limit.
|
||||
*
|
||||
* See below, in MouseArea, for calling the right method.
|
||||
*/
|
||||
function getTzOnline() {
|
||||
var xhr = new XMLHttpRequest
|
||||
var latC = map.center.latitude
|
||||
var lonC = map.center.longitude
|
||||
@ -73,16 +92,29 @@ Column {
|
||||
var responseJSON = JSON.parse(xhr.responseText)
|
||||
var tz2 = responseJSON.timezoneId
|
||||
|
||||
tzText.text = "Timezone: " + tz2
|
||||
config.setCurrentLocation(tz2)
|
||||
}
|
||||
}
|
||||
|
||||
console.log("Online lookup", latC, lonC)
|
||||
// Needs to move to localeq.conf, each distribution will need their own account
|
||||
xhr.open("GET", "http://api.geonames.org/timezoneJSON?lat=" + latC + "&lng=" + lonC + "&username=SOME_USERNAME")
|
||||
xhr.send()
|
||||
}
|
||||
|
||||
/* This is a quick TZ lookup method: it uses the existing
|
||||
* Calamares "closest TZ" code, which has lots of caveats.
|
||||
*
|
||||
* See below, in MouseArea, for calling the right method.
|
||||
*/
|
||||
function getTzOffline() {
|
||||
var latC = map.center.latitude
|
||||
var lonC = map.center.longitude
|
||||
var tz = config.zonesModel.lookup(latC, lonC)
|
||||
console.log("Offline lookup", latC, lonC)
|
||||
config.setCurrentLocation(tz.region, tz.zone)
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: parent.height / 1.28
|
||||
@ -156,9 +188,8 @@ Column {
|
||||
map.center.latitude = coordinate.latitude
|
||||
map.center.longitude = coordinate.longitude
|
||||
|
||||
getTz();
|
||||
|
||||
console.log(coordinate.latitude, coordinate.longitude)
|
||||
// Pick a TZ lookup method here (quick:offline, accurate:online)
|
||||
getTzOffline();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -218,13 +249,16 @@ Column {
|
||||
|
||||
Text {
|
||||
id: tzText
|
||||
text: tzText.text
|
||||
//text: qsTr("Timezone: %1").arg(timeZone)
|
||||
text: qsTr("Timezone: %1").arg(config.currentTimezoneName)
|
||||
color: Kirigami.Theme.textColor
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
Component.onCompleted: getIp();
|
||||
/* If you want an extra (and accurate) GeoIP lookup,
|
||||
* enable this one and disable the offline lookup in
|
||||
* onActivate().
|
||||
Component.onCompleted: getIpOnline();
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,14 @@ Page {
|
||||
width: 800
|
||||
height: 550
|
||||
|
||||
function onActivate() {
|
||||
/* If you want the map to follow Calamares's GeoIP
|
||||
* lookup or configuration, call the update function
|
||||
* here, and disable the one at onCompleted in Map.qml.
|
||||
*/
|
||||
if (Network.hasInternet) { image.item.getIpOffline() }
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: image
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
@ -138,7 +138,7 @@ PreserveFiles::exec()
|
||||
}
|
||||
if ( it.type == ItemType::Config )
|
||||
{
|
||||
if ( Calamares::JobQueue::instance()->globalStorage()->save( dest ) )
|
||||
if ( Calamares::JobQueue::instance()->globalStorage()->saveJson( dest ) )
|
||||
{
|
||||
cWarning() << "Could not write config for" << dest;
|
||||
}
|
||||
|
@ -71,4 +71,7 @@ calamares_add_test(
|
||||
SOURCES
|
||||
Tests.cpp
|
||||
Config.cpp
|
||||
CheckPWQuality.cpp
|
||||
LIBRARIES
|
||||
${USER_EXTRA_LIB}
|
||||
)
|
||||
|
@ -22,7 +22,6 @@
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QString>
|
||||
#include <QWidget>
|
||||
|
||||
#ifdef HAVE_LIBPWQUALITY
|
||||
#include <pwquality.h>
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "utils/String.h"
|
||||
#include "utils/Variant.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QFile>
|
||||
#include <QRegExp>
|
||||
|
||||
@ -36,6 +37,22 @@ static const QRegExp HOSTNAME_RX( "^[a-zA-Z0-9][-a-zA-Z0-9_]*$" );
|
||||
static constexpr const int HOSTNAME_MIN_LENGTH = 2;
|
||||
static constexpr const int HOSTNAME_MAX_LENGTH = 63;
|
||||
|
||||
const NamedEnumTable< HostNameAction >&
|
||||
hostNameActionNames()
|
||||
{
|
||||
// *INDENT-OFF*
|
||||
// clang-format off
|
||||
static const NamedEnumTable< HostNameAction > names {
|
||||
{ QStringLiteral( "none" ), HostNameAction::None },
|
||||
{ QStringLiteral( "etcfile" ), HostNameAction::EtcHostname },
|
||||
{ QStringLiteral( "hostnamed" ), HostNameAction::SystemdHostname }
|
||||
};
|
||||
// clang-format on
|
||||
// *INDENT-ON*
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
Config::Config( QObject* parent )
|
||||
: QObject( parent )
|
||||
{
|
||||
@ -343,6 +360,106 @@ Config::setAutoLogin( bool b )
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Config::setReuseUserPasswordForRoot( bool reuse )
|
||||
{
|
||||
if ( reuse != m_reuseUserPasswordForRoot )
|
||||
{
|
||||
m_reuseUserPasswordForRoot = reuse;
|
||||
emit reuseUserPasswordForRootChanged( reuse );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Config::setRequireStrongPasswords( bool strong )
|
||||
{
|
||||
if ( strong != m_requireStrongPasswords )
|
||||
{
|
||||
m_requireStrongPasswords = strong;
|
||||
emit requireStrongPasswordsChanged( strong );
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Config::isPasswordAcceptable( const QString& password, QString& message )
|
||||
{
|
||||
bool failureIsFatal = requireStrongPasswords();
|
||||
|
||||
for ( auto pc : m_passwordChecks )
|
||||
{
|
||||
QString s = pc.filter( password );
|
||||
|
||||
if ( !s.isEmpty() )
|
||||
{
|
||||
message = s;
|
||||
return !failureIsFatal;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Config::setUserPassword( const QString& s )
|
||||
{
|
||||
m_userPassword = s;
|
||||
// TODO: check new password status
|
||||
emit userPasswordChanged( s );
|
||||
}
|
||||
|
||||
void
|
||||
Config::setUserPasswordSecondary( const QString& s )
|
||||
{
|
||||
m_userPasswordSecondary = s;
|
||||
// TODO: check new password status
|
||||
emit userPasswordSecondaryChanged( s );
|
||||
}
|
||||
|
||||
void
|
||||
Config::setRootPassword( const QString& s )
|
||||
{
|
||||
if ( writeRootPassword() )
|
||||
{
|
||||
m_rootPassword = s;
|
||||
// TODO: check new password status
|
||||
emit rootPasswordChanged( s );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Config::setRootPasswordSecondary( const QString& s )
|
||||
{
|
||||
if ( writeRootPassword() )
|
||||
{
|
||||
m_rootPasswordSecondary = s;
|
||||
// TODO: check new password status
|
||||
emit rootPasswordSecondaryChanged( s );
|
||||
}
|
||||
}
|
||||
|
||||
QString Config::rootPassword() const
|
||||
{
|
||||
if ( writeRootPassword() )
|
||||
{
|
||||
if ( reuseUserPasswordForRoot() )
|
||||
return userPassword();
|
||||
return m_rootPassword;
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString Config::rootPasswordSecondary() const
|
||||
{
|
||||
if ( writeRootPassword() )
|
||||
{
|
||||
if ( reuseUserPasswordForRoot() )
|
||||
return userPasswordSecondary();
|
||||
return m_rootPasswordSecondary;
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
|
||||
STATICTEST void
|
||||
setConfigurationDefaultGroups( const QVariantMap& map, QStringList& defaultGroups )
|
||||
{
|
||||
@ -357,6 +474,74 @@ setConfigurationDefaultGroups( const QVariantMap& map, QStringList& defaultGroup
|
||||
}
|
||||
}
|
||||
|
||||
STATICTEST HostNameActions
|
||||
getHostNameActions( const QVariantMap& configurationMap )
|
||||
{
|
||||
HostNameAction setHostName = HostNameAction::EtcHostname;
|
||||
QString hostnameActionString = CalamaresUtils::getString( configurationMap, "setHostname" );
|
||||
if ( !hostnameActionString.isEmpty() )
|
||||
{
|
||||
bool ok = false;
|
||||
setHostName = hostNameActionNames().find( hostnameActionString, ok );
|
||||
if ( !ok )
|
||||
{
|
||||
setHostName = HostNameAction::EtcHostname; // Rather than none
|
||||
}
|
||||
}
|
||||
|
||||
HostNameAction writeHosts = CalamaresUtils::getBool( configurationMap, "writeHostsFile", true )
|
||||
? HostNameAction::WriteEtcHosts
|
||||
: HostNameAction::None;
|
||||
return setHostName | writeHosts;
|
||||
}
|
||||
|
||||
/** @brief Process entries in the passwordRequirements config entry
|
||||
*
|
||||
* Called once for each item in the config entry, which should
|
||||
* be a key-value pair. What makes sense as a value depends on
|
||||
* the key. Supported keys are documented in users.conf.
|
||||
*
|
||||
* @return if the check was added, returns @c true
|
||||
*/
|
||||
STATICTEST bool
|
||||
addPasswordCheck( const QString& key, const QVariant& value, PasswordCheckList& passwordChecks )
|
||||
{
|
||||
if ( key == "minLength" )
|
||||
{
|
||||
add_check_minLength( passwordChecks, value );
|
||||
}
|
||||
else if ( key == "maxLength" )
|
||||
{
|
||||
add_check_maxLength( passwordChecks, value );
|
||||
}
|
||||
else if ( key == "nonempty" )
|
||||
{
|
||||
if ( value.toBool() )
|
||||
{
|
||||
passwordChecks.push_back(
|
||||
PasswordCheck( []() { return QCoreApplication::translate( "PWQ", "Password is empty" ); },
|
||||
[]( const QString& s ) { return !s.isEmpty(); },
|
||||
PasswordCheck::Weight( 1 ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
cDebug() << "nonempty check is mentioned but set to false";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#ifdef CHECK_PWQUALITY
|
||||
else if ( key == "libpwquality" )
|
||||
{
|
||||
add_check_libpwquality( passwordChecks, value );
|
||||
}
|
||||
#endif // CHECK_PWQUALITY
|
||||
else
|
||||
{
|
||||
cWarning() << "Unknown password-check key" << key;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Config::setConfigurationMap( const QVariantMap& configurationMap )
|
||||
@ -372,9 +557,25 @@ Config::setConfigurationMap( const QVariantMap& configurationMap )
|
||||
setAutologinGroup( CalamaresUtils::getString( configurationMap, "autologinGroup" ) );
|
||||
setSudoersGroup( CalamaresUtils::getString( configurationMap, "sudoersGroup" ) );
|
||||
|
||||
m_hostNameActions = getHostNameActions( configurationMap );
|
||||
|
||||
setConfigurationDefaultGroups( configurationMap, m_defaultGroups );
|
||||
m_doAutoLogin = CalamaresUtils::getBool( configurationMap, "doAutologin", false );
|
||||
|
||||
m_writeRootPassword = CalamaresUtils::getBool( configurationMap, "setRootPassword", true );
|
||||
Calamares::JobQueue::instance()->globalStorage()->insert( "setRootPassword", m_writeRootPassword );
|
||||
|
||||
m_reuseUserPasswordForRoot = CalamaresUtils::getBool( configurationMap, "doReusePassword", false );
|
||||
|
||||
m_permitWeakPasswords = CalamaresUtils::getBool( configurationMap, "allowWeakPasswords", false );
|
||||
m_requireStrongPasswords
|
||||
= !m_permitWeakPasswords || !CalamaresUtils::getBool( configurationMap, "allowWeakPasswordsDefault", false );
|
||||
|
||||
// If the value doesn't exist, or isn't a map, this gives an empty map -- no problem
|
||||
auto pr_checks( configurationMap.value( "passwordRequirements" ).toMap() );
|
||||
for ( decltype( pr_checks )::const_iterator i = pr_checks.constBegin(); i != pr_checks.constEnd(); ++i )
|
||||
{
|
||||
addPasswordCheck( i.key(), i.value(), m_passwordChecks );
|
||||
}
|
||||
std::sort( m_passwordChecks.begin(), m_passwordChecks.end() );
|
||||
}
|
||||
|
@ -21,9 +21,25 @@
|
||||
#ifndef USERS_CONFIG_H
|
||||
#define USERS_CONFIG_H
|
||||
|
||||
#include "CheckPWQuality.h"
|
||||
|
||||
#include "utils/NamedEnum.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariantMap>
|
||||
|
||||
enum HostNameAction
|
||||
{
|
||||
None = 0x0,
|
||||
EtcHostname = 0x1, // Write to /etc/hostname directly
|
||||
SystemdHostname = 0x2, // Set via hostnamed(1)
|
||||
WriteEtcHosts = 0x4 // Write /etc/hosts (127.0.1.1 is this host)
|
||||
};
|
||||
Q_DECLARE_FLAGS( HostNameActions, HostNameAction )
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS( HostNameActions )
|
||||
|
||||
const NamedEnumTable< HostNameAction >& hostNameActionNames();
|
||||
|
||||
class Config : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -41,6 +57,22 @@ class Config : public QObject
|
||||
|
||||
Q_PROPERTY( QString hostName READ hostName WRITE setHostName NOTIFY hostNameChanged )
|
||||
Q_PROPERTY( QString hostNameStatus READ hostNameStatus NOTIFY hostNameStatusChanged )
|
||||
Q_PROPERTY( HostNameActions hostNameActions READ hostNameActions CONSTANT )
|
||||
|
||||
Q_PROPERTY( QString userPassword READ userPassword WRITE setUserPassword NOTIFY userPasswordChanged )
|
||||
Q_PROPERTY( QString userPasswordSecondary READ userPasswordSecondary WRITE setUserPasswordSecondary NOTIFY
|
||||
userPasswordSecondaryChanged )
|
||||
Q_PROPERTY( QString rootPassword READ rootPassword WRITE setRootPassword NOTIFY rootPasswordChanged )
|
||||
Q_PROPERTY( QString rootPasswordSecondary READ rootPasswordSecondary WRITE setRootPasswordSecondary NOTIFY
|
||||
rootPasswordSecondaryChanged )
|
||||
|
||||
Q_PROPERTY( bool writeRootPassword READ writeRootPassword CONSTANT )
|
||||
Q_PROPERTY( bool reuseUserPasswordForRoot READ reuseUserPasswordForRoot WRITE setReuseUserPasswordForRoot NOTIFY
|
||||
reuseUserPasswordForRootChanged )
|
||||
|
||||
Q_PROPERTY( bool permitWeakPasswords READ permitWeakPasswords CONSTANT )
|
||||
Q_PROPERTY( bool requireStrongPasswords READ requireStrongPasswords WRITE setRequireStrongPasswords NOTIFY
|
||||
requireStrongPasswordsChanged )
|
||||
|
||||
public:
|
||||
Config( QObject* parent = nullptr );
|
||||
@ -71,14 +103,42 @@ public:
|
||||
QString hostName() const { return m_hostName; }
|
||||
/// Status message about hostname -- empty for "ok"
|
||||
QString hostNameStatus() const;
|
||||
/// How to write the hostname
|
||||
HostNameActions hostNameActions() const { return m_hostNameActions; }
|
||||
|
||||
/// Should the user be automatically logged-in?
|
||||
bool doAutoLogin() const { return m_doAutoLogin; }
|
||||
/// Should the root password be written (if false, no password is set and the root account is disabled for login)
|
||||
bool writeRootPassword() const { return m_writeRootPassword; }
|
||||
/// Should the user's password be used for root, too? (if root is written at all)
|
||||
bool reuseUserPasswordForRoot() const { return m_reuseUserPasswordForRoot; }
|
||||
/// Show UI to change the "require strong password" setting?
|
||||
bool permitWeakPasswords() const { return m_permitWeakPasswords; }
|
||||
/// Current setting for "require strong password"?
|
||||
bool requireStrongPasswords() const { return m_requireStrongPasswords; }
|
||||
|
||||
const QStringList& defaultGroups() const { return m_defaultGroups; }
|
||||
|
||||
/** @brief Checks if the password is acceptable.
|
||||
*
|
||||
* If all is well, sets @p message to empty and returns @c true.
|
||||
* If there are warnings, but acceptable, sets @p message to something
|
||||
* non-empty and returns @c true. This happens if requireStrongPasswords
|
||||
* is turned off (by config or user).
|
||||
* If the password is not acceptable, sets @p message to something
|
||||
* non-empty and returns @c false.
|
||||
*/
|
||||
bool isPasswordAcceptable( const QString& password, QString& message );
|
||||
|
||||
// The user enters a password (and again in a separate UI element)
|
||||
QString userPassword() const { return m_userPassword; }
|
||||
QString userPasswordSecondary() const { return m_userPasswordSecondary; }
|
||||
// The root password **may** be entered in the UI, or may be suppressed
|
||||
// entirely when writeRootPassword is off, or may be equal to
|
||||
// the user password when reuseUserPasswordForRoot is on.
|
||||
QString rootPassword() const;
|
||||
QString rootPasswordSecondary() const;
|
||||
|
||||
static const QStringList& forbiddenLoginNames();
|
||||
static const QStringList& forbiddenHostNames();
|
||||
|
||||
@ -109,6 +169,16 @@ public Q_SLOTS:
|
||||
/// Sets the autologin flag
|
||||
void setAutoLogin( bool b );
|
||||
|
||||
/// Set to true to use the user password, unchanged, for root too
|
||||
void setReuseUserPasswordForRoot( bool reuse );
|
||||
/// Change setting for "require strong password"
|
||||
void setRequireStrongPasswords( bool strong );
|
||||
|
||||
void setUserPassword( const QString& );
|
||||
void setUserPasswordSecondary( const QString& );
|
||||
void setRootPassword( const QString& );
|
||||
void setRootPasswordSecondary( const QString& );
|
||||
|
||||
signals:
|
||||
void userShellChanged( const QString& );
|
||||
void autologinGroupChanged( const QString& );
|
||||
@ -119,6 +189,13 @@ signals:
|
||||
void hostNameChanged( const QString& );
|
||||
void hostNameStatusChanged( const QString& );
|
||||
void autoLoginChanged( bool );
|
||||
void reuseUserPasswordForRootChanged( bool );
|
||||
void requireStrongPasswordsChanged( bool );
|
||||
void userPasswordChanged( const QString& );
|
||||
void userPasswordSecondaryChanged( const QString& );
|
||||
void rootPasswordChanged( const QString& );
|
||||
void rootPasswordSecondaryChanged( const QString& );
|
||||
|
||||
|
||||
private:
|
||||
QStringList m_defaultGroups;
|
||||
@ -128,11 +205,25 @@ private:
|
||||
QString m_fullName;
|
||||
QString m_loginName;
|
||||
QString m_hostName;
|
||||
|
||||
QString m_userPassword;
|
||||
QString m_userPasswordSecondary; // enter again to be sure
|
||||
QString m_rootPassword;
|
||||
QString m_rootPasswordSecondary;
|
||||
|
||||
bool m_doAutoLogin = false;
|
||||
|
||||
bool m_writeRootPassword = true;
|
||||
bool m_reuseUserPasswordForRoot = false;
|
||||
|
||||
bool m_permitWeakPasswords = false;
|
||||
bool m_requireStrongPasswords = true;
|
||||
|
||||
bool m_customLoginName = false;
|
||||
bool m_customHostName = false;
|
||||
|
||||
HostNameActions m_hostNameActions;
|
||||
PasswordCheckList m_passwordChecks;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -27,13 +27,13 @@
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QtDBus/QDBusConnection>
|
||||
#include <QtDBus/QDBusInterface>
|
||||
#include <QtDBus/QDBusReply>
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusInterface>
|
||||
#include <QDBusReply>
|
||||
|
||||
using WriteMode = CalamaresUtils::System::WriteMode;
|
||||
|
||||
SetHostNameJob::SetHostNameJob( const QString& hostname, Actions a )
|
||||
SetHostNameJob::SetHostNameJob( const QString& hostname, HostNameActions a )
|
||||
: Calamares::Job()
|
||||
, m_hostname( hostname )
|
||||
, m_actions( a )
|
||||
@ -138,7 +138,7 @@ SetHostNameJob::exec()
|
||||
return Calamares::JobResult::error( tr( "Internal Error" ) );
|
||||
}
|
||||
|
||||
if ( m_actions & Action::EtcHostname )
|
||||
if ( m_actions & HostNameAction::EtcHostname )
|
||||
{
|
||||
if ( !setFileHostname( m_hostname ) )
|
||||
{
|
||||
@ -147,7 +147,7 @@ SetHostNameJob::exec()
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_actions & Action::WriteEtcHosts )
|
||||
if ( m_actions & HostNameAction::WriteEtcHosts )
|
||||
{
|
||||
if ( !writeFileEtcHosts( m_hostname ) )
|
||||
{
|
||||
@ -156,7 +156,7 @@ SetHostNameJob::exec()
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_actions & Action::SystemdHostname )
|
||||
if ( m_actions & HostNameAction::SystemdHostname )
|
||||
{
|
||||
// Does its own logging
|
||||
setSystemdHostname( m_hostname );
|
||||
|
@ -21,23 +21,15 @@
|
||||
#ifndef SETHOSTNAMEJOB_CPP_H
|
||||
#define SETHOSTNAMEJOB_CPP_H
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#include "Job.h"
|
||||
|
||||
class SetHostNameJob : public Calamares::Job
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Action
|
||||
{
|
||||
None = 0x0,
|
||||
EtcHostname = 0x1, // Write to /etc/hostname directly
|
||||
SystemdHostname = 0x2, // Set via hostnamed(1)
|
||||
WriteEtcHosts = 0x4 // Write /etc/hosts (127.0.1.1 is this host)
|
||||
};
|
||||
Q_DECLARE_FLAGS( Actions, Action )
|
||||
|
||||
|
||||
SetHostNameJob( const QString& hostname, Actions a );
|
||||
SetHostNameJob( const QString& hostname, HostNameActions a );
|
||||
QString prettyName() const override;
|
||||
QString prettyDescription() const override;
|
||||
QString prettyStatusMessage() const override;
|
||||
@ -45,9 +37,7 @@ public:
|
||||
|
||||
private:
|
||||
const QString m_hostname;
|
||||
const Actions m_actions;
|
||||
const HostNameActions m_actions;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS( SetHostNameJob::Actions )
|
||||
|
||||
#endif // SETHOSTNAMEJOB_CPP_H
|
||||
|
@ -25,6 +25,8 @@
|
||||
|
||||
// Implementation details
|
||||
extern void setConfigurationDefaultGroups( const QVariantMap& map, QStringList& defaultGroups );
|
||||
extern HostNameActions getHostNameActions( const QVariantMap& configurationMap );
|
||||
extern bool addPasswordCheck( const QString& key, const QVariant& value, PasswordCheckList& passwordChecks );
|
||||
|
||||
/** @brief Test Config object methods and internals
|
||||
*
|
||||
@ -40,6 +42,9 @@ private Q_SLOTS:
|
||||
void initTestCase();
|
||||
|
||||
void testDefaultGroups();
|
||||
void testHostActions_data();
|
||||
void testHostActions();
|
||||
void testPasswordChecks();
|
||||
};
|
||||
|
||||
UserTests::UserTests() {}
|
||||
@ -105,6 +110,52 @@ UserTests::testDefaultGroups()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UserTests::testHostActions_data()
|
||||
{
|
||||
QTest::addColumn< bool >( "set" );
|
||||
QTest::addColumn< QString >( "string" );
|
||||
QTest::addColumn< int >( "result" );
|
||||
|
||||
QTest::newRow( "unset " ) << false << QString() << int( HostNameAction::EtcHostname );
|
||||
QTest::newRow( "empty " ) << true << QString() << int( HostNameAction::EtcHostname );
|
||||
QTest::newRow( "bad " ) << true << QString( "derp" ) << int( HostNameAction::EtcHostname );
|
||||
QTest::newRow( "none " ) << true << QString( "none" ) << int( HostNameAction::None );
|
||||
QTest::newRow( "systemd" ) << true << QString( "Hostnamed" ) << int( HostNameAction::SystemdHostname );
|
||||
}
|
||||
|
||||
void
|
||||
UserTests::testHostActions()
|
||||
{
|
||||
QFETCH( bool, set );
|
||||
QFETCH( QString, string );
|
||||
QFETCH( int, result );
|
||||
|
||||
QVariantMap m;
|
||||
if ( set )
|
||||
{
|
||||
m.insert( "setHostname", string );
|
||||
}
|
||||
QCOMPARE( getHostNameActions( m ), HostNameActions( result ) | HostNameAction::WriteEtcHosts ); // write bits default to true
|
||||
m.insert( "writeHostsFile", false );
|
||||
QCOMPARE( getHostNameActions( m ), HostNameActions( result ) );
|
||||
m.insert( "writeHostsFile", true );
|
||||
QCOMPARE( getHostNameActions( m ), HostNameActions( result ) | HostNameAction::WriteEtcHosts );
|
||||
}
|
||||
|
||||
void
|
||||
UserTests::testPasswordChecks()
|
||||
{
|
||||
{
|
||||
PasswordCheckList l;
|
||||
QCOMPARE( l.length(), 0 );
|
||||
QVERIFY( !addPasswordCheck( "nonempty", QVariant(false), l ) ); // a silly setting
|
||||
QCOMPARE( l.length(), 0 );
|
||||
QVERIFY( addPasswordCheck( "nonempty", QVariant(true), l ) );
|
||||
QCOMPARE( l.length(), 1 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QTEST_GUILESS_MAIN( UserTests )
|
||||
|
||||
|
@ -50,7 +50,7 @@ enum class Badness
|
||||
|
||||
/** Add an error message and pixmap to a label. */
|
||||
static inline void
|
||||
labelError( QLabel* pix, QLabel* label, const QString& message, Badness bad = Badness::Fatal )
|
||||
labelError( QLabel* pix, QLabel* label, const QString& message, Badness bad )
|
||||
{
|
||||
label->setText( message );
|
||||
pix->setPixmap( CalamaresUtils::defaultPixmap( ( bad == Badness::Fatal ) ? CalamaresUtils::StatusError
|
||||
@ -88,7 +88,7 @@ labelStatus( QLabel* pix, QLabel* label, const QString& value, const QString& st
|
||||
}
|
||||
else
|
||||
{
|
||||
labelError( pix, label, status );
|
||||
labelError( pix, label, status, Badness::Fatal );
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
@ -105,6 +105,12 @@ UsersPage::UsersPage( Config* config, QWidget* parent )
|
||||
{
|
||||
ui->setupUi( this );
|
||||
|
||||
ui->checkBoxReusePassword->setVisible( m_config->writeRootPassword() );
|
||||
ui->checkBoxReusePassword->setChecked( m_config->reuseUserPasswordForRoot() );
|
||||
|
||||
ui->checkBoxValidatePassword->setVisible( m_config->permitWeakPasswords() );
|
||||
ui->checkBoxValidatePassword->setChecked( m_config->requireStrongPasswords() );
|
||||
|
||||
// Connect signals and slots
|
||||
connect( ui->textBoxUserPassword, &QLineEdit::textChanged, this, &UsersPage::onPasswordTextChanged );
|
||||
connect( ui->textBoxUserVerifiedPassword, &QLineEdit::textChanged, this, &UsersPage::onPasswordTextChanged );
|
||||
@ -115,21 +121,7 @@ UsersPage::UsersPage( Config* config, QWidget* parent )
|
||||
onRootPasswordTextChanged( ui->textBoxRootPassword->text() );
|
||||
checkReady( isReady() );
|
||||
} );
|
||||
connect( ui->checkBoxReusePassword, &QCheckBox::stateChanged, this, [this]( const int checked ) {
|
||||
/* When "reuse" is checked, hide the fields for explicitly
|
||||
* entering the root password. However, if we're going to
|
||||
* disable the root password anyway, hide them all regardless of
|
||||
* the checkbox -- so when writeRoot is false, checked needs
|
||||
* to be true, to hide them all.
|
||||
*/
|
||||
const bool visible = m_config->writeRootPassword() ? !checked : false;
|
||||
ui->labelChooseRootPassword->setVisible( visible );
|
||||
ui->labelRootPassword->setVisible( visible );
|
||||
ui->labelRootPasswordError->setVisible( visible );
|
||||
ui->textBoxRootPassword->setVisible( visible );
|
||||
ui->textBoxVerifiedRootPassword->setVisible( visible );
|
||||
checkReady( isReady() );
|
||||
} );
|
||||
connect( ui->checkBoxReusePassword, &QCheckBox::stateChanged, this, &UsersPage::onReuseUserPasswordChanged );
|
||||
|
||||
connect( ui->textBoxFullName, &QLineEdit::textEdited, config, &Config::setFullName );
|
||||
connect( config, &Config::fullNameChanged, this, &UsersPage::onFullNameTextEdited );
|
||||
@ -147,13 +139,25 @@ UsersPage::UsersPage( Config* config, QWidget* parent )
|
||||
} );
|
||||
connect( config, &Config::autoLoginChanged, ui->checkBoxDoAutoLogin, &QCheckBox::setChecked );
|
||||
|
||||
ui->checkBoxReusePassword->setVisible( m_config->writeRootPassword() );
|
||||
ui->checkBoxReusePassword->setChecked( true );
|
||||
ui->checkBoxValidatePassword->setChecked( true );
|
||||
if ( m_config->writeRootPassword() )
|
||||
{
|
||||
connect( ui->checkBoxReusePassword, &QCheckBox::stateChanged, this, [this]( int checked ) {
|
||||
m_config->setReuseUserPasswordForRoot( checked != Qt::Unchecked );
|
||||
} );
|
||||
connect( config, &Config::reuseUserPasswordForRootChanged, ui->checkBoxReusePassword, &QCheckBox::setChecked );
|
||||
}
|
||||
|
||||
setPasswordCheckboxVisible( false );
|
||||
if ( m_config->permitWeakPasswords() )
|
||||
{
|
||||
connect( ui->checkBoxValidatePassword, &QCheckBox::stateChanged, this, [this]( int checked ) {
|
||||
m_config->setRequireStrongPasswords( checked != Qt::Unchecked );
|
||||
} );
|
||||
connect( config, &Config::requireStrongPasswordsChanged, ui->checkBoxValidatePassword, &QCheckBox::setChecked );
|
||||
}
|
||||
|
||||
CALAMARES_RETRANSLATE_SLOT( &UsersPage::retranslate );
|
||||
|
||||
onReuseUserPasswordChanged( m_config->reuseUserPasswordForRoot() );
|
||||
}
|
||||
|
||||
UsersPage::~UsersPage()
|
||||
@ -195,32 +199,6 @@ UsersPage::isReady() const
|
||||
return readyFields;
|
||||
}
|
||||
|
||||
QString
|
||||
UsersPage::getRootPassword() const
|
||||
{
|
||||
if ( m_config->writeRootPassword() )
|
||||
{
|
||||
if ( ui->checkBoxReusePassword->isChecked() )
|
||||
{
|
||||
return ui->textBoxUserPassword->text();
|
||||
}
|
||||
else
|
||||
{
|
||||
return ui->textBoxRootPassword->text();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
QPair< QString, QString >
|
||||
UsersPage::getUserPassword() const
|
||||
{
|
||||
return QPair< QString, QString >( m_config->loginName(), ui->textBoxUserPassword->text() );
|
||||
}
|
||||
|
||||
void
|
||||
UsersPage::fillGlobalStorage() const
|
||||
{
|
||||
@ -274,43 +252,26 @@ UsersPage::checkPasswordAcceptance( const QString& pw1, const QString& pw2, QLab
|
||||
{
|
||||
if ( pw1 != pw2 )
|
||||
{
|
||||
labelError( badge, message, tr( "Your passwords do not match!" ) );
|
||||
labelError( badge, message, tr( "Your passwords do not match!" ), Badness::Fatal );
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool failureIsFatal = ui->checkBoxValidatePassword->isChecked();
|
||||
bool failureFound = false;
|
||||
|
||||
if ( m_passwordChecksChanged )
|
||||
QString s;
|
||||
bool ok = m_config->isPasswordAcceptable( pw1, s );
|
||||
if ( !ok )
|
||||
{
|
||||
std::sort( m_passwordChecks.begin(), m_passwordChecks.end() );
|
||||
m_passwordChecksChanged = false;
|
||||
labelError( badge, message, s, Badness::Fatal );
|
||||
}
|
||||
|
||||
for ( auto pc : m_passwordChecks )
|
||||
else if ( !s.isEmpty() )
|
||||
{
|
||||
QString s = pc.filter( pw1 );
|
||||
|
||||
if ( !s.isEmpty() )
|
||||
{
|
||||
labelError( badge, message, s, failureIsFatal ? Badness::Fatal : Badness::Warning );
|
||||
failureFound = true;
|
||||
if ( failureIsFatal )
|
||||
{
|
||||
return false;
|
||||
labelError( badge, message, s, Badness::Warning );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !failureFound )
|
||||
else
|
||||
{
|
||||
labelOk( badge, message );
|
||||
}
|
||||
|
||||
// Here, if failureFound is true then we've found **warnings**,
|
||||
// which is ok to continue but the user should know.
|
||||
return true;
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
|
||||
@ -335,58 +296,24 @@ UsersPage::onRootPasswordTextChanged( const QString& )
|
||||
emit checkReady( isReady() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
UsersPage::setPasswordCheckboxVisible( bool visible )
|
||||
UsersPage::onReuseUserPasswordChanged( const int checked )
|
||||
{
|
||||
ui->checkBoxValidatePassword->setVisible( visible );
|
||||
}
|
||||
|
||||
void
|
||||
UsersPage::setValidatePasswordDefault( bool checked )
|
||||
{
|
||||
ui->checkBoxValidatePassword->setChecked( checked );
|
||||
emit checkReady( isReady() );
|
||||
}
|
||||
|
||||
void
|
||||
UsersPage::setReusePasswordDefault( bool checked )
|
||||
{
|
||||
ui->checkBoxReusePassword->setChecked( checked );
|
||||
emit checkReady( isReady() );
|
||||
}
|
||||
|
||||
void
|
||||
UsersPage::addPasswordCheck( const QString& key, const QVariant& value )
|
||||
{
|
||||
m_passwordChecksChanged = true;
|
||||
|
||||
if ( key == "minLength" )
|
||||
{
|
||||
add_check_minLength( m_passwordChecks, value );
|
||||
}
|
||||
else if ( key == "maxLength" )
|
||||
{
|
||||
add_check_maxLength( m_passwordChecks, value );
|
||||
}
|
||||
else if ( key == "nonempty" )
|
||||
{
|
||||
if ( value.toBool() )
|
||||
{
|
||||
m_passwordChecks.push_back(
|
||||
PasswordCheck( []() { return QCoreApplication::translate( "PWQ", "Password is empty" ); },
|
||||
[]( const QString& s ) { return !s.isEmpty(); },
|
||||
PasswordCheck::Weight( 1 ) ) );
|
||||
}
|
||||
}
|
||||
#ifdef CHECK_PWQUALITY
|
||||
else if ( key == "libpwquality" )
|
||||
{
|
||||
add_check_libpwquality( m_passwordChecks, value );
|
||||
}
|
||||
#endif // CHECK_PWQUALITY
|
||||
else
|
||||
{
|
||||
cWarning() << "Unknown password-check key" << key;
|
||||
}
|
||||
/* When "reuse" is checked, hide the fields for explicitly
|
||||
* entering the root password. However, if we're going to
|
||||
* disable the root password anyway, hide them all regardless of
|
||||
* the checkbox -- so when writeRoot is false, visible needs
|
||||
* to be false, to hide them all.
|
||||
*
|
||||
* In principle this is only connected when writeRootPassword is @c true,
|
||||
* but it is **always** called at least once in the constructor
|
||||
* to set up initial visibility.
|
||||
*/
|
||||
const bool visible = m_config->writeRootPassword() ? !checked : false;
|
||||
ui->labelChooseRootPassword->setVisible( visible );
|
||||
ui->labelRootPassword->setVisible( visible );
|
||||
ui->labelRootPasswordError->setVisible( visible );
|
||||
ui->textBoxRootPassword->setVisible( visible );
|
||||
ui->textBoxVerifiedRootPassword->setVisible( visible );
|
||||
checkReady( isReady() );
|
||||
}
|
||||
|
@ -24,8 +24,6 @@
|
||||
#ifndef USERSPAGE_H
|
||||
#define USERSPAGE_H
|
||||
|
||||
#include "CheckPWQuality.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class Config;
|
||||
@ -50,29 +48,13 @@ public:
|
||||
|
||||
void onActivate();
|
||||
|
||||
void setPasswordCheckboxVisible( bool visible );
|
||||
void setValidatePasswordDefault( bool checked );
|
||||
void setReusePasswordDefault( bool checked );
|
||||
|
||||
/** @brief Process entries in the passwordRequirements config entry
|
||||
*
|
||||
* Called once for each item in the config entry, which should
|
||||
* be a key-value pair. What makes sense as a value depends on
|
||||
* the key. Supported keys are documented in users.conf.
|
||||
*/
|
||||
void addPasswordCheck( const QString& key, const QVariant& value );
|
||||
|
||||
///@brief Root password, depends on settings, may be empty
|
||||
QString getRootPassword() const;
|
||||
///@brief User name and password
|
||||
QPair< QString, QString > getUserPassword() const;
|
||||
|
||||
protected slots:
|
||||
void onFullNameTextEdited( const QString& );
|
||||
void reportLoginNameStatus( const QString& );
|
||||
void reportHostNameStatus( const QString& );
|
||||
void onPasswordTextChanged( const QString& );
|
||||
void onRootPasswordTextChanged( const QString& );
|
||||
void onReuseUserPasswordChanged( const int );
|
||||
|
||||
signals:
|
||||
void checkReady( bool );
|
||||
@ -91,9 +73,6 @@ private:
|
||||
Ui::Page_UserSetup* ui;
|
||||
Config* m_config;
|
||||
|
||||
PasswordCheckList m_passwordChecks;
|
||||
bool m_passwordChecksChanged = false;
|
||||
|
||||
bool m_readyFullName;
|
||||
bool m_readyUsername;
|
||||
bool m_readyHostname;
|
||||
|
@ -34,28 +34,9 @@
|
||||
|
||||
CALAMARES_PLUGIN_FACTORY_DEFINITION( UsersViewStepFactory, registerPlugin< UsersViewStep >(); )
|
||||
|
||||
static const NamedEnumTable< SetHostNameJob::Action >&
|
||||
hostnameActions()
|
||||
{
|
||||
using Action = SetHostNameJob::Action;
|
||||
|
||||
// *INDENT-OFF*
|
||||
// clang-format off
|
||||
static const NamedEnumTable< Action > names {
|
||||
{ QStringLiteral( "none" ), Action::None },
|
||||
{ QStringLiteral( "etcfile" ), Action::EtcHostname },
|
||||
{ QStringLiteral( "hostnamed" ), Action::SystemdHostname }
|
||||
};
|
||||
// clang-format on
|
||||
// *INDENT-ON*
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
UsersViewStep::UsersViewStep( QObject* parent )
|
||||
: Calamares::ViewStep( parent )
|
||||
, m_widget( nullptr )
|
||||
, m_actions( SetHostNameJob::Action::None )
|
||||
, m_config( new Config( this ) )
|
||||
{
|
||||
emit nextStatusChanged( true );
|
||||
@ -151,14 +132,14 @@ UsersViewStep::onLeave()
|
||||
m_config->doAutoLogin(),
|
||||
m_config->defaultGroups() );
|
||||
|
||||
auto userPW = m_widget->getUserPassword();
|
||||
j = new SetPasswordJob( userPW.first, userPW.second );
|
||||
j = new SetPasswordJob( m_config->loginName(), m_config->userPassword() );
|
||||
m_jobs.append( Calamares::job_ptr( j ) );
|
||||
|
||||
j = new SetPasswordJob( "root", m_widget->getRootPassword() );
|
||||
j = new SetPasswordJob( "root", m_config->rootPassword() );
|
||||
m_jobs.append( Calamares::job_ptr( j ) );
|
||||
|
||||
j = new SetHostNameJob( m_config->hostName(), m_actions );
|
||||
// TODO: Config object should create jobs
|
||||
j = new SetHostNameJob( m_config->hostName(), m_config->hostNameActions() );
|
||||
m_jobs.append( Calamares::job_ptr( j ) );
|
||||
|
||||
m_widget->fillGlobalStorage();
|
||||
@ -168,42 +149,5 @@ UsersViewStep::onLeave()
|
||||
void
|
||||
UsersViewStep::setConfigurationMap( const QVariantMap& configurationMap )
|
||||
{
|
||||
// Create the widget, after all .. as long as writing configuration to the UI is needed
|
||||
(void)this->widget();
|
||||
using CalamaresUtils::getBool;
|
||||
|
||||
m_widget->setReusePasswordDefault( getBool( configurationMap, "doReusePassword", false ) );
|
||||
|
||||
if ( configurationMap.contains( "passwordRequirements" )
|
||||
&& configurationMap.value( "passwordRequirements" ).type() == QVariant::Map )
|
||||
{
|
||||
auto pr_checks( configurationMap.value( "passwordRequirements" ).toMap() );
|
||||
|
||||
for ( decltype( pr_checks )::const_iterator i = pr_checks.constBegin(); i != pr_checks.constEnd(); ++i )
|
||||
{
|
||||
m_widget->addPasswordCheck( i.key(), i.value() );
|
||||
}
|
||||
}
|
||||
|
||||
m_widget->setPasswordCheckboxVisible( getBool( configurationMap, "allowWeakPasswords", false ) );
|
||||
m_widget->setValidatePasswordDefault( !getBool( configurationMap, "allowWeakPasswordsDefault", false ) );
|
||||
|
||||
using Action = SetHostNameJob::Action;
|
||||
|
||||
QString hostnameActionString = CalamaresUtils::getString( configurationMap, "setHostname" );
|
||||
if ( hostnameActionString.isEmpty() )
|
||||
{
|
||||
hostnameActionString = QStringLiteral( "EtcFile" );
|
||||
}
|
||||
bool ok = false;
|
||||
auto hostnameAction = hostnameActions().find( hostnameActionString, ok );
|
||||
if ( !ok )
|
||||
{
|
||||
hostnameAction = Action::EtcHostname;
|
||||
}
|
||||
|
||||
Action hostsfileAction = getBool( configurationMap, "writeHostsFile", true ) ? Action::WriteEtcHosts : Action::None;
|
||||
m_actions = hostsfileAction | hostnameAction;
|
||||
|
||||
m_config->setConfigurationMap( configurationMap );
|
||||
}
|
||||
|
@ -20,8 +20,6 @@
|
||||
#ifndef USERSPAGEPLUGIN_H
|
||||
#define USERSPAGEPLUGIN_H
|
||||
|
||||
#include "SetHostNameJob.h"
|
||||
|
||||
#include "DllMacro.h"
|
||||
#include "utils/PluginFactory.h"
|
||||
#include "viewpages/ViewStep.h"
|
||||
@ -61,8 +59,6 @@ private:
|
||||
UsersPage* m_widget;
|
||||
QList< Calamares::job_ptr > m_jobs;
|
||||
|
||||
SetHostNameJob::Actions m_actions;
|
||||
|
||||
Config* m_config;
|
||||
};
|
||||
|
||||
|
@ -138,4 +138,5 @@ setHostname: EtcFile
|
||||
|
||||
# Should /etc/hosts be written with a hostname for this machine
|
||||
# (also adds localhost and some ipv6 standard entries).
|
||||
# Defaults to *true*.
|
||||
writeHostsFile: true
|
||||
|
Loading…
Reference in New Issue
Block a user