Merge branch 'master' into issue-1152

This commit is contained in:
Adriaan de Groot 2019-06-16 13:11:03 +02:00
commit 075f0787f9
46 changed files with 864 additions and 561 deletions

33
.clang-format Normal file
View File

@ -0,0 +1,33 @@
---
BasedOnStyle: WebKit
AlignAfterOpenBracket: Align
AllowAllParametersOfDeclarationOnNextLine: 'false'
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: 'false'
AllowShortLoopsOnASingleLine: 'false'
AlwaysBreakAfterDefinitionReturnType: All
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: 'false'
BinPackParameters: 'false'
BreakBeforeBraces: Allman
BreakBeforeTernaryOperators: 'true'
BreakConstructorInitializers: BeforeComma
ColumnLimit: 120
Cpp11BracedListStyle: 'false'
FixNamespaceComments: 'true'
IncludeBlocks: Preserve
IndentWidth: '4'
MaxEmptyLinesToKeep: '2'
NamespaceIndentation: Inner
PointerAlignment: Left
ReflowComments: 'false'
SortIncludes: 'true'
SpaceAfterCStyleCast: 'false'
SpacesBeforeTrailingComments: '2'
SpacesInAngles: 'true'
SpacesInParentheses: 'true'
SpacesInSquareBrackets: 'true'
Standard: Cpp11
...

30
CHANGES
View File

@ -3,7 +3,31 @@ 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 changelog -- this log starts with version 3.2.0. The release notes on the
website will have to do for older versions. website will have to do for older versions.
# 3.2.9 (unreleased) # # 3.2.10 (unreleased) #
This release contains contributions from (alphabetically by first name):
## Core ##
- With this release, option *WITH_PYTHONQT* changes default to **off**.
There does not seem to be any serious use of the PythonQt API and
the UI opportunities it offers, so begin the process of deprecating
and removing that. Sometime in the future, QML pages will fill the
gap for easily-prototyped-yet-slick UI elements.
- A crash when no *finished* page (or rather, no page at all) is
configured after the last *exec* section of the sequence has been
solved. The *finished* page can be left out (but then you don't get
the restart-now functionality). #1168
## Modules ##
- *partition* Now has its own setting for *requiredStorage*, duplicating
the same setting in the *welcome* module. This is useful for
configurations where no *welcome* module is used, but a minimum
size must be checked anyway. #1169
# 3.2.9 (2019-06-03) #
This release contains contributions from (alphabetically by first name): This release contains contributions from (alphabetically by first name):
- Kevin Kofler - Kevin Kofler
@ -21,7 +45,9 @@ milestone for details.
- *branding* allows the use of FreeDesktop.org icon names for the - *branding* allows the use of FreeDesktop.org icon names for the
*productLogo* and *productIcon* keys. If a file is named there, then *productLogo* and *productIcon* keys. If a file is named there, then
the file is used, and otherwise the icon is looked up in the current the file is used, and otherwise the icon is looked up in the current
theme. theme. #1160
- *packages* On Arch, with the `pacman` package manager, avoid a hang
during system update. #1154
- *welcome* allows a custom image path or icon name to be set for the - *welcome* allows a custom image path or icon name to be set for the
language-selection drop-down (instead of the international standard one). language-selection drop-down (instead of the international standard one).

View File

@ -37,7 +37,7 @@
cmake_minimum_required( VERSION 3.2 FATAL_ERROR ) cmake_minimum_required( VERSION 3.2 FATAL_ERROR )
project( CALAMARES project( CALAMARES
VERSION 3.2.9 VERSION 3.2.10
LANGUAGES C CXX ) LANGUAGES C CXX )
set( CALAMARES_VERSION_RC 1 ) # Set to 0 during release cycle, 1 during development set( CALAMARES_VERSION_RC 1 ) # Set to 0 during release cycle, 1 during development
@ -48,7 +48,7 @@ option( INSTALL_CONFIG "Install configuration files" OFF )
option( INSTALL_POLKIT "Install Polkit configuration" ON ) option( INSTALL_POLKIT "Install Polkit configuration" ON )
option( BUILD_TESTING "Build the testing tree." ON ) option( BUILD_TESTING "Build the testing tree." ON )
option( WITH_PYTHON "Enable Python modules API (requires Boost.Python)." ON ) option( WITH_PYTHON "Enable Python modules API (requires Boost.Python)." ON )
option( WITH_PYTHONQT "Enable next generation Python modules API (experimental, requires PythonQt)." ON ) option( WITH_PYTHONQT "Enable next generation Python modules API (experimental, requires PythonQt)." OFF )
option( WITH_KF5Crash "Enable crash reporting with KCrash." ON ) option( WITH_KF5Crash "Enable crash reporting with KCrash." ON )
@ -104,12 +104,12 @@ set( CALAMARES_DESCRIPTION_SUMMARY
# checks for new languages and misspelled ones are done (that is, # checks for new languages and misspelled ones are done (that is,
# copy these four lines to four backup lines, add "p", and then update # copy these four lines to four backup lines, add "p", and then update
# the original four lines with the current translations). # the original four lines with the current translations).
set( _tx_complete ast ca cs_CZ da de fr hr ja lt pl pt_BR pt_PT set( _tx_complete ca cs_CZ da de fr he hr hu ko lt pt_BR sq tr_TR
tr_TR zh_TW ) zh_TW )
set( _tx_good bg en_GB es es_MX et gl he hi hu id it_IT ro ru sk sq set( _tx_good ast en_GB es es_MX et gl id it_IT ja nl pl pt_PT ro
zh_CN ) ru sk zh_CN )
set( _tx_ok ar el es_PR eu fi_FI is ko mr nb nl sl sr set( _tx_ok ar bg el es_PR eu fi_FI hi is mr nb sl sr sr@latin sv
sr@latin sv th uk ) th uk )
set( _tx_bad be eo fa fr_CH gu kk kn lo mk ne_NP ur uz ) set( _tx_bad be eo fa fr_CH gu kk kn lo mk ne_NP ur uz )

View File

@ -56,7 +56,7 @@ some PEP8 guidelines.
* For pointer and reference variable declarations, put a space before the variable name * For pointer and reference variable declarations, put a space before the variable name
and no space between the type and the `*` or `&`, e.g. `int* p`. and no space between the type and the `*` or `&`, e.g. `int* p`.
* `for`, `if`, `else`, `while` and similar statements put the braces on the next line, * `for`, `if`, `else`, `while` and similar statements put the braces on the next line,
if the following block is more than one statement. Use no braces for single statements. if the following block is more than one statement. Always use braces.
* Function and class definitions have their braces on separate lines. * Function and class definitions have their braces on separate lines.
* A function implementation's return type is on its own line. * A function implementation's return type is on its own line.
* `CamelCase.{cpp,h}` style file names. * `CamelCase.{cpp,h}` style file names.
@ -86,9 +86,13 @@ MyClass::myMethod( QStringList list, const QString& name )
} }
``` ```
You can use the `ci/calamaresstyle` script to run You can use `clang-format` (version 7) to have Calamares sources formatted
[astyle](http://astyle.sf.net) on your code and have it formatted the right the right way. There is a `.clang-format` file that specifies the details.
way. In general:
```
$ clang-format-7 -i -style=file <files>
```
`
**NOTE:** An .editorconfig file is included to assist with formatting. In **NOTE:** An .editorconfig file is included to assist with formatting. In
order to take advantage of this functionality you will need to acquire the order to take advantage of this functionality you will need to acquire the
@ -179,15 +183,19 @@ connect( m_moduleManager, &Calamares::ModuleManager::modulesLoaded, [this]
Debugging Debugging
--------- ---------
Use `cDebug()` and `cLog()` from `utils/Logger.h`. You can pass a debug-level to Use `cDebug()` from `utils/Logger.h`. You can pass a debug-level to the
either macro (1 is debugging, higher is less important). Use `cLog()` for warning macro (6 is debugging, higher is less important). Use `cWarning()` for warning
messages. It is recommended to add *WARNING* as the first part of a warning messages (equivalent to level 2) and `cError()` for errors (level 1). Warnings
message. and errors will add relevant text automatically. See `libcalamares/utils/Logger.h`
for details.
For log messages that are continued across multiple calls to `cDebug()`, For log messages that are continued across multiple calls to `cDebug()`,
in particular listing things, conventional formatting is as follows: in particular listing things, conventional formatting is as follows:
* End the first debug message with ` ..` * End the first debug message with ` ..`
* Indent following lines with ` ..` * Start the next debug message by outputting `Logger::SubEntry`
For single-outputs that need to be split across multiplt lines,
output `Logger::Continuation`.
Commit Messages Commit Messages

View File

@ -5,7 +5,7 @@ indent=spaces=4
# Brackets # Brackets
style=break style=break
remove-brackets # Remove brackets on single-line `if` and `for` (requires astyle 2.04) add-brackets
# Spaces # Spaces
pad-paren-in pad-paren-in

View File

@ -1,6 +1,42 @@
#!/bin/sh #!/bin/sh
#
# Calls astyle with settings matching Calamares coding style # Calls astyle with settings matching Calamares coding style
# Requires astyle >= 2.04 # Requires astyle >= 2.04 and clang-format-7
#
# You can pass in directory names, in which case the files
# in that directory (NOT below it) are processed.
#
set -e set -e
astyle --options=$(dirname $0)/astylerc "$@" AS=$( which astyle )
CF=$( which clang-format-7 )
test -n "$AS" || { echo "! No astyle found in PATH"; exit 1 ; }
test -n "$CF" || { echo "! No clang-format-7 found in PATH"; exit 1 ; }
test -x "$AS" || { echo "! $AS is not executable."; exit 1 ; }
test -x "$CF" || { echo "! $CF is not executable."; exit 1 ; }
any_dirs=no
for d in "$@"
do
test -d "$d" && any_dirs=yes
done
style_some()
{
$AS --options=$(dirname $0)/astylerc --quiet "$@"
$CF -i -style=file "$@"
}
if test "x$any_dirs" = "xyes" ; then
for d in "$@"
do
if test -d "$@" ; then
style_some $( find "$d" -maxdepth 1 -type f -name '*.cpp' -o -name '*.h' )
else
style_some "$d"
fi
done
else
style_some "$@"
fi

View File

@ -15,12 +15,12 @@ showReleaseNotesUrl: true
# that are checked. They may not match with the actual requirements # that are checked. They may not match with the actual requirements
# imposed by other modules in the system. # imposed by other modules in the system.
requirements: requirements:
# Amount of available disk, in GB. Floating-point is allowed here. # Amount of available disk, in GiB. Floating-point is allowed here.
# Note that this does not account for *usable* disk, so it is possible # Note that this does not account for *usable* disk, so it is possible
# to pass this requirement, yet have no space to install to. # to pass this requirement, yet have no space to install to.
requiredStorage: 5.5 requiredStorage: 5.5
# Amount of available RAM, in GB. Floating-point is allowed here. # Amount of available RAM, in GiB. Floating-point is allowed here.
requiredRam: 1.0 requiredRam: 1.0
# To check for internet connectivity, Calamares does a HTTP GET # To check for internet connectivity, Calamares does a HTTP GET

View File

@ -854,17 +854,17 @@ El instalador terminará y se perderán todos los cambios.</translation>
<location filename="../src/modules/partition/jobs/DeactivateVolumeGroupJob.cpp" line="34"/> <location filename="../src/modules/partition/jobs/DeactivateVolumeGroupJob.cpp" line="34"/>
<location filename="../src/modules/partition/jobs/DeactivateVolumeGroupJob.cpp" line="48"/> <location filename="../src/modules/partition/jobs/DeactivateVolumeGroupJob.cpp" line="48"/>
<source>Deactivate volume group named %1.</source> <source>Deactivate volume group named %1.</source>
<translation type="unfinished"/> <translation>Desactivar el grupo de volúmenes llamado%1.</translation>
</message> </message>
<message> <message>
<location filename="../src/modules/partition/jobs/DeactivateVolumeGroupJob.cpp" line="41"/> <location filename="../src/modules/partition/jobs/DeactivateVolumeGroupJob.cpp" line="41"/>
<source>Deactivate volume group named &lt;strong&gt;%1&lt;/strong&gt;.</source> <source>Deactivate volume group named &lt;strong&gt;%1&lt;/strong&gt;.</source>
<translation type="unfinished"/> <translation>Desactivar el grupo de volúmenes llamado&lt;strong&gt;% 1&lt;/strong&gt;.</translation>
</message> </message>
<message> <message>
<location filename="../src/modules/partition/jobs/DeactivateVolumeGroupJob.cpp" line="61"/> <location filename="../src/modules/partition/jobs/DeactivateVolumeGroupJob.cpp" line="61"/>
<source>The installer failed to deactivate a volume group named %1.</source> <source>The installer failed to deactivate a volume group named %1.</source>
<translation type="unfinished"/> <translation>El instalador no pudo desactivar un grupo de volúmenes llamado%1.</translation>
</message> </message>
</context> </context>
<context> <context>
@ -1098,7 +1098,7 @@ El instalador terminará y se perderán todos los cambios.</translation>
<message> <message>
<location filename="../src/modules/finished/FinishedPage.ui" line="95"/> <location filename="../src/modules/finished/FinishedPage.ui" line="95"/>
<source>&lt;Restart checkbox tooltip&gt;</source> <source>&lt;Restart checkbox tooltip&gt;</source>
<translation type="unfinished"/> <translation>&lt;Restart checkbox tooltip&gt;</translation>
</message> </message>
<message> <message>
<location filename="../src/modules/finished/FinishedPage.ui" line="98"/> <location filename="../src/modules/finished/FinishedPage.ui" line="98"/>
@ -1108,12 +1108,12 @@ El instalador terminará y se perderán todos los cambios.</translation>
<message> <message>
<location filename="../src/modules/finished/FinishedPage.cpp" line="54"/> <location filename="../src/modules/finished/FinishedPage.cpp" line="54"/>
<source>&lt;h1&gt;All done.&lt;/h1&gt;&lt;br/&gt;%1 has been set up on your computer.&lt;br/&gt;You may now start using your new system.</source> <source>&lt;h1&gt;All done.&lt;/h1&gt;&lt;br/&gt;%1 has been set up on your computer.&lt;br/&gt;You may now start using your new system.</source>
<translation type="unfinished"/> <translation>&lt;h1&gt;Todo listo.&lt;/h1&gt;&lt;br/&gt;% 1 se ha configurado en su computadora. &lt;br/&gt;Ahora puede comenzar a usar su nuevo sistema.</translation>
</message> </message>
<message> <message>
<location filename="../src/modules/finished/FinishedPage.cpp" line="58"/> <location filename="../src/modules/finished/FinishedPage.cpp" line="58"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;When this box is checked, your system will restart immediately when you click on &lt;span style=&quot;font-style:italic;&quot;&gt;Done&lt;/span&gt; or close the setup program.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source> <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;When this box is checked, your system will restart immediately when you click on &lt;span style=&quot;font-style:italic;&quot;&gt;Done&lt;/span&gt; or close the setup program.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"/> <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Cuando esta casilla está marcada, su sistema se reiniciará inmediatamente cuando haga clic en &lt;span style=&quot;font-style:italic;&quot;&gt;Listo&lt;/span&gt; o cierre el programa de instalación.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message> </message>
<message> <message>
<location filename="../src/modules/finished/FinishedPage.cpp" line="66"/> <location filename="../src/modules/finished/FinishedPage.cpp" line="66"/>

File diff suppressed because it is too large Load Diff

View File

@ -347,7 +347,7 @@ msgstr ""
#: src/modules/openrcdmcryptcfg/main.py:34 #: src/modules/openrcdmcryptcfg/main.py:34
msgid "Configuring OpenRC dmcrypt service." msgid "Configuring OpenRC dmcrypt service."
msgstr "" msgstr "Configurando'l serviciu dmcrypt d'OpenRC."
#: src/modules/luksbootkeyfile/main.py:35 #: src/modules/luksbootkeyfile/main.py:35
msgid "Configuring LUKS key file." msgid "Configuring LUKS key file."

View File

@ -88,25 +88,27 @@ msgstr ""
#: src/modules/umount/main.py:40 #: src/modules/umount/main.py:40
msgid "Unmount file systems." msgid "Unmount file systems."
msgstr "" msgstr "Irrota tiedostojärjestelmät käytöstä."
#: src/modules/unpackfs/main.py:41 #: src/modules/unpackfs/main.py:41
msgid "Filling up filesystems." msgid "Filling up filesystems."
msgstr "" msgstr "Paikannetaan tiedostojärjestelmiä."
#: src/modules/unpackfs/main.py:159 #: src/modules/unpackfs/main.py:159
msgid "rsync failed with error code {}." msgid "rsync failed with error code {}."
msgstr "" msgstr "rsync epäonnistui virhekoodilla {}."
#: src/modules/unpackfs/main.py:220 src/modules/unpackfs/main.py:238 #: src/modules/unpackfs/main.py:220 src/modules/unpackfs/main.py:238
msgid "Failed to unpack image \"{}\"" msgid "Failed to unpack image \"{}\""
msgstr "" msgstr "Kuvan purkaminen epäonnistui \"{}\""
#: src/modules/unpackfs/main.py:221 #: src/modules/unpackfs/main.py:221
msgid "" msgid ""
"Failed to find unsquashfs, make sure you have the squashfs-tools package " "Failed to find unsquashfs, make sure you have the squashfs-tools package "
"installed" "installed"
msgstr "" msgstr ""
"Ei löytynyt unsquashfs, varmista, että sinulla on squashfs-tools paketti "
"asennettuna"
#: src/modules/unpackfs/main.py:320 #: src/modules/unpackfs/main.py:320
msgid "No mount point for root partition" msgid "No mount point for root partition"
@ -118,7 +120,7 @@ msgstr ""
#: src/modules/unpackfs/main.py:326 #: src/modules/unpackfs/main.py:326
msgid "Bad mount point for root partition" msgid "Bad mount point for root partition"
msgstr "" msgstr "Huono kiinnityspiste root-osioon"
#: src/modules/unpackfs/main.py:327 #: src/modules/unpackfs/main.py:327
msgid "rootMountPoint is \"{}\", which does not exist, doing nothing" msgid "rootMountPoint is \"{}\", which does not exist, doing nothing"
@ -127,7 +129,7 @@ msgstr ""
#: src/modules/unpackfs/main.py:340 src/modules/unpackfs/main.py:347 #: src/modules/unpackfs/main.py:340 src/modules/unpackfs/main.py:347
#: src/modules/unpackfs/main.py:352 #: src/modules/unpackfs/main.py:352
msgid "Bad unsquash configuration" msgid "Bad unsquash configuration"
msgstr "" msgstr "Huono epäpuhdas kokoonpano"
#: src/modules/unpackfs/main.py:341 #: src/modules/unpackfs/main.py:341
msgid "The filesystem for \"{}\" ({}) is not supported" msgid "The filesystem for \"{}\" ({}) is not supported"
@ -167,19 +169,19 @@ msgstr ""
#: src/modules/displaymanager/main.py:602 #: src/modules/displaymanager/main.py:602
msgid "Cannot configure LightDM" msgid "Cannot configure LightDM"
msgstr "" msgstr "LightDM määritysvirhe"
#: src/modules/displaymanager/main.py:603 #: src/modules/displaymanager/main.py:603
msgid "No LightDM greeter installed." msgid "No LightDM greeter installed."
msgstr "" msgstr "LightDM ei ole asennettu."
#: src/modules/displaymanager/main.py:634 #: src/modules/displaymanager/main.py:634
msgid "Cannot write SLIM configuration file" msgid "Cannot write SLIM configuration file"
msgstr "" msgstr "SLIM-määritystiedostoa ei voi kirjoittaa"
#: src/modules/displaymanager/main.py:635 #: src/modules/displaymanager/main.py:635
msgid "SLIM config file {!s} does not exist" msgid "SLIM config file {!s} does not exist"
msgstr "" msgstr "SLIM-määritystiedostoa {!s} ei ole olemassa"
#: src/modules/displaymanager/main.py:750 #: src/modules/displaymanager/main.py:750
msgid "No display managers selected for the displaymanager module." msgid "No display managers selected for the displaymanager module."
@ -193,11 +195,11 @@ msgstr ""
#: src/modules/displaymanager/main.py:831 #: src/modules/displaymanager/main.py:831
msgid "Display manager configuration was incomplete" msgid "Display manager configuration was incomplete"
msgstr "" msgstr "Näytönhallinnan kokoonpano oli puutteellinen"
#: src/modules/initcpiocfg/main.py:36 #: src/modules/initcpiocfg/main.py:36
msgid "Configuring mkinitcpio." msgid "Configuring mkinitcpio."
msgstr "" msgstr "Määritetään mkinitcpio."
#: src/modules/initcpiocfg/main.py:192 #: src/modules/initcpiocfg/main.py:192
#: src/modules/luksopenswaphookcfg/main.py:100 #: src/modules/luksopenswaphookcfg/main.py:100
@ -213,7 +215,7 @@ msgstr ""
#: src/modules/initcpio/main.py:47 #: src/modules/initcpio/main.py:47
msgid "Process Failed" msgid "Process Failed"
msgstr "" msgstr "Prosessi epäonnistui"
#: src/modules/initcpio/main.py:48 #: src/modules/initcpio/main.py:48
msgid "" msgid ""
@ -227,7 +229,7 @@ msgstr ""
#: src/modules/rawfs/main.py:35 #: src/modules/rawfs/main.py:35
msgid "Installing data." msgid "Installing data."
msgstr "" msgstr "Asennetaan tietoja."
#: src/modules/services-openrc/main.py:38 #: src/modules/services-openrc/main.py:38
msgid "Configure OpenRC services" msgid "Configure OpenRC services"

View File

@ -16,27 +16,27 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Calamares. If not, see <http://www.gnu.org/licenses/>. * along with Calamares. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <QDesktopWidget>
#include "CalamaresApplication.h" #include "CalamaresApplication.h"
#include "CalamaresConfig.h" #include "CalamaresConfig.h"
#include "CalamaresWindow.h"
#include "CalamaresVersion.h" #include "CalamaresVersion.h"
#include "progresstree/ProgressTreeView.h" #include "CalamaresWindow.h"
#include "progresstree/ProgressTreeModel.h" #include "progresstree/ProgressTreeModel.h"
#include "progresstree/ProgressTreeView.h"
#include "Branding.h"
#include "JobQueue.h"
#include "Settings.h"
#include "ViewManager.h"
#include "modulesystem/ModuleManager.h" #include "modulesystem/ModuleManager.h"
#include "utils/CalamaresUtilsGui.h" #include "utils/CalamaresUtilsGui.h"
#include "utils/CalamaresUtilsSystem.h" #include "utils/CalamaresUtilsSystem.h"
#include "utils/Dirs.h" #include "utils/Dirs.h"
#include "utils/Logger.h" #include "utils/Logger.h"
#include "utils/Retranslator.h" #include "utils/Retranslator.h"
#include "JobQueue.h"
#include "Branding.h"
#include "Settings.h"
#include "viewpages/ViewStep.h" #include "viewpages/ViewStep.h"
#include "ViewManager.h"
#include <QDesktopWidget>
#include <QDir> #include <QDir>
#include <QFileInfo> #include <QFileInfo>
@ -77,12 +77,11 @@ CalamaresApplication::init()
initSettings(); initSettings();
initBranding(); initBranding();
setWindowIcon( QIcon( Calamares::Branding::instance()-> setWindowIcon( QIcon( Calamares::Branding::instance()->imagePath( Calamares::Branding::ProductIcon ) ) );
imagePath( Calamares::Branding::ProductIcon ) ) );
cDebug() << "STARTUP: initQmlPath, initSettings, initBranding done"; cDebug() << "STARTUP: initQmlPath, initSettings, initBranding done";
initModuleManager(); //also shows main window initModuleManager(); //also shows main window
cDebug() << "STARTUP: initModuleManager: module init started"; cDebug() << "STARTUP: initModuleManager: module init started";
} }
@ -91,15 +90,7 @@ CalamaresApplication::init()
CalamaresApplication::~CalamaresApplication() CalamaresApplication::~CalamaresApplication()
{ {
cDebug( Logger::LOGVERBOSE ) << "Shutting down Calamares..."; cDebug( Logger::LOGVERBOSE ) << "Shutting down Calamares...";
cDebug( Logger::LOGVERBOSE ) << Logger::SubEntry << "Finished shutdown.";
// if ( JobQueue::instance() )
// JobQueue::instance()->stop();
// delete m_mainwindow;
// delete JobQueue::instance();
cDebug( Logger::LOGVERBOSE ) << "Finished shutdown.";
} }
@ -138,14 +129,20 @@ qmlDirCandidates( bool assumeBuilddir )
QStringList qmlDirs; QStringList qmlDirs;
if ( CalamaresUtils::isAppDataDirOverridden() ) if ( CalamaresUtils::isAppDataDirOverridden() )
{
qmlDirs << CalamaresUtils::appDataDir().absoluteFilePath( QML ); qmlDirs << CalamaresUtils::appDataDir().absoluteFilePath( QML );
}
else else
{ {
if ( assumeBuilddir ) if ( assumeBuilddir )
{
qmlDirs << QDir::current().absoluteFilePath( "src/qml" ); // In build-dir qmlDirs << QDir::current().absoluteFilePath( "src/qml" ); // In build-dir
}
if ( CalamaresUtils::haveExtraDirs() ) if ( CalamaresUtils::haveExtraDirs() )
for ( auto s : CalamaresUtils::extraDataDirs() ) for ( auto s : CalamaresUtils::extraDataDirs() )
{
qmlDirs << ( s + QML ); qmlDirs << ( s + QML );
}
qmlDirs << CalamaresUtils::appDataDir().absoluteFilePath( QML ); qmlDirs << CalamaresUtils::appDataDir().absoluteFilePath( QML );
} }
@ -160,14 +157,20 @@ settingsFileCandidates( bool assumeBuilddir )
QStringList settingsPaths; QStringList settingsPaths;
if ( CalamaresUtils::isAppDataDirOverridden() ) if ( CalamaresUtils::isAppDataDirOverridden() )
{
settingsPaths << CalamaresUtils::appDataDir().absoluteFilePath( settings ); settingsPaths << CalamaresUtils::appDataDir().absoluteFilePath( settings );
}
else else
{ {
if ( assumeBuilddir ) if ( assumeBuilddir )
{
settingsPaths << QDir::current().absoluteFilePath( settings ); settingsPaths << QDir::current().absoluteFilePath( settings );
}
if ( CalamaresUtils::haveExtraDirs() ) if ( CalamaresUtils::haveExtraDirs() )
for ( auto s : CalamaresUtils::extraConfigDirs() ) for ( auto s : CalamaresUtils::extraConfigDirs() )
{
settingsPaths << ( s + settings ); settingsPaths << ( s + settings );
}
settingsPaths << CMAKE_INSTALL_FULL_SYSCONFDIR "/calamares/settings.conf"; // String concat settingsPaths << CMAKE_INSTALL_FULL_SYSCONFDIR "/calamares/settings.conf"; // String concat
settingsPaths << CalamaresUtils::appDataDir().absoluteFilePath( settings ); settingsPaths << CalamaresUtils::appDataDir().absoluteFilePath( settings );
} }
@ -181,16 +184,22 @@ brandingFileCandidates( bool assumeBuilddir, const QString& brandingFilename )
{ {
QStringList brandingPaths; QStringList brandingPaths;
if ( CalamaresUtils::isAppDataDirOverridden() ) if ( CalamaresUtils::isAppDataDirOverridden() )
{
brandingPaths << CalamaresUtils::appDataDir().absoluteFilePath( brandingFilename ); brandingPaths << CalamaresUtils::appDataDir().absoluteFilePath( brandingFilename );
}
else else
{ {
if ( assumeBuilddir ) if ( assumeBuilddir )
{
brandingPaths << ( QDir::currentPath() + QStringLiteral( "/src/" ) + brandingFilename ); brandingPaths << ( QDir::currentPath() + QStringLiteral( "/src/" ) + brandingFilename );
}
if ( CalamaresUtils::haveExtraDirs() ) if ( CalamaresUtils::haveExtraDirs() )
for ( auto s : CalamaresUtils::extraDataDirs() ) for ( auto s : CalamaresUtils::extraDataDirs() )
{
brandingPaths << ( s + brandingFilename ); brandingPaths << ( s + brandingFilename );
}
brandingPaths << QDir( CMAKE_INSTALL_FULL_SYSCONFDIR "/calamares/" ).absoluteFilePath( brandingFilename ); brandingPaths << QDir( CMAKE_INSTALL_FULL_SYSCONFDIR "/calamares/" ).absoluteFilePath( brandingFilename );
brandingPaths << CalamaresUtils::appDataDir().absoluteFilePath( brandingFilename); brandingPaths << CalamaresUtils::appDataDir().absoluteFilePath( brandingFilename );
} }
return brandingPaths; return brandingPaths;
@ -218,11 +227,15 @@ CalamaresApplication::initQmlPath()
if ( !found || !importPath.exists() || !importPath.isReadable() ) if ( !found || !importPath.exists() || !importPath.isReadable() )
{ {
cError() << "Cowardly refusing to continue startup without a QML directory." cError() << "Cowardly refusing to continue startup without a QML directory."
<< Logger::DebugList( qmlDirCandidatesByPriority ); << Logger::DebugList( qmlDirCandidatesByPriority );
if ( CalamaresUtils::isAppDataDirOverridden() ) if ( CalamaresUtils::isAppDataDirOverridden() )
{
cError() << "FATAL: explicitly configured application data directory is missing qml/"; cError() << "FATAL: explicitly configured application data directory is missing qml/";
}
else else
{
cError() << "FATAL: none of the expected QML paths exist."; cError() << "FATAL: none of the expected QML paths exist.";
}
::exit( EXIT_FAILURE ); ::exit( EXIT_FAILURE );
} }
@ -253,11 +266,15 @@ CalamaresApplication::initSettings()
if ( !found || !settingsFile.exists() || !settingsFile.isReadable() ) if ( !found || !settingsFile.exists() || !settingsFile.isReadable() )
{ {
cError() << "Cowardly refusing to continue startup without settings." cError() << "Cowardly refusing to continue startup without settings."
<< Logger::DebugList( settingsFileCandidatesByPriority ); << Logger::DebugList( settingsFileCandidatesByPriority );
if ( CalamaresUtils::isAppDataDirOverridden() ) if ( CalamaresUtils::isAppDataDirOverridden() )
{
cError() << "FATAL: explicitly configured application data directory is missing settings.conf"; cError() << "FATAL: explicitly configured application data directory is missing settings.conf";
}
else else
{
cError() << "FATAL: none of the expected configuration file paths exist."; cError() << "FATAL: none of the expected configuration file paths exist.";
}
::exit( EXIT_FAILURE ); ::exit( EXIT_FAILURE );
} }
@ -281,7 +298,7 @@ CalamaresApplication::initBranding()
} }
QString brandingDescriptorSubpath = QString( "branding/%1/branding.desc" ).arg( brandingComponentName ); QString brandingDescriptorSubpath = QString( "branding/%1/branding.desc" ).arg( brandingComponentName );
QStringList brandingFileCandidatesByPriority = brandingFileCandidates( isDebug(), brandingDescriptorSubpath); QStringList brandingFileCandidatesByPriority = brandingFileCandidates( isDebug(), brandingDescriptorSubpath );
QFileInfo brandingFile; QFileInfo brandingFile;
bool found = false; bool found = false;
@ -300,11 +317,15 @@ CalamaresApplication::initBranding()
if ( !found || !brandingFile.exists() || !brandingFile.isReadable() ) if ( !found || !brandingFile.exists() || !brandingFile.isReadable() )
{ {
cError() << "Cowardly refusing to continue startup without branding." cError() << "Cowardly refusing to continue startup without branding."
<< Logger::DebugList( brandingFileCandidatesByPriority ); << Logger::DebugList( brandingFileCandidatesByPriority );
if ( CalamaresUtils::isAppDataDirOverridden() ) if ( CalamaresUtils::isAppDataDirOverridden() )
{
cError() << "FATAL: explicitly configured application data directory is missing" << brandingComponentName; cError() << "FATAL: explicitly configured application data directory is missing" << brandingComponentName;
}
else else
{
cError() << "FATAL: none of the expected branding descriptor file paths exist."; cError() << "FATAL: none of the expected branding descriptor file paths exist.";
}
::exit( EXIT_FAILURE ); ::exit( EXIT_FAILURE );
} }
@ -315,10 +336,8 @@ CalamaresApplication::initBranding()
void void
CalamaresApplication::initModuleManager() CalamaresApplication::initModuleManager()
{ {
m_moduleManager = new Calamares::ModuleManager( m_moduleManager = new Calamares::ModuleManager( Calamares::Settings::instance()->modulesSearchPaths(), this );
Calamares::Settings::instance()->modulesSearchPaths(), this ); connect( m_moduleManager, &Calamares::ModuleManager::initDone, this, &CalamaresApplication::initView );
connect( m_moduleManager, &Calamares::ModuleManager::initDone,
this, &CalamaresApplication::initView );
m_moduleManager->init(); m_moduleManager->init();
} }
@ -330,18 +349,14 @@ CalamaresApplication::initView()
initJobQueue(); initJobQueue();
cDebug() << "STARTUP: initJobQueue done"; cDebug() << "STARTUP: initJobQueue done";
m_mainwindow = new CalamaresWindow(); //also creates ViewManager m_mainwindow = new CalamaresWindow(); //also creates ViewManager
connect( m_moduleManager, &Calamares::ModuleManager::modulesLoaded, connect( m_moduleManager, &Calamares::ModuleManager::modulesLoaded, this, &CalamaresApplication::initViewSteps );
this, &CalamaresApplication::initViewSteps ); connect( m_moduleManager, &Calamares::ModuleManager::modulesFailed, this, &CalamaresApplication::initFailed );
connect( m_moduleManager, &Calamares::ModuleManager::modulesFailed,
this, &CalamaresApplication::initFailed );
m_moduleManager->loadModules(); m_moduleManager->loadModules();
m_mainwindow->move( m_mainwindow->move( this->desktop()->availableGeometry().center() - m_mainwindow->rect().center() );
this->desktop()->availableGeometry().center() -
m_mainwindow->rect().center() );
cDebug() << "STARTUP: CalamaresWindow created; loadModules started"; cDebug() << "STARTUP: CalamaresWindow created; loadModules started";
} }
@ -358,7 +373,9 @@ CalamaresApplication::initViewSteps()
m_mainwindow->showMaximized(); m_mainwindow->showMaximized();
} }
else else
{
m_mainwindow->show(); m_mainwindow->show();
}
ProgressTreeModel* m = new ProgressTreeModel( nullptr ); ProgressTreeModel* m = new ProgressTreeModel( nullptr );
ProgressTreeView::instance()->setModel( m ); ProgressTreeView::instance()->setModel( m );
@ -368,11 +385,13 @@ CalamaresApplication::initViewSteps()
cDebug() << Logger::SubEntry << steps.count() << "view steps loaded."; cDebug() << Logger::SubEntry << steps.count() << "view steps loaded.";
// Tell the first view that it's been shown. // Tell the first view that it's been shown.
if ( steps.count() > 0 ) if ( steps.count() > 0 )
steps[0]->onActivate(); {
steps[ 0 ]->onActivate();
}
} }
void void
CalamaresApplication::initFailed(const QStringList& l) CalamaresApplication::initFailed( const QStringList& l )
{ {
cError() << "STARTUP: failed modules are" << l; cError() << "STARTUP: failed modules are" << l;
m_mainwindow->show(); m_mainwindow->show();

View File

@ -82,4 +82,4 @@ private:
bool m_debugMode; bool m_debugMode;
}; };
#endif //CALAMARESAPPLICATION_H #endif // CALAMARESAPPLICATION_H

View File

@ -21,33 +21,39 @@
#include "CalamaresWindow.h" #include "CalamaresWindow.h"
#include "Branding.h"
#include "Settings.h"
#include "ViewManager.h" #include "ViewManager.h"
#include "progresstree/ProgressTreeView.h" #include "progresstree/ProgressTreeView.h"
#include "utils/CalamaresUtilsGui.h" #include "utils/CalamaresUtilsGui.h"
#include "utils/Logger.h"
#include "utils/DebugWindow.h" #include "utils/DebugWindow.h"
#include "utils/Logger.h"
#include "utils/Retranslator.h" #include "utils/Retranslator.h"
#include "Settings.h"
#include "Branding.h"
#include <QApplication> #include <QApplication>
#include <QBoxLayout> #include <QBoxLayout>
#include <QCloseEvent> #include <QCloseEvent>
#include <QDesktopWidget> #include <QDesktopWidget>
#include <QLabel>
#include <QTreeView>
#include <QFile> #include <QFile>
#include <QFileInfo> #include <QFileInfo>
#include <QLabel>
#include <QTreeView>
static inline int static inline int
windowDimensionToPixels( const Calamares::Branding::WindowDimension& u ) windowDimensionToPixels( const Calamares::Branding::WindowDimension& u )
{ {
if ( !u.isValid() ) if ( !u.isValid() )
{
return 0; return 0;
}
if ( u.unit() == Calamares::Branding::WindowDimensionUnit::Pixies ) if ( u.unit() == Calamares::Branding::WindowDimensionUnit::Pixies )
{
return u.value(); return u.value();
}
if ( u.unit() == Calamares::Branding::WindowDimensionUnit::Fonties ) if ( u.unit() == Calamares::Branding::WindowDimensionUnit::Fonties )
{
return u.value() * CalamaresUtils::defaultFontHeight(); return u.value() * CalamaresUtils::defaultFontHeight();
}
return 0; return 0;
} }
@ -58,14 +64,13 @@ CalamaresWindow::CalamaresWindow( QWidget* parent )
{ {
// If we can never cancel, don't show the window-close button // If we can never cancel, don't show the window-close button
if ( Calamares::Settings::instance()->disableCancel() ) if ( Calamares::Settings::instance()->disableCancel() )
{
setWindowFlag( Qt::WindowCloseButtonHint, false ); setWindowFlag( Qt::WindowCloseButtonHint, false );
}
CALAMARES_RETRANSLATE( CALAMARES_RETRANSLATE( setWindowTitle( Calamares::Settings::instance()->isSetupMode()
setWindowTitle( Calamares::Settings::instance()->isSetupMode() ? tr( "%1 Setup Program" ).arg( *Calamares::Branding::ProductName )
? tr( "%1 Setup Program" ).arg( *Calamares::Branding::ProductName ) : tr( "%1 Installer" ).arg( *Calamares::Branding::ProductName ) ); )
: tr( "%1 Installer" ).arg( *Calamares::Branding::ProductName )
);
)
const Calamares::Branding* const branding = Calamares::Branding::instance(); const Calamares::Branding* const branding = Calamares::Branding::instance();
@ -75,7 +80,7 @@ CalamaresWindow::CalamaresWindow( QWidget* parent )
using CalamaresUtils::windowPreferredWidth; using CalamaresUtils::windowPreferredWidth;
// Needs to match what's checked in DebugWindow // Needs to match what's checked in DebugWindow
this->setObjectName("mainApp"); this->setObjectName( "mainApp" );
QSize availableSize = qApp->desktop()->availableGeometry( this ).size(); QSize availableSize = qApp->desktop()->availableGeometry( this ).size();
QSize minimumSize( qBound( windowMinimumWidth, availableSize.width(), windowPreferredWidth ), QSize minimumSize( qBound( windowMinimumWidth, availableSize.width(), windowPreferredWidth ),
@ -87,7 +92,7 @@ CalamaresWindow::CalamaresWindow( QWidget* parent )
auto brandingSizes = branding->windowSize(); auto brandingSizes = branding->windowSize();
int w = qBound( minimumSize.width(), windowDimensionToPixels( brandingSizes.first ), availableSize.width() ); int w = qBound( minimumSize.width(), windowDimensionToPixels( brandingSizes.first ), availableSize.width() );
int h = qBound( minimumSize.height(), windowDimensionToPixels( brandingSizes.second ), availableSize.height() ); int h = qBound( minimumSize.height(), windowDimensionToPixels( brandingSizes.second ), availableSize.height() );
cDebug() << Logger::SubEntry << "Proposed window size:" << w << h; cDebug() << Logger::SubEntry << "Proposed window size:" << w << h;
resize( w, h ); resize( w, h );
@ -96,25 +101,26 @@ CalamaresWindow::CalamaresWindow( QWidget* parent )
setLayout( mainLayout ); setLayout( mainLayout );
QWidget* sideBox = new QWidget( this ); QWidget* sideBox = new QWidget( this );
sideBox->setObjectName("sidebarApp"); sideBox->setObjectName( "sidebarApp" );
mainLayout->addWidget( sideBox ); mainLayout->addWidget( sideBox );
QBoxLayout* sideLayout = new QVBoxLayout; QBoxLayout* sideLayout = new QVBoxLayout;
sideBox->setLayout( sideLayout ); sideBox->setLayout( sideLayout );
// Set this attribute into qss file // Set this attribute into qss file
sideBox->setFixedWidth( qBound( 100, CalamaresUtils::defaultFontHeight() * 12, w < windowPreferredWidth ? 100 : 190 ) ); sideBox->setFixedWidth(
qBound( 100, CalamaresUtils::defaultFontHeight() * 12, w < windowPreferredWidth ? 100 : 190 ) );
sideBox->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ); sideBox->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
QHBoxLayout* logoLayout = new QHBoxLayout; QHBoxLayout* logoLayout = new QHBoxLayout;
sideLayout->addLayout( logoLayout ); sideLayout->addLayout( logoLayout );
logoLayout->addStretch(); logoLayout->addStretch();
QLabel* logoLabel = new QLabel( sideBox ); QLabel* logoLabel = new QLabel( sideBox );
logoLabel->setObjectName("logoApp"); logoLabel->setObjectName( "logoApp" );
//Define all values into qss file //Define all values into qss file
{ {
QPalette plt = sideBox->palette(); QPalette plt = sideBox->palette();
sideBox->setAutoFillBackground( true ); sideBox->setAutoFillBackground( true );
plt.setColor( sideBox->backgroundRole(),branding->styleString( Calamares::Branding::SidebarBackground ) ); plt.setColor( sideBox->backgroundRole(), branding->styleString( Calamares::Branding::SidebarBackground ) );
plt.setColor( sideBox->foregroundRole(), branding->styleString( Calamares::Branding::SidebarText ) ); plt.setColor( sideBox->foregroundRole(), branding->styleString( Calamares::Branding::SidebarText ) );
sideBox->setPalette( plt ); sideBox->setPalette( plt );
logoLabel->setPalette( plt ); logoLabel->setPalette( plt );
@ -133,22 +139,16 @@ CalamaresWindow::CalamaresWindow( QWidget* parent )
{ {
QPushButton* debugWindowBtn = new QPushButton; QPushButton* debugWindowBtn = new QPushButton;
debugWindowBtn->setObjectName( "debugButton" ); debugWindowBtn->setObjectName( "debugButton" );
CALAMARES_RETRANSLATE( CALAMARES_RETRANSLATE( debugWindowBtn->setText( tr( "Show debug information" ) ); )
debugWindowBtn->setText( tr( "Show debug information" ) );
)
sideLayout->addWidget( debugWindowBtn ); sideLayout->addWidget( debugWindowBtn );
debugWindowBtn->setFlat( true ); debugWindowBtn->setFlat( true );
debugWindowBtn->setCheckable( true ); debugWindowBtn->setCheckable( true );
connect( debugWindowBtn, &QPushButton::clicked, connect( debugWindowBtn, &QPushButton::clicked, this, [=]( bool checked ) {
this, [ = ]( bool checked )
{
if ( checked ) if ( checked )
{ {
m_debugWindow = new Calamares::DebugWindow(); m_debugWindow = new Calamares::DebugWindow();
m_debugWindow->show(); m_debugWindow->show();
connect( m_debugWindow.data(), &Calamares::DebugWindow::closed, connect( m_debugWindow.data(), &Calamares::DebugWindow::closed, this, [=]() {
this, [ = ]()
{
m_debugWindow->deleteLater(); m_debugWindow->deleteLater();
debugWindowBtn->setChecked( false ); debugWindowBtn->setChecked( false );
} ); } );
@ -156,7 +156,9 @@ CalamaresWindow::CalamaresWindow( QWidget* parent )
else else
{ {
if ( m_debugWindow ) if ( m_debugWindow )
{
m_debugWindow->deleteLater(); m_debugWindow->deleteLater();
}
} }
} ); } );
} }
@ -166,7 +168,9 @@ CalamaresWindow::CalamaresWindow( QWidget* parent )
m_viewManager = Calamares::ViewManager::instance( this ); m_viewManager = Calamares::ViewManager::instance( this );
if ( branding->windowExpands() ) if ( branding->windowExpands() )
{
connect( m_viewManager, &Calamares::ViewManager::enlarge, this, &CalamaresWindow::enlarge ); connect( m_viewManager, &Calamares::ViewManager::enlarge, this, &CalamaresWindow::enlarge );
}
// NOTE: Although the ViewManager has a signal cancelEnabled() that // NOTE: Although the ViewManager has a signal cancelEnabled() that
// signals when the state of the cancel button changes (in // signals when the state of the cancel button changes (in
// particular, to disable cancel during the exec phase), // particular, to disable cancel during the exec phase),
@ -201,5 +205,7 @@ CalamaresWindow::closeEvent( QCloseEvent* event )
qApp->quit(); qApp->quit();
} }
else else
{
event->ignore(); event->ignore();
}
} }

View File

@ -27,7 +27,7 @@ namespace Calamares
{ {
class DebugWindow; class DebugWindow;
class ViewManager; class ViewManager;
} } // namespace Calamares
/** /**
* @brief The CalamaresWindow class represents the main window of the Calamares UI. * @brief The CalamaresWindow class represents the main window of the Calamares UI.
@ -55,4 +55,4 @@ private:
Calamares::ViewManager* m_viewManager; Calamares::ViewManager* m_viewManager;
}; };
#endif //CALAMARESWINDOW_H #endif // CALAMARESWINDOW_H

View File

@ -24,11 +24,10 @@
#include "kdsingleapplicationguard/kdsingleapplicationguard.h" #include "kdsingleapplicationguard/kdsingleapplicationguard.h"
#include "utils/Dirs.h" #include "utils/Dirs.h"
#include "utils/Logger.h" #include "utils/Logger.h"
#include "CalamaresConfig.h"
#ifdef WITH_KF5Crash #ifdef WITH_KF5Crash
#include <KF5/KCrash/KCrash>
#include <KF5/KCoreAddons/KAboutData> #include <KF5/KCoreAddons/KAboutData>
#include <KF5/KCrash/KCrash>
#endif #endif
#include <QCommandLineParser> #include <QCommandLineParser>
@ -38,14 +37,13 @@
static void static void
handle_args( CalamaresApplication& a ) handle_args( CalamaresApplication& a )
{ {
QCommandLineOption debugOption( QStringList{ "d", "debug"}, QCommandLineOption debugOption( QStringList { "d", "debug" },
"Also look in current directory for configuration. Implies -D8." ); "Also look in current directory for configuration. Implies -D8." );
QCommandLineOption debugLevelOption( QStringLiteral("D"), QCommandLineOption debugLevelOption(
"Verbose output for debugging purposes (0-8).", "level" ); QStringLiteral( "D" ), "Verbose output for debugging purposes (0-8).", "level" );
QCommandLineOption configOption( QStringList{ "c", "config"}, QCommandLineOption configOption(
"Configuration directory to use, for testing purposes.", "config" ); QStringList { "c", "config" }, "Configuration directory to use, for testing purposes.", "config" );
QCommandLineOption xdgOption( QStringList{"X", "xdg-config"}, QCommandLineOption xdgOption( QStringList { "X", "xdg-config" }, "Use XDG_{CONFIG,DATA}_DIRS as well." );
"Use XDG_{CONFIG,DATA}_DIRS as well." );
QCommandLineParser parser; QCommandLineParser parser;
parser.setApplicationDescription( "Distribution-independent installer framework" ); parser.setApplicationDescription( "Distribution-independent installer framework" );
@ -61,22 +59,32 @@ handle_args( CalamaresApplication& a )
a.setDebug( parser.isSet( debugOption ) ); a.setDebug( parser.isSet( debugOption ) );
if ( parser.isSet( debugOption ) ) if ( parser.isSet( debugOption ) )
{
Logger::setupLogLevel( Logger::LOGVERBOSE ); Logger::setupLogLevel( Logger::LOGVERBOSE );
}
else if ( parser.isSet( debugLevelOption ) ) else if ( parser.isSet( debugLevelOption ) )
{ {
bool ok = true; bool ok = true;
int l = parser.value( debugLevelOption ).toInt( &ok ); int l = parser.value( debugLevelOption ).toInt( &ok );
unsigned int dlevel = 0; unsigned int dlevel = 0;
if ( !ok || ( l < 0 ) ) if ( !ok || ( l < 0 ) )
{
dlevel = Logger::LOGVERBOSE; dlevel = Logger::LOGVERBOSE;
}
else else
dlevel = static_cast<unsigned int>( l ); // l >= 0 {
dlevel = static_cast< unsigned int >( l ); // l >= 0
}
Logger::setupLogLevel( dlevel ); Logger::setupLogLevel( dlevel );
} }
if ( parser.isSet( configOption ) ) if ( parser.isSet( configOption ) )
{
CalamaresUtils::setAppDataDir( QDir( parser.value( configOption ) ) ); CalamaresUtils::setAppDataDir( QDir( parser.value( configOption ) ) );
}
if ( parser.isSet( xdgOption ) ) if ( parser.isSet( xdgOption ) )
{
CalamaresUtils::setXdgDirs(); CalamaresUtils::setXdgDirs();
}
} }
int int
@ -118,9 +126,13 @@ main( int argc, char* argv[] )
auto instancelist = guard.instances(); auto instancelist = guard.instances();
qDebug() << "Calamares is already running, shutting down."; qDebug() << "Calamares is already running, shutting down.";
if ( instancelist.count() > 0 ) if ( instancelist.count() > 0 )
{
qDebug() << "Other running Calamares instances:"; qDebug() << "Other running Calamares instances:";
}
for ( const auto& i : instancelist ) for ( const auto& i : instancelist )
{
qDebug() << " " << i.isValid() << i.pid() << i.arguments(); qDebug() << " " << i.isValid() << i.pid() << i.arguments();
}
} }
return returnCode; return returnCode;

View File

@ -20,23 +20,28 @@
#include "ProgressTreeDelegate.h" #include "ProgressTreeDelegate.h"
#include "ProgressTreeModel.h" #include "ProgressTreeModel.h"
#include "Branding.h"
#include "CalamaresApplication.h" #include "CalamaresApplication.h"
#include "CalamaresWindow.h" #include "CalamaresWindow.h"
#include "Branding.h"
#include "utils/CalamaresUtilsGui.h" #include "utils/CalamaresUtilsGui.h"
#include <QPainter> #include <QPainter>
static constexpr int const item_margin = 8; static constexpr int const item_margin = 8;
static inline int item_fontsize() { return CalamaresUtils::defaultFontSize() + 4; } static inline int
item_fontsize()
{
return CalamaresUtils::defaultFontSize() + 4;
}
QSize QSize
ProgressTreeDelegate::sizeHint( const QStyleOptionViewItem& option, ProgressTreeDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const
const QModelIndex& index ) const
{ {
if ( !index.isValid() ) if ( !index.isValid() )
{
return option.rect.size(); return option.rect.size();
}
QFont font = qApp->font(); QFont font = qApp->font();
@ -51,9 +56,7 @@ ProgressTreeDelegate::sizeHint( const QStyleOptionViewItem& option,
void void
ProgressTreeDelegate::paint( QPainter* painter, ProgressTreeDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
const QStyleOptionViewItem& option,
const QModelIndex& index) const
{ {
QStyleOptionViewItem opt = option; QStyleOptionViewItem opt = option;
@ -62,10 +65,9 @@ ProgressTreeDelegate::paint( QPainter* painter,
initStyleOption( &opt, index ); initStyleOption( &opt, index );
opt.text.clear(); opt.text.clear();
painter->setBrush( QColor( Calamares::Branding::instance()-> painter->setBrush(
styleString( Calamares::Branding::SidebarBackground ) ) ); QColor( Calamares::Branding::instance()->styleString( Calamares::Branding::SidebarBackground ) ) );
painter->setPen( QColor( Calamares::Branding::instance()-> painter->setPen( QColor( Calamares::Branding::instance()->styleString( Calamares::Branding::SidebarText ) ) );
styleString( Calamares::Branding::SidebarText ) ) );
paintViewStep( painter, opt, index ); paintViewStep( painter, opt, index );
@ -89,14 +91,17 @@ ProgressTreeDelegate::paintViewStep( QPainter* painter,
if ( isCurrent ) if ( isCurrent )
{ {
painter->setPen( Calamares::Branding::instance()-> painter->setPen( Calamares::Branding::instance()->styleString( Calamares::Branding::SidebarTextSelect ) );
styleString( Calamares::Branding::SidebarTextSelect ) ); QString textHighlight
QString textHighlight = Calamares::Branding::instance()-> = Calamares::Branding::instance()->styleString( Calamares::Branding::SidebarTextHighlight );
styleString( Calamares::Branding::SidebarTextHighlight );
if ( textHighlight.isEmpty() ) if ( textHighlight.isEmpty() )
{
painter->setBrush( CalamaresApplication::instance()->mainWindow()->palette().background() ); painter->setBrush( CalamaresApplication::instance()->mainWindow()->palette().background() );
}
else else
{
painter->setBrush( QColor( textHighlight ) ); painter->setBrush( QColor( textHighlight ) );
}
} }
@ -114,17 +119,19 @@ ProgressTreeDelegate::paintViewStep( QPainter* painter,
shrinkSteps++; shrinkSteps++;
QRectF boundingBox; QRectF boundingBox;
painter->drawText( textRect, Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextSingleLine, index.data().toString(), &boundingBox ); painter->drawText(
textRect, Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextSingleLine, index.data().toString(), &boundingBox );
// The extra check here is to avoid the changing-font-size if we're not going to use // The extra check here is to avoid the changing-font-size if we're not going to use
// it in the next iteration of the loop anyway. // it in the next iteration of the loop anyway.
if ( ( shrinkSteps <= maximumShrink ) && (boundingBox.width() > textRect.width() ) ) if ( ( shrinkSteps <= maximumShrink ) && ( boundingBox.width() > textRect.width() ) )
{ {
font.setPointSize( item_fontsize() - shrinkSteps ); font.setPointSize( item_fontsize() - shrinkSteps );
painter->setFont( font ); painter->setFont( font );
} }
else else
{
break; // It fits break; // It fits
} }
while ( shrinkSteps <= maximumShrink ); } while ( shrinkSteps <= maximumShrink );
} }

View File

@ -33,16 +33,11 @@ public:
using QStyledItemDelegate::QStyledItemDelegate; using QStyledItemDelegate::QStyledItemDelegate;
protected: protected:
QSize sizeHint( const QStyleOptionViewItem& option, QSize sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const override;
const QModelIndex& index ) const override; void paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const override;
void paint( QPainter* painter,
const QStyleOptionViewItem& option,
const QModelIndex& index ) const override;
private: private:
void paintViewStep( QPainter* painter, void paintViewStep( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
const QStyleOptionViewItem& option,
const QModelIndex& index ) const;
}; };
#endif // PROGRESSTREEDELEGATE_H #endif // PROGRESSTREEDELEGATE_H

View File

@ -65,8 +65,9 @@ int
ProgressTreeItem::row() const ProgressTreeItem::row() const
{ {
if ( m_parentItem ) if ( m_parentItem )
return m_parentItem->m_childItems.indexOf( {
const_cast< ProgressTreeItem* >( this ) ); return m_parentItem->m_childItems.indexOf( const_cast< ProgressTreeItem* >( this ) );
}
return 0; return 0;
} }
@ -80,7 +81,8 @@ ProgressTreeItem::parent()
ProgressTreeRoot::ProgressTreeRoot() ProgressTreeRoot::ProgressTreeRoot()
: ProgressTreeItem() : ProgressTreeItem()
{} {
}
QVariant QVariant

View File

@ -57,4 +57,4 @@ public:
virtual QVariant data( int role ) const; virtual QVariant data( int role ) const;
}; };
#endif // PROGRESSTREEITEM_H #endif // PROGRESSTREEITEM_H

View File

@ -19,7 +19,8 @@
#include "ProgressTreeModel.h" #include "ProgressTreeModel.h"
#include "progresstree/ViewStepItem.h" #include "ViewStepItem.h"
#include "ViewManager.h" #include "ViewManager.h"
ProgressTreeModel::ProgressTreeModel( QObject* parent ) ProgressTreeModel::ProgressTreeModel( QObject* parent )
@ -40,7 +41,9 @@ Qt::ItemFlags
ProgressTreeModel::flags( const QModelIndex& index ) const ProgressTreeModel::flags( const QModelIndex& index ) const
{ {
if ( !index.isValid() ) if ( !index.isValid() )
{
return Qt::ItemFlags(); return Qt::ItemFlags();
}
return Qt::ItemIsEnabled; return Qt::ItemIsEnabled;
} }
@ -50,20 +53,30 @@ QModelIndex
ProgressTreeModel::index( int row, int column, const QModelIndex& parent ) const ProgressTreeModel::index( int row, int column, const QModelIndex& parent ) const
{ {
if ( !hasIndex( row, column, parent ) ) if ( !hasIndex( row, column, parent ) )
{
return QModelIndex(); return QModelIndex();
}
ProgressTreeItem* parentItem; ProgressTreeItem* parentItem;
if ( !parent.isValid() ) if ( !parent.isValid() )
{
parentItem = m_rootItem; parentItem = m_rootItem;
}
else else
{
parentItem = static_cast< ProgressTreeItem* >( parent.internalPointer() ); parentItem = static_cast< ProgressTreeItem* >( parent.internalPointer() );
}
ProgressTreeItem* childItem = parentItem->child( row ); ProgressTreeItem* childItem = parentItem->child( row );
if ( childItem ) if ( childItem )
{
return createIndex( row, column, childItem ); return createIndex( row, column, childItem );
}
else else
{
return QModelIndex(); return QModelIndex();
}
} }
@ -71,13 +84,17 @@ QModelIndex
ProgressTreeModel::parent( const QModelIndex& index ) const ProgressTreeModel::parent( const QModelIndex& index ) const
{ {
if ( !index.isValid() ) if ( !index.isValid() )
{
return QModelIndex(); return QModelIndex();
}
ProgressTreeItem* childItem = static_cast< ProgressTreeItem* >( index.internalPointer() ); ProgressTreeItem* childItem = static_cast< ProgressTreeItem* >( index.internalPointer() );
ProgressTreeItem* parentItem = childItem->parent(); ProgressTreeItem* parentItem = childItem->parent();
if ( parentItem == m_rootItem ) if ( parentItem == m_rootItem )
{
return QModelIndex(); return QModelIndex();
}
return createIndex( parentItem->row(), 0, parentItem ); return createIndex( parentItem->row(), 0, parentItem );
} }
@ -87,7 +104,9 @@ QVariant
ProgressTreeModel::data( const QModelIndex& index, int role ) const ProgressTreeModel::data( const QModelIndex& index, int role ) const
{ {
if ( !index.isValid() ) if ( !index.isValid() )
{
return QVariant(); return QVariant();
}
ProgressTreeItem* item = static_cast< ProgressTreeItem* >( index.internalPointer() ); ProgressTreeItem* item = static_cast< ProgressTreeItem* >( index.internalPointer() );
@ -111,12 +130,18 @@ ProgressTreeModel::rowCount( const QModelIndex& parent ) const
{ {
ProgressTreeItem* parentItem; ProgressTreeItem* parentItem;
if ( parent.column() > 0 ) if ( parent.column() > 0 )
{
return 0; return 0;
}
if ( !parent.isValid() ) if ( !parent.isValid() )
{
parentItem = m_rootItem; parentItem = m_rootItem;
}
else else
{
parentItem = static_cast< ProgressTreeItem* >( parent.internalPointer() ); parentItem = static_cast< ProgressTreeItem* >( parent.internalPointer() );
}
return parentItem->childCount(); return parentItem->childCount();
} }
@ -126,9 +151,13 @@ int
ProgressTreeModel::columnCount( const QModelIndex& parent ) const ProgressTreeModel::columnCount( const QModelIndex& parent ) const
{ {
if ( parent.isValid() ) if ( parent.isValid() )
{
return static_cast< ProgressTreeItem* >( parent.internalPointer() )->columnCount(); return static_cast< ProgressTreeItem* >( parent.internalPointer() )->columnCount();
}
else else
{
return m_rootItem->columnCount(); return m_rootItem->columnCount();
}
} }
@ -152,7 +181,9 @@ QModelIndex
ProgressTreeModel::indexFromItem( ProgressTreeItem* item ) ProgressTreeModel::indexFromItem( ProgressTreeItem* item )
{ {
if ( !item || !item->parent() ) if ( !item || !item->parent() )
{
return QModelIndex(); return QModelIndex();
}
// Reconstructs a QModelIndex from a ProgressTreeItem that is somewhere in the tree. // Reconstructs a QModelIndex from a ProgressTreeItem that is somewhere in the tree.
// Traverses the item to the root node, then rebuilds the qmodelindices from there // Traverses the item to the root node, then rebuilds the qmodelindices from there
@ -172,10 +203,13 @@ ProgressTreeModel::indexFromItem( ProgressTreeItem* item )
**/ **/
QList< int > childIndexList; QList< int > childIndexList;
ProgressTreeItem* curItem = item; ProgressTreeItem* curItem = item;
while ( curItem != m_rootItem ) { while ( curItem != m_rootItem )
int row = curItem->row(); //relative to its parent {
if ( row < 0 ) // something went wrong, bail int row = curItem->row(); //relative to its parent
if ( row < 0 ) // something went wrong, bail
{
return QModelIndex(); return QModelIndex();
}
childIndexList << row; childIndexList << row;
@ -184,7 +218,7 @@ ProgressTreeModel::indexFromItem( ProgressTreeItem* item )
// Now we rebuild the QModelIndex we need // Now we rebuild the QModelIndex we need
QModelIndex idx; QModelIndex idx;
for ( int i = childIndexList.size() - 1; i >= 0 ; i-- ) for ( int i = childIndexList.size() - 1; i >= 0; i-- )
{ {
idx = index( childIndexList[ i ], 0, idx ); idx = index( childIndexList[ i ], 0, idx );
} }

View File

@ -57,4 +57,4 @@ private:
ProgressTreeRoot* m_rootItem; ProgressTreeRoot* m_rootItem;
}; };
#endif // PROGRESSTREEMODEL_H #endif // PROGRESSTREEMODEL_H

View File

@ -19,8 +19,9 @@
#include "ProgressTreeView.h" #include "ProgressTreeView.h"
#include "ProgressTreeDelegate.h" #include "ProgressTreeDelegate.h"
#include "ViewManager.h"
#include "Branding.h" #include "Branding.h"
#include "ViewManager.h"
ProgressTreeView* ProgressTreeView::s_instance = nullptr; ProgressTreeView* ProgressTreeView::s_instance = nullptr;
@ -33,9 +34,9 @@ ProgressTreeView::instance()
ProgressTreeView::ProgressTreeView( QWidget* parent ) ProgressTreeView::ProgressTreeView( QWidget* parent )
: QTreeView( parent ) : QTreeView( parent )
{ {
s_instance = this; //FIXME: should assert when s_instance gets written and it wasn't nullptr s_instance = this; //FIXME: should assert when s_instance gets written and it wasn't nullptr
this->setObjectName("sidebarMenuApp"); this->setObjectName( "sidebarMenuApp" );
setFrameShape( QFrame::NoFrame ); setFrameShape( QFrame::NoFrame );
setContentsMargins( 0, 0, 0, 0 ); setContentsMargins( 0, 0, 0, 0 );
@ -55,31 +56,29 @@ ProgressTreeView::ProgressTreeView( QWidget* parent )
setItemDelegate( m_delegate ); setItemDelegate( m_delegate );
QPalette plt = palette(); QPalette plt = palette();
plt.setColor( QPalette::Base, Calamares::Branding::instance()-> plt.setColor( QPalette::Base,
styleString( Calamares::Branding::SidebarBackground ) ); Calamares::Branding::instance()->styleString( Calamares::Branding::SidebarBackground ) );
setPalette( plt ); setPalette( plt );
} }
ProgressTreeView::~ProgressTreeView() ProgressTreeView::~ProgressTreeView() {}
{
}
void void
ProgressTreeView::setModel( QAbstractItemModel* model ) ProgressTreeView::setModel( QAbstractItemModel* model )
{ {
if ( ProgressTreeView::model() ) if ( ProgressTreeView::model() )
{
return; return;
}
QTreeView::setModel( model ); QTreeView::setModel( model );
expandAll(); expandAll();
connect( Calamares::ViewManager::instance(), connect( Calamares::ViewManager::instance(),
&Calamares::ViewManager::currentStepChanged, &Calamares::ViewManager::currentStepChanged,
this, [this]() this,
{ [this]() { viewport()->update(); },
viewport()->update(); Qt::UniqueConnection );
},
Qt::UniqueConnection );
} }

View File

@ -48,4 +48,4 @@ private:
ProgressTreeDelegate* m_delegate; ProgressTreeDelegate* m_delegate;
}; };
#endif // PROGRESSTREEVIEW_H #endif // PROGRESSTREEVIEW_H

View File

@ -19,6 +19,7 @@
#include "ViewStepItem.h" #include "ViewStepItem.h"
#include "ProgressTreeModel.h" #include "ProgressTreeModel.h"
#include "Settings.h" #include "Settings.h"
#include "ViewManager.h" #include "ViewManager.h"
#include "viewpages/ViewStep.h" #include "viewpages/ViewStep.h"
@ -28,18 +29,17 @@ ViewStepItem::ViewStepItem( std::function< QString() > prettyName,
std::function< const Calamares::ViewStep*() > accessor, std::function< const Calamares::ViewStep*() > accessor,
ProgressTreeItem* parent ) ProgressTreeItem* parent )
: ProgressTreeItem( parent ) : ProgressTreeItem( parent )
, m_accessor( accessor )
, m_prettyName( prettyName )
, m_step( nullptr ) , m_step( nullptr )
{ {
m_prettyName = prettyName;
m_accessor = accessor;
} }
ViewStepItem::ViewStepItem( const Calamares::ViewStep* step, ViewStepItem::ViewStepItem( const Calamares::ViewStep* step, ProgressTreeItem* parent )
ProgressTreeItem* parent )
: ProgressTreeItem( parent ) : ProgressTreeItem( parent )
, m_step( step )
{ {
m_step = step;
} }
void void
@ -55,8 +55,7 @@ ViewStepItem::data( int role ) const
{ {
if ( role == Qt::DisplayRole ) if ( role == Qt::DisplayRole )
{ {
return m_step ? m_step->prettyName() return m_step ? m_step->prettyName() : m_prettyName();
: m_prettyName();
} }
if ( Calamares::Settings::instance()->debugMode() && role == Qt::ToolTipRole ) if ( Calamares::Settings::instance()->debugMode() && role == Qt::ToolTipRole )
{ {
@ -66,9 +65,9 @@ ViewStepItem::data( int role ) const
toolTip.append( "<br/>Type:\tViewStep" ); toolTip.append( "<br/>Type:\tViewStep" );
toolTip.append( QString( "<br/>Pretty:\t%1" ).arg( m_step->prettyName() ) ); toolTip.append( QString( "<br/>Pretty:\t%1" ).arg( m_step->prettyName() ) );
toolTip.append( QString( "<br/>Status:\t%1" ).arg( m_step->prettyStatus() ) ); toolTip.append( QString( "<br/>Status:\t%1" ).arg( m_step->prettyStatus() ) );
toolTip.append( QString( "<br/>Source:\t%1" ).arg( toolTip.append(
m_step->moduleInstanceKey().isEmpty() ? "built-in" QString( "<br/>Source:\t%1" )
: m_step->moduleInstanceKey() ) ); .arg( m_step->moduleInstanceKey().isEmpty() ? "built-in" : m_step->moduleInstanceKey() ) );
} }
else else
{ {
@ -78,8 +77,7 @@ ViewStepItem::data( int role ) const
return toolTip; return toolTip;
} }
if ( role == ProgressTreeModel::ProgressTreeItemCurrentRole ) if ( role == ProgressTreeModel::ProgressTreeItemCurrentRole )
return m_step ? return m_step ? ( Calamares::ViewManager::instance()->currentStep() == m_step )
( Calamares::ViewManager::instance()->currentStep() == m_step ) : : ( Calamares::ViewManager::instance()->currentStep() == m_accessor() );
( Calamares::ViewManager::instance()->currentStep() == m_accessor() );
return QVariant(); return QVariant();
} }

View File

@ -37,18 +37,17 @@ public:
std::function< const Calamares::ViewStep*() > accessor, std::function< const Calamares::ViewStep*() > accessor,
ProgressTreeItem* parent = nullptr ); ProgressTreeItem* parent = nullptr );
explicit ViewStepItem( const Calamares::ViewStep* step, explicit ViewStepItem( const Calamares::ViewStep* step, ProgressTreeItem* parent = nullptr );
ProgressTreeItem* parent = nullptr );
void appendChild( ProgressTreeItem* item ) override; void appendChild( ProgressTreeItem* item ) override;
QVariant data( int role ) const override; QVariant data( int role ) const override;
private: private:
std::function< const Calamares::ViewStep*() > m_accessor; const std::function< const Calamares::ViewStep*() > m_accessor;
std::function< QString() > m_prettyName; const std::function< QString() > m_prettyName;
const Calamares::ViewStep* m_step; const Calamares::ViewStep* const m_step;
}; };
#endif // VIEWSTEPITEM_H #endif // VIEWSTEPITEM_H

View File

@ -22,9 +22,9 @@
* bindings. * bindings.
*/ */
#include "modulesystem/Module.h"
#include "utils/Logger.h" #include "utils/Logger.h"
#include "utils/Yaml.h" #include "utils/Yaml.h"
#include "modulesystem/Module.h"
#include "GlobalStorage.h" #include "GlobalStorage.h"
#include "Job.h" #include "Job.h"
@ -40,28 +40,47 @@
struct ModuleConfig struct ModuleConfig
{ {
QString moduleName() const { return m_module; } QString
QString configFile() const { return m_jobConfig; } moduleName() const
QString language() const { return m_language; } {
QString globalConfigFile() const { return m_globalConfig; } return m_module;
}
QString
configFile() const
{
return m_jobConfig;
}
QString
language() const
{
return m_language;
}
QString
globalConfigFile() const
{
return m_globalConfig;
}
QString m_module; QString m_module;
QString m_jobConfig; QString m_jobConfig;
QString m_globalConfig; QString m_globalConfig;
QString m_language; QString m_language;
} ; };
static ModuleConfig static ModuleConfig
handle_args( QCoreApplication& a ) handle_args( QCoreApplication& a )
{ {
QCommandLineOption debugLevelOption( QStringLiteral("D"), QCommandLineOption debugLevelOption(
"Verbose output for debugging purposes (0-8).", "level" ); QStringLiteral( "D" ), "Verbose output for debugging purposes (0-8).", "level" );
QCommandLineOption globalOption( QStringList() << QStringLiteral( "g" ) << QStringLiteral( "global "), QCommandLineOption globalOption( QStringList() << QStringLiteral( "g" ) << QStringLiteral( "global " ),
QStringLiteral( "Global settings document" ), "global.yaml" ); QStringLiteral( "Global settings document" ),
QCommandLineOption jobOption( QStringList() << QStringLiteral( "j" ) << QStringLiteral( "job"), "global.yaml" );
QStringLiteral( "Job settings document" ), "job.yaml" ); QCommandLineOption jobOption( QStringList() << QStringLiteral( "j" ) << QStringLiteral( "job" ),
QStringLiteral( "Job settings document" ),
"job.yaml" );
QCommandLineOption langOption( QStringList() << QStringLiteral( "l" ) << QStringLiteral( "language" ), QCommandLineOption langOption( QStringList() << QStringLiteral( "l" ) << QStringLiteral( "language" ),
QStringLiteral( "Language (global)" ), "languagecode" ); QStringLiteral( "Language (global)" ),
"languagecode" );
QCommandLineParser parser; QCommandLineParser parser;
parser.setApplicationDescription( "Calamares module tester" ); parser.setApplicationDescription( "Calamares module tester" );
@ -73,7 +92,7 @@ handle_args( QCoreApplication& a )
parser.addOption( jobOption ); parser.addOption( jobOption );
parser.addOption( langOption ); parser.addOption( langOption );
parser.addPositionalArgument( "module", "Path or name of module to run." ); parser.addPositionalArgument( "module", "Path or name of module to run." );
parser.addPositionalArgument( "job.yaml", "Path of job settings document to use.", "[job.yaml]"); parser.addPositionalArgument( "job.yaml", "Path of job settings document to use.", "[job.yaml]" );
parser.process( a ); parser.process( a );
@ -83,9 +102,13 @@ handle_args( QCoreApplication& a )
unsigned int l = parser.value( debugLevelOption ).toUInt( &ok ); unsigned int l = parser.value( debugLevelOption ).toUInt( &ok );
unsigned int dlevel = 0; unsigned int dlevel = 0;
if ( !ok ) if ( !ok )
{
dlevel = Logger::LOGVERBOSE; dlevel = Logger::LOGVERBOSE;
}
else else
{
dlevel = l; dlevel = l;
}
Logger::setupLogLevel( dlevel ); Logger::setupLogLevel( dlevel );
} }
@ -104,9 +127,11 @@ handle_args( QCoreApplication& a )
{ {
QString jobSettings( parser.value( jobOption ) ); QString jobSettings( parser.value( jobOption ) );
if ( jobSettings.isEmpty() && ( args.size() == 2 ) ) if ( jobSettings.isEmpty() && ( args.size() == 2 ) )
jobSettings = args.at(1); {
jobSettings = args.at( 1 );
}
return ModuleConfig{ args.first(), jobSettings, parser.value( globalOption ), parser.value( langOption ) }; return ModuleConfig { args.first(), jobSettings, parser.value( globalOption ), parser.value( langOption ) };
} }
} }
@ -120,14 +145,18 @@ load_module( const ModuleConfig& moduleConfig )
bool ok = false; bool ok = false;
QVariantMap descriptor; QVariantMap descriptor;
for ( const QString& prefix : QStringList{ "./", "src/modules/", "modules/" } ) for ( const QString& prefix : QStringList { "./", "src/modules/", "modules/" } )
{ {
// Could be a complete path, eg. src/modules/dummycpp/module.desc // Could be a complete path, eg. src/modules/dummycpp/module.desc
fi = QFileInfo( prefix + moduleName ); fi = QFileInfo( prefix + moduleName );
if ( fi.exists() && fi.isFile() ) if ( fi.exists() && fi.isFile() )
{
descriptor = CalamaresUtils::loadYaml( fi, &ok ); descriptor = CalamaresUtils::loadYaml( fi, &ok );
}
if ( ok ) if ( ok )
{
break; break;
}
// Could be a path without module.desc // Could be a path without module.desc
fi = QFileInfo( prefix + moduleName ); fi = QFileInfo( prefix + moduleName );
@ -135,8 +164,13 @@ load_module( const ModuleConfig& moduleConfig )
{ {
fi = QFileInfo( prefix + moduleName + "/module.desc" ); fi = QFileInfo( prefix + moduleName + "/module.desc" );
if ( fi.exists() && fi.isFile() ) if ( fi.exists() && fi.isFile() )
{
descriptor = CalamaresUtils::loadYaml( fi, &ok ); descriptor = CalamaresUtils::loadYaml( fi, &ok );
if ( ok ) break; }
if ( ok )
{
break;
}
} }
} }
@ -154,15 +188,12 @@ load_module( const ModuleConfig& moduleConfig )
} }
QString moduleDirectory = fi.absolutePath(); QString moduleDirectory = fi.absolutePath();
QString configFile( QString configFile( moduleConfig.configFile().isEmpty() ? moduleDirectory + '/' + name + ".conf"
moduleConfig.configFile().isEmpty() : moduleConfig.configFile() );
? moduleDirectory + '/' + name + ".conf"
: moduleConfig.configFile() );
cDebug() << "Module" << moduleName << "job-configuration:" << configFile; cDebug() << "Module" << moduleName << "job-configuration:" << configFile;
Calamares::Module* module = Calamares::Module::fromDescriptor( Calamares::Module* module = Calamares::Module::fromDescriptor( descriptor, name, configFile, moduleDirectory );
descriptor, name, configFile, moduleDirectory );
return module; return module;
} }
@ -174,14 +205,18 @@ main( int argc, char* argv[] )
ModuleConfig module = handle_args( a ); ModuleConfig module = handle_args( a );
if ( module.moduleName().isEmpty() ) if ( module.moduleName().isEmpty() )
{
return 1; return 1;
}
std::unique_ptr< Calamares::Settings > settings_p( new Calamares::Settings( QString(), true ) ); std::unique_ptr< Calamares::Settings > settings_p( new Calamares::Settings( QString(), true ) );
std::unique_ptr< Calamares::JobQueue > jobqueue_p( new Calamares::JobQueue( nullptr ) ); std::unique_ptr< Calamares::JobQueue > jobqueue_p( new Calamares::JobQueue( nullptr ) );
auto gs = jobqueue_p->globalStorage(); auto gs = jobqueue_p->globalStorage();
if ( !module.globalConfigFile().isEmpty() ) if ( !module.globalConfigFile().isEmpty() )
{
gs->loadYaml( module.globalConfigFile() ); gs->loadYaml( module.globalConfigFile() );
}
if ( !module.language().isEmpty() ) if ( !module.language().isEmpty() )
{ {
QVariantMap vm; QVariantMap vm;
@ -199,7 +234,9 @@ main( int argc, char* argv[] )
} }
if ( !m->isLoaded() ) if ( !m->isLoaded() )
{
m->loadSelf(); m->loadSelf();
}
if ( !m->isLoaded() ) if ( !m->isLoaded() )
{ {
@ -207,12 +244,10 @@ main( int argc, char* argv[] )
return 1; return 1;
} }
using TR = Logger::DebugRow<const char*, const QString>; using TR = Logger::DebugRow< const char*, const QString >;
cDebug() << "Module metadata" cDebug() << "Module metadata" << TR( "name", m->name() ) << TR( "type", m->typeString() )
<< TR( "name", m->name() ) << TR( "interface", m->interfaceString() );
<< TR( "type", m->typeString() )
<< TR( "interface", m->interfaceString() );
cDebug() << "Job outputs:"; cDebug() << "Job outputs:";
Calamares::JobList jobList = m->jobs(); Calamares::JobList jobList = m->jobs();
@ -224,11 +259,11 @@ main( int argc, char* argv[] )
Calamares::JobResult r = p->exec(); Calamares::JobResult r = p->exec();
if ( !r ) if ( !r )
{ {
cError() << "Job #" << count << "failed" cError() << "Job #" << count << "failed" << TR( "summary", r.message() ) << TR( "details", r.details() );
<< TR( "summary", r.message() )
<< TR( "details", r.details() );
if ( r.errorCode() > 0 ) if ( r.errorCode() > 0 )
{
++failure_count; ++failure_count;
}
} }
++count; ++count;
} }

View File

@ -44,7 +44,7 @@ public:
} }
virtual ~JobThread() override; virtual ~JobThread() override;
void setJobs( const JobList& jobs ) void setJobs( const JobList& jobs )
{ {
m_jobs = jobs; m_jobs = jobs;
@ -157,6 +157,14 @@ JobQueue::JobQueue( QObject* parent )
JobQueue::~JobQueue() JobQueue::~JobQueue()
{ {
if ( m_thread->isRunning() )
{
m_thread->terminate();
if ( !m_thread->wait(300) )
cError() << "Could not terminate job thread (expect a crash now).";
delete m_thread;
}
delete m_storage; delete m_storage;
} }

View File

@ -48,10 +48,8 @@ ProcessJob::~ProcessJob()
QString QString
ProcessJob::prettyName() const ProcessJob::prettyName() const
{ {
//TODO: show something more meaningful return ( m_runInChroot ? tr( "Run command '%1' in target system." ) : tr( " Run command '%1'." ) )
return tr( "Run command %1 %2" ) .arg( m_command );
.arg( m_command )
.arg( m_runInChroot ? "in chroot." : " ." );
} }
@ -67,83 +65,23 @@ ProcessJob::prettyStatusMessage() const
JobResult JobResult
ProcessJob::exec() ProcessJob::exec()
{ {
int ec = 0; using CalamaresUtils::System;
QString output;
if ( m_runInChroot ) if ( m_runInChroot )
ec = CalamaresUtils::System::instance()-> return CalamaresUtils::System::instance()->
targetEnvOutput( m_command, targetEnvCommand( { m_command },
output,
m_workingPath, m_workingPath,
QString(), QString(),
m_timeoutSec ); m_timeoutSec )
.explainProcess( m_command, m_timeoutSec );
else else
ec = callOutput( m_command, return
output, System::runCommand( System::RunLocation::RunInHost,
m_workingPath, { "/bin/sh", "-c", m_command },
QString(), m_workingPath,
m_timeoutSec ); QString(),
m_timeoutSec )
return CalamaresUtils::ProcessResult::explainProcess( ec, m_command, output, m_timeoutSec ); .explainProcess( m_command, m_timeoutSec );
}
int
ProcessJob::callOutput( const QString& command,
QString& output,
const QString& workingPath,
const QString& stdInput,
int timeoutSec )
{
output.clear();
QProcess process;
process.setProgram( "/bin/sh" );
process.setArguments( { "-c", command } );
process.setProcessChannelMode( QProcess::MergedChannels );
if ( !workingPath.isEmpty() )
{
if ( QDir( workingPath ).exists() )
process.setWorkingDirectory( QDir( workingPath ).absolutePath() );
else
{
cWarning() << "Invalid working directory:" << workingPath;
return -3;
}
}
cDebug() << "Running" << command;
process.start();
if ( !process.waitForStarted() )
{
cWarning() << "Process failed to start" << process.error();
return -2;
}
if ( !stdInput.isEmpty() )
{
process.write( stdInput.toLocal8Bit() );
process.closeWriteChannel();
}
if ( !process.waitForFinished( timeoutSec ? ( timeoutSec * 1000 ) : -1 ) )
{
cWarning() << "Timed out. output so far:";
output.append( QString::fromLocal8Bit( process.readAllStandardOutput() ).trimmed() );
cWarning() << output;
return -4;
}
output.append( QString::fromLocal8Bit( process.readAllStandardOutput() ).trimmed() );
if ( process.exitStatus() == QProcess::CrashExit )
{
cWarning() << "Process crashed";
return -1;
}
cDebug() << "Finished. Exit code:" << process.exitCode();
return process.exitCode();
} }
} // namespace Calamares } // namespace Calamares

View File

@ -1,7 +1,7 @@
/* === This file is part of Calamares - <https://github.com/calamares> === /* === This file is part of Calamares - <https://github.com/calamares> ===
* *
* Copyright 2014, Teo Mrnjavac <teo@kde.org> * Copyright 2014, Teo Mrnjavac <teo@kde.org>
* Copyright 2017-2018, Adriaan de Groot <groot@kde.org> * Copyright 2017-2019, Adriaan de Groot <groot@kde.org>
* *
* Calamares is free software: you can redistribute it and/or modify * Calamares is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -40,11 +40,6 @@ public:
JobResult exec() override; JobResult exec() override;
private: private:
int callOutput( const QString& command,
QString& output,
const QString& workingPath = QString(),
const QString& stdInput = QString(),
int timeoutSec = 0 );
QString m_command; QString m_command;
QString m_workingPath; QString m_workingPath;
bool m_runInChroot; bool m_runInChroot;

View File

@ -18,9 +18,12 @@
#include "Tests.h" #include "Tests.h"
#include "utils/CalamaresUtilsSystem.h"
#include "utils/Logger.h" #include "utils/Logger.h"
#include "utils/Yaml.h" #include "utils/Yaml.h"
#include <QTemporaryFile>
#include <QtTest/QtTest> #include <QtTest/QtTest>
QTEST_GUILESS_MAIN( LibCalamaresTests ) QTEST_GUILESS_MAIN( LibCalamaresTests )
@ -113,3 +116,45 @@ LibCalamaresTests::testLoadSaveYamlExtended()
} }
QFile::remove( "out.yaml" ); QFile::remove( "out.yaml" );
} }
void
LibCalamaresTests::testCommands()
{
using CalamaresUtils::System;
auto r = System::runCommand(
System::RunLocation::RunInHost,
{ "/bin/ls", "/tmp" }
);
QVERIFY( r.getExitCode() == 0 );
QTemporaryFile tf( "/tmp/calamares-test-XXXXXX" );
QVERIFY( tf.open() );
QVERIFY( !tf.fileName().isEmpty() );
QFileInfo tfn( tf.fileName() );
QVERIFY( !r.getOutput().contains( tfn.fileName() ) );
// Run ls again, now that the file exists
r = System::runCommand(
System::RunLocation::RunInHost,
{ "/bin/ls", "/tmp" }
);
QVERIFY( r.getOutput().contains( tfn.fileName() ) );
// .. and without a working directory set, assume builddir != /tmp
r = System::runCommand(
System::RunLocation::RunInHost,
{ "/bin/ls" }
);
QVERIFY( !r.getOutput().contains( tfn.fileName() ) );
r = System::runCommand(
System::RunLocation::RunInHost,
{ "/bin/ls" },
"/tmp"
);
QVERIFY( r.getOutput().contains( tfn.fileName() ) );
}

View File

@ -34,6 +34,8 @@ private Q_SLOTS:
void testLoadSaveYaml(); // Just settings.conf void testLoadSaveYaml(); // Just settings.conf
void testLoadSaveYamlExtended(); // Do a find() in the src dir void testLoadSaveYamlExtended(); // Do a find() in the src dir
void testCommands();
}; };
#endif #endif

View File

@ -114,14 +114,24 @@ System::mount( const QString& devicePath,
const QString& options ) const QString& options )
{ {
if ( devicePath.isEmpty() || mountPoint.isEmpty() ) if ( devicePath.isEmpty() || mountPoint.isEmpty() )
return -3; {
if ( devicePath.isEmpty() )
cWarning() << "Can't mount an empty device.";
if ( mountPoint.isEmpty() )
cWarning() << "Can't mount on an empty mountpoint.";
return static_cast<int>(ProcessResult::Code::NoWorkingDirectory);
}
QDir mountPointDir( mountPoint ); QDir mountPointDir( mountPoint );
if ( !mountPointDir.exists() ) if ( !mountPointDir.exists() )
{ {
bool ok = mountPointDir.mkpath( mountPoint ); bool ok = mountPointDir.mkpath( mountPoint );
if ( !ok ) if ( !ok )
return -3; {
cWarning() << "Could not create mountpoint" << mountPoint;
return static_cast<int>(ProcessResult::Code::NoWorkingDirectory);
}
} }
QString program( "mount" ); QString program( "mount" );
@ -146,15 +156,13 @@ System::runCommand(
{ {
QString output; QString output;
if ( !Calamares::JobQueue::instance() ) Calamares::GlobalStorage* gs = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr;
return -3;
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
if ( ( location == System::RunLocation::RunInTarget ) && if ( ( location == System::RunLocation::RunInTarget ) &&
( !gs || !gs->contains( "rootMountPoint" ) ) ) ( !gs || !gs->contains( "rootMountPoint" ) ) )
{ {
cWarning() << "No rootMountPoint in global storage"; cWarning() << "No rootMountPoint in global storage";
return -3; return ProcessResult::Code::NoWorkingDirectory;
} }
QProcess process; QProcess process;
@ -167,7 +175,7 @@ System::runCommand(
if ( !QDir( destDir ).exists() ) if ( !QDir( destDir ).exists() )
{ {
cWarning() << "rootMountPoint points to a dir which does not exist"; cWarning() << "rootMountPoint points to a dir which does not exist";
return -3; return ProcessResult::Code::NoWorkingDirectory;
} }
program = "chroot"; program = "chroot";
@ -189,8 +197,10 @@ System::runCommand(
if ( QDir( workingPath ).exists() ) if ( QDir( workingPath ).exists() )
process.setWorkingDirectory( QDir( workingPath ).absolutePath() ); process.setWorkingDirectory( QDir( workingPath ).absolutePath() );
else else
{
cWarning() << "Invalid working directory:" << workingPath; cWarning() << "Invalid working directory:" << workingPath;
return -3; return ProcessResult::Code::NoWorkingDirectory;
}
} }
cDebug() << "Running" << program << RedactedList( arguments ); cDebug() << "Running" << program << RedactedList( arguments );
@ -198,20 +208,20 @@ System::runCommand(
if ( !process.waitForStarted() ) if ( !process.waitForStarted() )
{ {
cWarning() << "Process failed to start" << process.error(); cWarning() << "Process failed to start" << process.error();
return -2; return ProcessResult::Code::FailedToStart;
} }
if ( !stdInput.isEmpty() ) if ( !stdInput.isEmpty() )
{ {
process.write( stdInput.toLocal8Bit() ); process.write( stdInput.toLocal8Bit() );
process.closeWriteChannel();
} }
process.closeWriteChannel();
if ( !process.waitForFinished( timeoutSec ? ( timeoutSec * 1000 ) : -1 ) ) if ( !process.waitForFinished( timeoutSec ? ( timeoutSec * 1000 ) : -1 ) )
{ {
cWarning().noquote().nospace() << "Timed out. Output so far:\n" << cWarning().noquote().nospace() << "Timed out. Output so far:\n" <<
process.readAllStandardOutput(); process.readAllStandardOutput();
return -4; return ProcessResult::Code::TimedOut;
} }
output.append( QString::fromLocal8Bit( process.readAllStandardOutput() ).trimmed() ); output.append( QString::fromLocal8Bit( process.readAllStandardOutput() ).trimmed() );
@ -219,12 +229,13 @@ System::runCommand(
if ( process.exitStatus() == QProcess::CrashExit ) if ( process.exitStatus() == QProcess::CrashExit )
{ {
cWarning().noquote().nospace() << "Process crashed. Output so far:\n" << output; cWarning().noquote().nospace() << "Process crashed. Output so far:\n" << output;
return -1; return ProcessResult::Code::Crashed;
} }
auto r = process.exitCode(); auto r = process.exitCode();
cDebug() << "Finished. Exit code:" << r; cDebug() << "Finished. Exit code:" << r;
if ( ( r != 0 ) || Calamares::Settings::instance()->debugMode() ) bool showDebug = ( !Calamares::Settings::instance() ) || ( Calamares::Settings::instance()->debugMode() );
if ( ( r != 0 ) || showDebug )
{ {
cDebug() << "Target cmd:" << RedactedList( args ); cDebug() << "Target cmd:" << RedactedList( args );
cDebug().noquote().nospace() << "Target output:\n" << output; cDebug().noquote().nospace() << "Target output:\n" << output;
@ -306,22 +317,22 @@ ProcessResult::explainProcess( int ec, const QString& command, const QString& ou
? QCoreApplication::translate( "ProcessResult", "\nThere was no output from the command.") ? QCoreApplication::translate( "ProcessResult", "\nThere was no output from the command.")
: (QCoreApplication::translate( "ProcessResult", "\nOutput:\n") + output); : (QCoreApplication::translate( "ProcessResult", "\nOutput:\n") + output);
if ( ec == -1 ) //Crash! if ( ec == static_cast<int>(ProcessResult::Code::Crashed) ) //Crash!
return JobResult::error( QCoreApplication::translate( "ProcessResult", "External command crashed." ), return JobResult::error( QCoreApplication::translate( "ProcessResult", "External command crashed." ),
QCoreApplication::translate( "ProcessResult", "Command <i>%1</i> crashed." ) QCoreApplication::translate( "ProcessResult", "Command <i>%1</i> crashed." )
.arg( command ) .arg( command )
+ outputMessage ); + outputMessage );
if ( ec == -2 ) if ( ec == static_cast<int>(ProcessResult::Code::FailedToStart) )
return JobResult::error( QCoreApplication::translate( "ProcessResult", "External command failed to start." ), return JobResult::error( QCoreApplication::translate( "ProcessResult", "External command failed to start." ),
QCoreApplication::translate( "ProcessResult", "Command <i>%1</i> failed to start." ) QCoreApplication::translate( "ProcessResult", "Command <i>%1</i> failed to start." )
.arg( command ) ); .arg( command ) );
if ( ec == -3 ) if ( ec == static_cast<int>(ProcessResult::Code::NoWorkingDirectory) )
return JobResult::error( QCoreApplication::translate( "ProcessResult", "Internal error when starting command." ), return JobResult::error( QCoreApplication::translate( "ProcessResult", "Internal error when starting command." ),
QCoreApplication::translate( "ProcessResult", "Bad parameters for process job call." ) ); QCoreApplication::translate( "ProcessResult", "Bad parameters for process job call." ) );
if ( ec == -4 ) if ( ec == static_cast<int>(ProcessResult::Code::TimedOut) )
return JobResult::error( QCoreApplication::translate( "ProcessResult", "External command failed to finish." ), return JobResult::error( QCoreApplication::translate( "ProcessResult", "External command failed to finish." ),
QCoreApplication::translate( "ProcessResult", "Command <i>%1</i> failed to finish in %2 seconds." ) QCoreApplication::translate( "ProcessResult", "Command <i>%1</i> failed to finish in %2 seconds." )
.arg( command ) .arg( command )

View File

@ -32,8 +32,16 @@ namespace CalamaresUtils
class ProcessResult : public QPair< int, QString > class ProcessResult : public QPair< int, QString >
{ {
public: public:
enum class Code : int
{
Crashed = -1, // Must match special return values from QProcess
FailedToStart = -2, // Must match special return values from QProcess
NoWorkingDirectory = -3,
TimedOut = -4
} ;
/** @brief Implicit one-argument constructor has no output, only a return code */ /** @brief Implicit one-argument constructor has no output, only a return code */
ProcessResult( int r ) : QPair< int, QString >( r, QString() ) {} ProcessResult( Code r ) : QPair< int, QString >( static_cast<int>(r), QString() ) {}
ProcessResult( int r, QString s ) : QPair< int, QString >( r, s ) {} ProcessResult( int r, QString s ) : QPair< int, QString >( r, s ) {}
int getExitCode() const { return first; } int getExitCode() const { return first; }
@ -93,9 +101,9 @@ public:
* @param filesystemName the name of the filesystem (optional). * @param filesystemName the name of the filesystem (optional).
* @param options any additional options as passed to mount -o (optional). * @param options any additional options as passed to mount -o (optional).
* @returns the program's exit code, or: * @returns the program's exit code, or:
* -1 = QProcess crash * Crashed = QProcess crash
* -2 = QProcess cannot start * FailedToStart = QProcess cannot start
* -3 = bad arguments * NoWorkingDirectory = bad arguments
*/ */
DLLEXPORT int mount( const QString& devicePath, DLLEXPORT int mount( const QString& devicePath,
const QString& mountPoint, const QString& mountPoint,
@ -120,10 +128,10 @@ public:
* *
* @returns the program's exit code and its output (if any). Special * @returns the program's exit code and its output (if any). Special
* exit codes (which will never have any output) are: * exit codes (which will never have any output) are:
* -1 = QProcess crash * Crashed = QProcess crash
* -2 = QProcess cannot start * FailedToStart = QProcess cannot start
* -3 = bad arguments * NoWorkingDirectory = bad arguments
* -4 = QProcess timeout * TimedOut = QProcess timeout
*/ */
static DLLEXPORT ProcessResult runCommand( static DLLEXPORT ProcessResult runCommand(
RunLocation location, RunLocation location,

View File

@ -78,6 +78,11 @@ constexpr int BytesToMiB( qint64 b )
return int( b / 1024 / 1024 ); return int( b / 1024 / 1024 );
} }
constexpr int BytesToGiB( qint64 b )
{
return int( b / 1024 / 1024 / 1024 );
}
constexpr qint64 alignBytesToBlockSize( qint64 bytes, qint64 blocksize ) constexpr qint64 alignBytesToBlockSize( qint64 bytes, qint64 blocksize )
{ {
qint64 blocks = bytes / blocksize; qint64 blocks = bytes / blocksize;

View File

@ -283,18 +283,35 @@ ViewManager::next()
} }
m_currentStep++; m_currentStep++;
m_stack->setCurrentIndex( m_currentStep );
m_stack->setCurrentIndex( m_currentStep ); // Does nothing if out of range
step->onLeave(); step->onLeave();
m_steps.at( m_currentStep )->onActivate();
executing = qobject_cast< ExecutionViewStep* >( m_steps.at( m_currentStep ) ) != nullptr; if ( m_currentStep < m_steps.count() )
emit currentStepChanged(); {
m_steps.at( m_currentStep )->onActivate();
executing = qobject_cast< ExecutionViewStep* >( m_steps.at( m_currentStep ) ) != nullptr;
emit currentStepChanged();
}
else
{
// Reached the end in a weird state (e.g. no finished step after an exec)
executing = false;
m_next->setEnabled( false );
m_back->setEnabled( false );
}
updateCancelEnabled( !settings->disableCancel() && !(executing && settings->disableCancelDuringExec() ) ); updateCancelEnabled( !settings->disableCancel() && !(executing && settings->disableCancelDuringExec() ) );
} }
else else
{
step->next(); step->next();
}
m_next->setEnabled( !executing && m_steps.at( m_currentStep )->isNextEnabled() ); if ( m_currentStep < m_steps.count() )
m_back->setEnabled( !executing && m_steps.at( m_currentStep )->isBackEnabled() ); {
m_next->setEnabled( !executing && m_steps.at( m_currentStep )->isNextEnabled() );
m_back->setEnabled( !executing && m_steps.at( m_currentStep )->isBackEnabled() );
}
updateButtonLabels(); updateButtonLabels();
} }
@ -320,7 +337,7 @@ ViewManager::updateButtonLabels()
else else
m_next->setText( tr( "&Next" ) ); m_next->setText( tr( "&Next" ) );
if ( m_currentStep == m_steps.count() -1 && m_steps.last()->isAtEnd() ) if ( isAtVeryEnd() )
{ {
m_quit->setText( tr( "&Done" ) ); m_quit->setText( tr( "&Done" ) );
m_quit->setToolTip( complete ); m_quit->setToolTip( complete );
@ -368,7 +385,7 @@ bool ViewManager::confirmCancelInstallation()
const auto* const settings = Calamares::Settings::instance(); const auto* const settings = Calamares::Settings::instance();
// When we're at the very end, then it's always OK to exit. // When we're at the very end, then it's always OK to exit.
if ( m_currentStep == m_steps.count() -1 && m_steps.last()->isAtEnd() ) if ( isAtVeryEnd() )
return true; return true;
// Not at the very end, cancel/quit might be disabled // Not at the very end, cancel/quit might be disabled

View File

@ -130,7 +130,12 @@ private:
void insertViewStep( int before, ViewStep* step ); void insertViewStep( int before, ViewStep* step );
void updateButtonLabels(); void updateButtonLabels();
void updateCancelEnabled( bool enabled ); void updateCancelEnabled( bool enabled );
bool isAtVeryEnd() const
{
return ( m_currentStep >= m_steps.count() ) || ( m_currentStep == m_steps.count() - 1 && m_steps.last()->isAtEnd() );
}
static ViewManager* s_instance; static ViewManager* s_instance;
ViewStepList m_steps; ViewStepList m_steps;

View File

@ -4,16 +4,16 @@
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
# #
# Translators: # Translators:
# Zmicer Turok <zmicerturok@gmail.com>, 2018 # Zmicer Turok <nashtlumach@gmail.com>, 2018
# #
#, fuzzy #, fuzzy
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-10-05 11:34-0400\n" "POT-Creation-Date: 2019-05-10 19:18-0400\n"
"PO-Revision-Date: 2016-12-16 12:18+0000\n" "PO-Revision-Date: 2016-12-16 12:18+0000\n"
"Last-Translator: Zmicer Turok <zmicerturok@gmail.com>, 2018\n" "Last-Translator: Zmicer Turok <nashtlumach@gmail.com>, 2018\n"
"Language-Team: Belarusian (https://www.transifex.com/calamares/teams/20061/be/)\n" "Language-Team: Belarusian (https://www.transifex.com/calamares/teams/20061/be/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"

View File

@ -83,13 +83,14 @@ size: 100%
atleast: 600MiB atleast: 600MiB
)" ); )" );
j.setConfigurationMap( CalamaresUtils::yamlMapToVariant( doc0 ).toMap() ); j.setConfigurationMap( CalamaresUtils::yamlMapToVariant( doc0 ).toMap() );
QVERIFY( j.name().isEmpty() ); QVERIFY( !j.name().isEmpty() );
QCOMPARE( j.name(), QString("/") );
QCOMPARE( j.size().unit(), SizeUnit::Percent ); QCOMPARE( j.size().unit(), SizeUnit::Percent );
QCOMPARE( j.minimumSize().unit(), SizeUnit::MiB ); QCOMPARE( j.minimumSize().unit(), SizeUnit::MiB );
QCOMPARE( j.size().value(), 100 ); QCOMPARE( j.size().value(), 100 );
QCOMPARE( j.minimumSize().value(), 600 ); QCOMPARE( j.minimumSize().value(), 600 );
// Silly config // Silly config has bad atleast value
doc0 = YAML::Load( R"(--- doc0 = YAML::Load( R"(---
fs: / fs: /
dev: /dev/m00 dev: /dev/m00
@ -98,12 +99,27 @@ atleast: 127 %
)" ); )" );
j.setConfigurationMap( CalamaresUtils::yamlMapToVariant( doc0 ).toMap() ); j.setConfigurationMap( CalamaresUtils::yamlMapToVariant( doc0 ).toMap() );
QVERIFY( !j.name().isEmpty() ); QVERIFY( !j.name().isEmpty() );
QCOMPARE( j.name(), QString("/") );
QCOMPARE( j.size().unit(), SizeUnit::MiB ); QCOMPARE( j.size().unit(), SizeUnit::MiB );
QCOMPARE( j.minimumSize().unit(), SizeUnit::None ); QCOMPARE( j.minimumSize().unit(), SizeUnit::None );
QCOMPARE( j.size().value(), 72 ); QCOMPARE( j.size().value(), 72 );
QCOMPARE( j.minimumSize().value(), 0 ); QCOMPARE( j.minimumSize().value(), 0 );
// Silly config // Silly config has bad atleast value
doc0 = YAML::Load( R"(---
dev: /dev/m00
size: 72 MiB
atleast: 127 %
)" );
j.setConfigurationMap( CalamaresUtils::yamlMapToVariant( doc0 ).toMap() );
QVERIFY( !j.name().isEmpty() );
QCOMPARE( j.name(), QString("/dev/m00") );
QCOMPARE( j.size().unit(), SizeUnit::MiB );
QCOMPARE( j.minimumSize().unit(), SizeUnit::None );
QCOMPARE( j.size().value(), 72 );
QCOMPARE( j.minimumSize().value(), 0 );
// Normal config
doc0 = YAML::Load( R"(--- doc0 = YAML::Load( R"(---
fs: / fs: /
# dev: /dev/m00 # dev: /dev/m00
@ -111,7 +127,8 @@ size: 71MiB
# atleast: 127% # atleast: 127%
)" ); )" );
j.setConfigurationMap( CalamaresUtils::yamlMapToVariant( doc0 ).toMap() ); j.setConfigurationMap( CalamaresUtils::yamlMapToVariant( doc0 ).toMap() );
QVERIFY( j.name().isEmpty() ); QVERIFY( !j.name().isEmpty() );
QCOMPARE( j.name(), QString("/") );
QCOMPARE( j.size().unit(), SizeUnit::MiB ); QCOMPARE( j.size().unit(), SizeUnit::MiB );
QCOMPARE( j.minimumSize().unit(), SizeUnit::None ); QCOMPARE( j.minimumSize().unit(), SizeUnit::None );
QCOMPARE( j.size().value(), 71 ); QCOMPARE( j.size().value(), 71 );

View File

@ -62,37 +62,55 @@ convenienceName( const Partition* const candidate )
return p; return p;
} }
/** @brief Get the globalStorage setting for required space. */
static double
getRequiredStorageGiB( bool& ok )
{
return Calamares::JobQueue::instance()->globalStorage()->value( "requiredStorageGiB" ).toDouble( &ok );
}
bool bool
canBeReplaced( Partition* candidate ) canBeReplaced( Partition* candidate )
{ {
if ( !candidate ) if ( !candidate )
{
cDebug() << "Partition* is NULL";
return false; return false;
}
cDebug() << "Checking if" << convenienceName( candidate ) << "can be replaced.";
if ( candidate->isMounted() ) if ( candidate->isMounted() )
{
cDebug() << Logger::SubEntry << "NO, it is mounted.";
return false; return false;
}
bool ok = false; bool ok = false;
double requiredStorageGB = Calamares::JobQueue::instance() double requiredStorageGiB = getRequiredStorageGiB( ok );
->globalStorage() if ( !ok )
->value( "requiredStorageGiB" ) {
.toDouble( &ok ); cDebug() << Logger::SubEntry << "NO, requiredStorageGiB is not set correctly.";
return false;
}
qint64 availableStorageB = candidate->capacity(); qint64 availableStorageB = candidate->capacity();
qint64 requiredStorageB = ( requiredStorageGB + 0.5 ) * 1024 * 1024 * 1024; qint64 requiredStorageB = CalamaresUtils::GiBtoBytes( requiredStorageGiB + 0.5 );
cDebug() << "Required storage B:" << requiredStorageB
<< QString( "(%1GB)" ).arg( requiredStorageB / 1024 / 1024 / 1024 );
cDebug() << "Storage capacity B:" << availableStorageB
<< QString( "(%1GB)" ).arg( availableStorageB / 1024 / 1024 / 1024 )
<< "for" << convenienceName( candidate ) << " length:" << candidate->length();
if ( ok && if ( availableStorageB > requiredStorageB )
availableStorageB > requiredStorageB )
{ {
cDebug() << "Partition" << convenienceName( candidate ) << "authorized for replace install."; cDebug() << "Partition" << convenienceName( candidate ) << "authorized for replace install.";
return true; return true;
} }
return false; else
{
Logger::CDebug deb;
deb << Logger::SubEntry << "NO, insufficient storage";
deb << Logger::Continuation << "Required storage B:" << requiredStorageB
<< QString( "(%1GiB)" ).arg( requiredStorageGiB );
deb << Logger::Continuation << "Available storage B:" << availableStorageB
<< QString( "(%1GiB)" ).arg( CalamaresUtils::BytesToGiB( availableStorageB ) );
return false;
}
} }
@ -144,40 +162,35 @@ canBeResized( Partition* candidate )
} }
bool ok = false; bool ok = false;
double requiredStorageGB = Calamares::JobQueue::instance() double requiredStorageGiB = getRequiredStorageGiB( ok );
->globalStorage() if ( !ok )
->value( "requiredStorageGiB" ) {
.toDouble( &ok ); cDebug() << Logger::SubEntry << "NO, requiredStorageGiB is not set correctly.";
return false;
}
// We require a little more for partitioning overhead and swap file // We require a little more for partitioning overhead and swap file
double advisedStorageGB = requiredStorageGB + 0.5 + 2.0; double advisedStorageGiB = requiredStorageGiB + 0.5 + 2.0;
qint64 availableStorageB = candidate->available(); qint64 availableStorageB = candidate->available();
qint64 advisedStorageB = CalamaresUtils::GiBtoBytes( advisedStorageGiB );
qint64 advisedStorageB = CalamaresUtils::GiBtoBytes( advisedStorageGB ); if ( availableStorageB > advisedStorageB )
if ( ok &&
availableStorageB > advisedStorageB )
{ {
cDebug() << "Partition" << convenienceName( candidate ) << "authorized for resize + autopartition install."; cDebug() << "Partition" << convenienceName( candidate ) << "authorized for resize + autopartition install.";
return true; return true;
} }
else if ( ok ) else
{ {
Logger::CDebug deb; Logger::CDebug deb;
deb << Logger::SubEntry << "NO, insufficient storage"; deb << Logger::SubEntry << "NO, insufficient storage";
deb << Logger::Continuation << "Required storage B:" << advisedStorageB deb << Logger::Continuation << "Required storage B:" << advisedStorageB
<< QString( "(%1GB)" ).arg( advisedStorageGB ); << QString( "(%1GiB)" ).arg( advisedStorageGiB );
deb << Logger::Continuation << "Available storage B:" << availableStorageB deb << Logger::Continuation << "Available storage B:" << availableStorageB
<< QString( "(%1GB)" ).arg( availableStorageB / 1024 / 1024 / 1024 ) << QString( "(%1GiB)" ).arg( CalamaresUtils::BytesToGiB( availableStorageB ) )
<< "for" << convenienceName( candidate ) << "length:" << candidate->length() << "for" << convenienceName( candidate ) << "length:" << candidate->length()
<< "sectorsUsed:" << candidate->sectorsUsed() << "fsType:" << candidate->fileSystem().name(); << "sectorsUsed:" << candidate->sectorsUsed() << "fsType:" << candidate->fileSystem().name();
return false; return false;
} }
else
{
cDebug() << Logger::SubEntry << "NO, requiredStorageGB is not set correctly.";
return false;
}
} }

View File

@ -69,6 +69,7 @@ PartitionViewStep::PartitionViewStep( QObject* parent )
, m_widget( new QStackedWidget() ) , m_widget( new QStackedWidget() )
, m_choicePage( nullptr ) , m_choicePage( nullptr )
, m_manualPartitionPage( nullptr ) , m_manualPartitionPage( nullptr )
, m_requiredStorageGiB( 0.0 )
{ {
m_widget->setContentsMargins( 0, 0, 0, 0 ); m_widget->setContentsMargins( 0, 0, 0, 0 );
@ -371,6 +372,14 @@ PartitionViewStep::isAtEnd() const
void void
PartitionViewStep::onActivate() PartitionViewStep::onActivate()
{ {
// If there's no setting (e.g. from the welcome page) for required storage
// then use ours, if it was set.
auto* gs = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr;
if ( m_requiredStorageGiB >= 0.0 && gs && !gs->contains( "requiredStorageGiB" ) )
{
gs->insert( "requiredStorageGiB", m_requiredStorageGiB );
}
// if we're coming back to PVS from the next VS // if we're coming back to PVS from the next VS
if ( m_widget->currentWidget() == m_choicePage && if ( m_widget->currentWidget() == m_choicePage &&
m_choicePage->currentChoice() == ChoicePage::Alongside ) m_choicePage->currentChoice() == ChoicePage::Alongside )
@ -564,6 +573,9 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap )
m_swapChoices = choices; m_swapChoices = choices;
// Settings that overlap with the Welcome module
m_requiredStorageGiB = CalamaresUtils::getDouble( configurationMap, "requiredStorage", -1.0 );
// These gs settings seem to be unused (in upstream Calamares) outside of // These gs settings seem to be unused (in upstream Calamares) outside of
// the partition module itself. // the partition module itself.
gs->insert( "ensureSuspendToDisk", ensureSuspendToDisk ); gs->insert( "ensureSuspendToDisk", ensureSuspendToDisk );

View File

@ -86,6 +86,8 @@ private:
QFutureWatcher<void>* m_future; QFutureWatcher<void>* m_future;
QSet< PartitionActions::Choices::SwapChoice > m_swapChoices; QSet< PartitionActions::Choices::SwapChoice > m_swapChoices;
qreal m_requiredStorageGiB; // May duplicate setting in the welcome module
}; };
CALAMARES_PLUGIN_FACTORY_DECLARATION( PartitionViewStepFactory ) CALAMARES_PLUGIN_FACTORY_DECLARATION( PartitionViewStepFactory )

View File

@ -120,3 +120,15 @@ defaultFileSystemType: "ext4"
# % of the available drive space if a '%' is appended to the value # % of the available drive space if a '%' is appended to the value
# - minSize: minimum partition size (optional parameter) # - minSize: minimum partition size (optional parameter)
# - maxSize: maximum partition size (optional parameter) # - maxSize: maximum partition size (optional parameter)
# Checking for available storage
#
# This overlaps with the setting of the same name in the welcome module's
# requirements section. If nothing is set by the welcome module, this
# value is used instead. It is still a problem if there is no required
# size set at all, and the replace and resize options will not be offered
# if no required size is set.
#
# The value is in Gibibytes (GiB).
#
# requiredStorage: 3.5