Compare commits
4 Commits
v3.3.11
...
issue-2321
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
810f8d7081 | ||
|
|
e59e916405 | ||
|
|
cf4d2d432f | ||
|
|
38dfbdccf3 |
@@ -19,10 +19,7 @@
|
||||
#include <QtDBus/QDBusInterface>
|
||||
#include <QtDBus/QDBusReply>
|
||||
|
||||
const NamedEnumTable< Config::RestartMode >&
|
||||
restartModes()
|
||||
{
|
||||
using M = Config::RestartMode;
|
||||
#if 0
|
||||
static const NamedEnumTable< M > table { { "never", M::Never },
|
||||
{ "user-unchecked", M::UserDefaultUnchecked },
|
||||
{ "unchecked", M::UserDefaultUnchecked },
|
||||
@@ -31,91 +28,37 @@ restartModes()
|
||||
{ "always", M::Always }
|
||||
|
||||
};
|
||||
return table;
|
||||
}
|
||||
#endif
|
||||
|
||||
Config::Config( QObject* parent )
|
||||
: QObject( parent )
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Config::setRestartNowMode( Config::RestartMode m )
|
||||
{
|
||||
// Can only go "down" in state (Always > UserDefaultChecked > .. > Never)
|
||||
if ( m > m_restartNowMode )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If changing to an unconditional mode, also set other flag
|
||||
if ( m == RestartMode::Always || m == RestartMode::Never )
|
||||
{
|
||||
setRestartNowWanted( m == RestartMode::Always );
|
||||
}
|
||||
|
||||
if ( m != m_restartNowMode )
|
||||
{
|
||||
m_restartNowMode = m;
|
||||
emit restartModeChanged( m );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Config::setRestartNowWanted( bool w )
|
||||
{
|
||||
// Follow the mode which may affect @p w
|
||||
if ( m_restartNowMode == RestartMode::Always )
|
||||
{
|
||||
w = true;
|
||||
}
|
||||
if ( m_restartNowMode == RestartMode::Never )
|
||||
{
|
||||
w = false;
|
||||
}
|
||||
|
||||
if ( w != m_userWantsRestart )
|
||||
{
|
||||
m_userWantsRestart = w;
|
||||
emit restartNowWantedChanged( w );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Config::onInstallationFailed( const QString& message, const QString& details )
|
||||
{
|
||||
const bool msgChange = message != m_failureMessage;
|
||||
const bool detChange = details != m_failureDetails;
|
||||
const bool messageChange = message != m_failureMessage;
|
||||
const bool detailsChange = details != m_failureDetails;
|
||||
m_failureMessage = message;
|
||||
m_failureDetails = details;
|
||||
if ( msgChange )
|
||||
if ( messageChange )
|
||||
{
|
||||
emit failureMessageChanged( message );
|
||||
}
|
||||
if ( detChange )
|
||||
if ( detailsChange )
|
||||
{
|
||||
emit failureDetailsChanged( message );
|
||||
}
|
||||
if ( ( msgChange || detChange ) )
|
||||
if ( ( messageChange || detailsChange ) )
|
||||
{
|
||||
emit failureChanged( hasFailed() );
|
||||
if ( hasFailed() )
|
||||
{
|
||||
setRestartNowMode( Config::RestartMode::Never );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Config::doRestart( bool restartAnyway )
|
||||
Config::doRestart()
|
||||
{
|
||||
cDebug() << "mode=" << restartModes().find( restartNowMode() ) << " user wants restart?" << restartNowWanted()
|
||||
<< "force restart?" << restartAnyway;
|
||||
if ( restartNowMode() != RestartMode::Never && restartAnyway )
|
||||
{
|
||||
cDebug() << Logger::SubEntry << "Running restart command" << m_restartNowCommand;
|
||||
QProcess::execute( "/bin/sh", { "-c", m_restartNowCommand } );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -175,56 +118,94 @@ Config::doNotify( bool hasFailed, bool sendAnyway )
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Config::setConfigurationMap( const QVariantMap& configurationMap )
|
||||
using Choices = int;
|
||||
|
||||
static Choices loadLive(bool isSelected)
|
||||
{
|
||||
RestartMode mode = RestartMode::Never;
|
||||
return isSelected ? 1 : 0;
|
||||
}
|
||||
|
||||
//TODO:3.3 remove deprecated restart settings
|
||||
QString restartMode = Calamares::getString( configurationMap, "restartNowMode" );
|
||||
if ( restartMode.isEmpty() )
|
||||
static Choices loadRestart(bool isSelected, const QString & /* command */ )
|
||||
{
|
||||
return isSelected ? 1 : 0;
|
||||
}
|
||||
|
||||
static Choices loadFromV3(const QVariantList & items, const QString & defaultChoice )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Choices loadFromV2(const QString & restartNowMode, const QString & restartNowCommand)
|
||||
{
|
||||
if (restartNowMode == QStringLiteral( "never"))
|
||||
{
|
||||
if ( configurationMap.contains( "restartNowEnabled" ) )
|
||||
{
|
||||
cWarning() << "Configuring the finished module with deprecated restartNowEnabled settings";
|
||||
}
|
||||
return loadLive(true);
|
||||
}
|
||||
|
||||
bool restartNowEnabled = Calamares::getBool( configurationMap, "restartNowEnabled", false );
|
||||
bool restartNowChecked = Calamares::getBool( configurationMap, "restartNowChecked", false );
|
||||
// Empty if not specified, defaults to user-unchecked according to the suggested config
|
||||
if (restartNowMode == QStringLiteral("user-unchecked") || restartNowMode == QStringLiteral("unchecked") || restartNowMode.isEmpty())
|
||||
{
|
||||
Choices c = loadLive(true);
|
||||
c += loadRestart(false, restartNowCommand);
|
||||
return c;
|
||||
}
|
||||
|
||||
if ( !restartNowEnabled )
|
||||
{
|
||||
mode = RestartMode::Never;
|
||||
}
|
||||
else
|
||||
{
|
||||
mode = restartNowChecked ? RestartMode::UserDefaultChecked : RestartMode::UserDefaultUnchecked;
|
||||
}
|
||||
if (restartNowMode == QStringLiteral("user-checked") || restartNowMode == QStringLiteral("checked"))
|
||||
{
|
||||
Choices c = loadLive(false);
|
||||
c += loadRestart(true, restartNowCommand);
|
||||
return c;
|
||||
}
|
||||
|
||||
if (restartNowMode == QStringLiteral("always"))
|
||||
{
|
||||
return loadRestart(true, restartNowCommand);
|
||||
}
|
||||
|
||||
cError() << "Unknown v2 restart mode" << restartNowMode << "using 'never'";
|
||||
return loadLive(true);
|
||||
}
|
||||
|
||||
static Choices loadFromV1(bool restartNowEnabled, bool restartNowChecked, const QString & restartNowCommand)
|
||||
{
|
||||
if (!restartNowEnabled)
|
||||
{
|
||||
return loadFromV2( QStringLiteral("never"), QString());
|
||||
}
|
||||
if (restartNowChecked)
|
||||
{
|
||||
return loadFromV2( QStringLiteral("user-checked"), restartNowCommand);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool ok = false;
|
||||
mode = restartModes().find( restartMode, ok );
|
||||
if ( !ok )
|
||||
{
|
||||
cWarning() << "Configuring the finished module with bad restartNowMode" << restartMode;
|
||||
}
|
||||
return loadFromV2( QStringLiteral("user-unchecked"), restartNowCommand);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Config::setConfigurationMap( const QVariantMap& configurationMap )
|
||||
{
|
||||
m_notifyOnFinished = Calamares::getBool( configurationMap, "notifyOnFinished", false );
|
||||
|
||||
const auto v1Enabled = QStringLiteral( "restartNowEnabled" );
|
||||
const auto v1Checked = QStringLiteral( "restartNowChecked" );
|
||||
|
||||
const auto v2Mode = QStringLiteral("restartNowMode");
|
||||
const auto v2Command = QStringLiteral("restartNowCommand");
|
||||
|
||||
if(configurationMap.contains( v1Enabled) || configurationMap.contains(v1Checked))
|
||||
{
|
||||
cWarning() << "Configuration uses v1 settings" << v1Enabled << "and" << v1Checked;
|
||||
loadFromV1(Calamares::getBool(configurationMap, v1Enabled, true), Calamares::getBool(configurationMap, v1Checked, false), Calamares::getString(configurationMap, v2Command));
|
||||
}
|
||||
else if(configurationMap.contains( v2Mode) || configurationMap.contains(v2Command))
|
||||
{
|
||||
cWarning() << "Configuration uses v2 settings" << v2Mode << "and" << v2Command;
|
||||
loadFromV2(Calamares::getString(configurationMap, v2Mode, QStringLiteral("user-unchecked")), Calamares::getString(configurationMap, v2Command));
|
||||
}
|
||||
else
|
||||
{
|
||||
loadFromV3(Calamares::getList(configurationMap, QStringLiteral("choices")), Calamares::getString(configurationMap, QStringLiteral("defaultChoice")));
|
||||
}
|
||||
|
||||
m_restartNowMode = mode;
|
||||
m_userWantsRestart = ( mode == RestartMode::Always || mode == RestartMode::UserDefaultChecked );
|
||||
emit restartModeChanged( m_restartNowMode );
|
||||
emit restartNowWantedChanged( m_userWantsRestart );
|
||||
|
||||
if ( mode != RestartMode::Never )
|
||||
{
|
||||
QString restartNowCommand = Calamares::getString( configurationMap, "restartNowCommand" );
|
||||
if ( restartNowCommand.isEmpty() )
|
||||
{
|
||||
restartNowCommand = QStringLiteral( "shutdown -r now" );
|
||||
}
|
||||
m_restartNowCommand = restartNowCommand;
|
||||
}
|
||||
|
||||
m_notifyOnFinished = Calamares::getBool( configurationMap, "notifyOnFinished", false );
|
||||
}
|
||||
|
||||
@@ -18,10 +18,6 @@ class Config : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY( RestartMode restartNowMode READ restartNowMode WRITE setRestartNowMode NOTIFY restartModeChanged )
|
||||
Q_PROPERTY( bool restartNowWanted READ restartNowWanted WRITE setRestartNowWanted NOTIFY restartNowWantedChanged )
|
||||
|
||||
Q_PROPERTY( QString restartNowCommand READ restartNowCommand CONSTANT FINAL )
|
||||
Q_PROPERTY( bool notifyOnFinished READ notifyOnFinished CONSTANT FINAL )
|
||||
|
||||
Q_PROPERTY( QString failureMessage READ failureMessage NOTIFY failureMessageChanged )
|
||||
@@ -31,32 +27,9 @@ class Config : public QObject
|
||||
public:
|
||||
Config( QObject* parent = nullptr );
|
||||
|
||||
enum class RestartMode
|
||||
{
|
||||
Never,
|
||||
UserDefaultUnchecked,
|
||||
UserDefaultChecked,
|
||||
Always
|
||||
};
|
||||
Q_ENUM( RestartMode )
|
||||
|
||||
void setConfigurationMap( const QVariantMap& configurationMap );
|
||||
|
||||
public Q_SLOTS:
|
||||
RestartMode restartNowMode() const { return m_restartNowMode; }
|
||||
void setRestartNowMode( RestartMode m );
|
||||
|
||||
bool restartNowWanted() const
|
||||
{
|
||||
if ( restartNowMode() == RestartMode::Never )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return ( restartNowMode() == RestartMode::Always ) || m_userWantsRestart;
|
||||
}
|
||||
void setRestartNowWanted( bool w );
|
||||
|
||||
QString restartNowCommand() const { return m_restartNowCommand; }
|
||||
bool notifyOnFinished() const { return m_notifyOnFinished; }
|
||||
|
||||
QString failureMessage() const { return m_failureMessage; }
|
||||
@@ -64,23 +37,6 @@ public Q_SLOTS:
|
||||
/// Failure is if any of the failure messages is non-empty
|
||||
bool hasFailed() const { return !m_failureMessage.isEmpty() || !m_failureDetails.isEmpty(); }
|
||||
|
||||
/** @brief Run the restart command, if desired.
|
||||
*
|
||||
* This should generally not be called somewhere during the
|
||||
* application's execution, but only in response to QApplication::quit()
|
||||
* or something like that when the user expects the system to restart.
|
||||
*
|
||||
* The "if desired" part is: only if the restart mode allows it,
|
||||
* **and** the user has checked the box (or done whatever to
|
||||
* turn on restartNowWanted()).
|
||||
*
|
||||
* - The one-argument form ignores what the user wants and restarts
|
||||
* if @p restartAnyway is @c true **unless** the mode is Never
|
||||
* - The no-argument form uses the user setting
|
||||
*/
|
||||
void doRestart( bool restartAnyway );
|
||||
void doRestart() { doRestart( restartNowWanted() ); }
|
||||
|
||||
/** @brief Send DBus notification
|
||||
*
|
||||
* At the end of installation (when the FinishedViewStep is activated),
|
||||
@@ -105,18 +61,16 @@ public Q_SLOTS:
|
||||
*/
|
||||
void onInstallationFailed( const QString& message, const QString& details );
|
||||
|
||||
signals:
|
||||
void restartModeChanged( RestartMode m );
|
||||
void restartNowWantedChanged( bool w );
|
||||
/// @brief Does whatever restart-action is selected / configured
|
||||
void doRestart();
|
||||
|
||||
Q_SIGNALS:
|
||||
void failureMessageChanged( const QString& );
|
||||
void failureDetailsChanged( const QString& );
|
||||
void failureChanged( bool );
|
||||
|
||||
private:
|
||||
// Configuration parts
|
||||
QString m_restartNowCommand;
|
||||
RestartMode m_restartNowMode = RestartMode::Never;
|
||||
bool m_userWantsRestart = false;
|
||||
bool m_notifyOnFinished = false;
|
||||
|
||||
// Dynamic parts
|
||||
@@ -125,6 +79,4 @@ private:
|
||||
QString m_failureDetails;
|
||||
};
|
||||
|
||||
const NamedEnumTable< Config::RestartMode >& restartModes();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -31,20 +31,6 @@ FinishedPage::FinishedPage( Config* config, QWidget* parent )
|
||||
ui->mainText->setWordWrap( true );
|
||||
ui->mainText->setOpenExternalLinks( true );
|
||||
|
||||
connect( config,
|
||||
&Config::restartModeChanged,
|
||||
[ this ]( Config::RestartMode mode )
|
||||
{
|
||||
using Mode = Config::RestartMode;
|
||||
|
||||
ui->restartCheckBox->setVisible( mode != Mode::Never );
|
||||
ui->restartCheckBox->setEnabled( mode != Mode::Always );
|
||||
} );
|
||||
connect( config, &Config::restartNowWantedChanged, ui->restartCheckBox, &QCheckBox::setChecked );
|
||||
connect( ui->restartCheckBox,
|
||||
&QCheckBox::stateChanged,
|
||||
[ config ]( int state ) { config->setRestartNowWanted( state != 0 ); } );
|
||||
|
||||
CALAMARES_RETRANSLATE_SLOT( &FinishedPage::retranslate );
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
# checkbox is shown by restartNowEnabled.
|
||||
# restartNowChecked: false
|
||||
|
||||
# DEPRECATED
|
||||
#
|
||||
# Behavior of the "restart system now" button.
|
||||
#
|
||||
# There are four usable values:
|
||||
@@ -34,14 +36,60 @@
|
||||
# This is new behavior.
|
||||
#
|
||||
# The three combinations of legacy values are still supported.
|
||||
restartNowMode: user-unchecked
|
||||
#
|
||||
# restartNowMode: user-unchecked
|
||||
|
||||
# DEPRECATED
|
||||
#
|
||||
# If the checkbox is shown, and the checkbox is checked, then when
|
||||
# Calamares exits from the finished-page it will run this command.
|
||||
# If not set, falls back to "shutdown -r now".
|
||||
restartNowCommand: "systemctl -i reboot"
|
||||
#
|
||||
# restartNowCommand: "systemctl -i reboot"
|
||||
|
||||
# When the last page is (successfully) reached, send a DBus notification
|
||||
# to the desktop that the installation is done. This works only if the
|
||||
# user as whom Calamares is run, can reach the regular desktop session bus.
|
||||
notifyOnFinished: false
|
||||
|
||||
# Choices displayed for the last page: this is a list of items. Each item
|
||||
# has a name. There are known names "live", "reboot" and "poweroff", but
|
||||
# you can add others. Each item also has an optional subkey "commands"
|
||||
# which is a list of commands -- see *shellprocess* for details. It is
|
||||
# legal to have an empty list of commands, written []. The known names
|
||||
# "live", "reboot" and "poweroff" have default-values for the commands,
|
||||
# other names will need a specific command.
|
||||
#
|
||||
# If nothing is specified for "choices", the default value is ["live", "reboot"]
|
||||
choices:
|
||||
- name: "live"
|
||||
commands: []
|
||||
- name: "reboot"
|
||||
commands:
|
||||
- "systemctl -i reboot"
|
||||
- name: "poweroff"
|
||||
commands:
|
||||
- "sync ; sleep 1"
|
||||
- "halt -p"
|
||||
|
||||
# Selects one of the choices -- by name -- from the list above.
|
||||
# If nothing is specified, or a name that does not exist in the list,
|
||||
# then no choice is specified and the user must select one before continuing.
|
||||
#
|
||||
defaultChoice: "live"
|
||||
|
||||
# Mapping restartNowMode values to choices:
|
||||
# - "never" means choices: ["live"] defaultChoice: "live"
|
||||
# - "user-unchecked" is equivalent to this:
|
||||
# choices: ["live", "reboot"]
|
||||
# defaultChoice: "live"
|
||||
# - "user-checked" is equivalent to the same configuration, but
|
||||
# choices: ["live", "reboot"]
|
||||
# defaultChoice: "reboot"
|
||||
# - "always" is equivalent to
|
||||
# choices: ["reboot"]
|
||||
# defaultChoice: "reboot"
|
||||
#
|
||||
# Mapping restartNowCommand to choices: this sets the value of
|
||||
# *commands* for the "reboot" item (if there is one) to a one-item
|
||||
# list with the specified command.
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
# SPDX-FileCopyrightText: 2021 Anke Boersma <demm@kaosx.us>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
#
|
||||
|
||||
# NOTE: finishedq module uses a different configuration from what
|
||||
# the finished module uses and is not compatible with
|
||||
# with the configurable shutdown actions.
|
||||
if(NOT WITH_QML)
|
||||
calamares_skip_module( "finishedq (QML is not supported in this build)" )
|
||||
return()
|
||||
@@ -14,15 +18,12 @@ if(NOT TARGET ${qtname}::DBus OR NOT TARGET ${qtname}::Network)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(_finished ${CMAKE_CURRENT_SOURCE_DIR}/../finished)
|
||||
include_directories(${_finished})
|
||||
|
||||
calamares_add_plugin(finishedq
|
||||
TYPE viewmodule
|
||||
EXPORT_MACRO PLUGINDLLEXPORT_PRO
|
||||
SOURCES
|
||||
FinishedQmlViewStep.cpp
|
||||
${_finished}/Config.cpp
|
||||
Config.cpp
|
||||
RESOURCES
|
||||
finishedq${QT_VERSION_SUFFIX}.qrc
|
||||
LINK_PRIVATE_LIBRARIES
|
||||
|
||||
230
src/modules/finishedq/Config.cpp
Normal file
230
src/modules/finishedq/Config.cpp
Normal file
@@ -0,0 +1,230 @@
|
||||
/* === This file is part of Calamares - <https://calamares.io> ===
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2021 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* Calamares is Free Software: see the License-Identifier above.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#include "Branding.h"
|
||||
#include "Settings.h"
|
||||
#include "utils/Logger.h"
|
||||
#include "utils/Variant.h"
|
||||
|
||||
#include <QProcess>
|
||||
#include <QtDBus/QDBusConnection>
|
||||
#include <QtDBus/QDBusInterface>
|
||||
#include <QtDBus/QDBusReply>
|
||||
|
||||
const NamedEnumTable< Config::RestartMode >&
|
||||
restartModes()
|
||||
{
|
||||
using M = Config::RestartMode;
|
||||
static const NamedEnumTable< M > table { { "never", M::Never },
|
||||
{ "user-unchecked", M::UserDefaultUnchecked },
|
||||
{ "unchecked", M::UserDefaultUnchecked },
|
||||
{ "user-checked", M::UserDefaultChecked },
|
||||
{ "checked", M::UserDefaultChecked },
|
||||
{ "always", M::Always }
|
||||
|
||||
};
|
||||
return table;
|
||||
}
|
||||
|
||||
Config::Config( QObject* parent )
|
||||
: QObject( parent )
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Config::setRestartNowMode( Config::RestartMode m )
|
||||
{
|
||||
// Can only go "down" in state (Always > UserDefaultChecked > .. > Never)
|
||||
if ( m > m_restartNowMode )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If changing to an unconditional mode, also set other flag
|
||||
if ( m == RestartMode::Always || m == RestartMode::Never )
|
||||
{
|
||||
setRestartNowWanted( m == RestartMode::Always );
|
||||
}
|
||||
|
||||
if ( m != m_restartNowMode )
|
||||
{
|
||||
m_restartNowMode = m;
|
||||
emit restartModeChanged( m );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Config::setRestartNowWanted( bool w )
|
||||
{
|
||||
// Follow the mode which may affect @p w
|
||||
if ( m_restartNowMode == RestartMode::Always )
|
||||
{
|
||||
w = true;
|
||||
}
|
||||
if ( m_restartNowMode == RestartMode::Never )
|
||||
{
|
||||
w = false;
|
||||
}
|
||||
|
||||
if ( w != m_userWantsRestart )
|
||||
{
|
||||
m_userWantsRestart = w;
|
||||
emit restartNowWantedChanged( w );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Config::onInstallationFailed( const QString& message, const QString& details )
|
||||
{
|
||||
const bool msgChange = message != m_failureMessage;
|
||||
const bool detChange = details != m_failureDetails;
|
||||
m_failureMessage = message;
|
||||
m_failureDetails = details;
|
||||
if ( msgChange )
|
||||
{
|
||||
emit failureMessageChanged( message );
|
||||
}
|
||||
if ( detChange )
|
||||
{
|
||||
emit failureDetailsChanged( message );
|
||||
}
|
||||
if ( ( msgChange || detChange ) )
|
||||
{
|
||||
emit failureChanged( hasFailed() );
|
||||
if ( hasFailed() )
|
||||
{
|
||||
setRestartNowMode( Config::RestartMode::Never );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Config::doRestart( bool restartAnyway )
|
||||
{
|
||||
cDebug() << "mode=" << restartModes().find( restartNowMode() ) << " user wants restart?" << restartNowWanted()
|
||||
<< "force restart?" << restartAnyway;
|
||||
if ( restartNowMode() != RestartMode::Never && restartAnyway )
|
||||
{
|
||||
cDebug() << Logger::SubEntry << "Running restart command" << m_restartNowCommand;
|
||||
QProcess::execute( "/bin/sh", { "-c", m_restartNowCommand } );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Config::doNotify( bool hasFailed, bool sendAnyway )
|
||||
{
|
||||
const char* const failName = hasFailed ? "failed" : "succeeded";
|
||||
|
||||
if ( !sendAnyway )
|
||||
{
|
||||
cDebug() << "Notification not sent; completion:" << failName;
|
||||
return;
|
||||
}
|
||||
|
||||
QDBusInterface notify(
|
||||
"org.freedesktop.Notifications", "/org/freedesktop/Notifications", "org.freedesktop.Notifications" );
|
||||
if ( notify.isValid() )
|
||||
{
|
||||
cDebug() << "Sending notification of completion:" << failName;
|
||||
|
||||
QString title;
|
||||
QString message;
|
||||
if ( hasFailed )
|
||||
{
|
||||
title = Calamares::Settings::instance()->isSetupMode() ? tr( "Setup Failed", "@title" )
|
||||
: tr( "Installation Failed", "@title" );
|
||||
message = Calamares::Settings::instance()->isSetupMode()
|
||||
? tr( "The setup of %1 did not complete successfully.", "@info" )
|
||||
: tr( "The installation of %1 did not complete successfully.", "@info" );
|
||||
}
|
||||
else
|
||||
{
|
||||
title = Calamares::Settings::instance()->isSetupMode() ? tr( "Setup Complete", "@title" )
|
||||
: tr( "Installation Complete", "@title" );
|
||||
message = Calamares::Settings::instance()->isSetupMode()
|
||||
? tr( "The setup of %1 is complete.", "@info" )
|
||||
: tr( "The installation of %1 is complete.", "@info" );
|
||||
}
|
||||
|
||||
const auto* branding = Calamares::Branding::instance();
|
||||
QDBusReply< uint > r = notify.call( "Notify",
|
||||
QString( "Calamares" ),
|
||||
QVariant( 0U ),
|
||||
QString( "calamares" ),
|
||||
title,
|
||||
message.arg( branding->versionedName() ),
|
||||
QStringList(),
|
||||
QVariantMap(),
|
||||
QVariant( 0 ) );
|
||||
if ( !r.isValid() )
|
||||
{
|
||||
cWarning() << "Could not call org.freedesktop.Notifications.Notify at end of installation." << r.error();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cWarning() << "Could not get dbus interface for notifications at end of installation." << notify.lastError();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Config::setConfigurationMap( const QVariantMap& configurationMap )
|
||||
{
|
||||
RestartMode mode = RestartMode::Never;
|
||||
|
||||
//TODO:3.3 remove deprecated restart settings
|
||||
QString restartMode = Calamares::getString( configurationMap, "restartNowMode" );
|
||||
if ( restartMode.isEmpty() )
|
||||
{
|
||||
if ( configurationMap.contains( "restartNowEnabled" ) )
|
||||
{
|
||||
cWarning() << "Configuring the finished module with deprecated restartNowEnabled settings";
|
||||
}
|
||||
|
||||
bool restartNowEnabled = Calamares::getBool( configurationMap, "restartNowEnabled", false );
|
||||
bool restartNowChecked = Calamares::getBool( configurationMap, "restartNowChecked", false );
|
||||
|
||||
if ( !restartNowEnabled )
|
||||
{
|
||||
mode = RestartMode::Never;
|
||||
}
|
||||
else
|
||||
{
|
||||
mode = restartNowChecked ? RestartMode::UserDefaultChecked : RestartMode::UserDefaultUnchecked;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool ok = false;
|
||||
mode = restartModes().find( restartMode, ok );
|
||||
if ( !ok )
|
||||
{
|
||||
cWarning() << "Configuring the finished module with bad restartNowMode" << restartMode;
|
||||
}
|
||||
}
|
||||
|
||||
m_restartNowMode = mode;
|
||||
m_userWantsRestart = ( mode == RestartMode::Always || mode == RestartMode::UserDefaultChecked );
|
||||
emit restartModeChanged( m_restartNowMode );
|
||||
emit restartNowWantedChanged( m_userWantsRestart );
|
||||
|
||||
if ( mode != RestartMode::Never )
|
||||
{
|
||||
QString restartNowCommand = Calamares::getString( configurationMap, "restartNowCommand" );
|
||||
if ( restartNowCommand.isEmpty() )
|
||||
{
|
||||
restartNowCommand = QStringLiteral( "shutdown -r now" );
|
||||
}
|
||||
m_restartNowCommand = restartNowCommand;
|
||||
}
|
||||
|
||||
m_notifyOnFinished = Calamares::getBool( configurationMap, "notifyOnFinished", false );
|
||||
}
|
||||
130
src/modules/finishedq/Config.h
Normal file
130
src/modules/finishedq/Config.h
Normal file
@@ -0,0 +1,130 @@
|
||||
/* === This file is part of Calamares - <https://calamares.io> ===
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2021 Adriaan de Groot <groot@kde.org>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* Calamares is Free Software: see the License-Identifier above.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FINISHED_CONFIG_H
|
||||
#define FINISHED_CONFIG_H
|
||||
|
||||
#include "utils/NamedEnum.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class Config : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY( RestartMode restartNowMode READ restartNowMode WRITE setRestartNowMode NOTIFY restartModeChanged )
|
||||
Q_PROPERTY( bool restartNowWanted READ restartNowWanted WRITE setRestartNowWanted NOTIFY restartNowWantedChanged )
|
||||
|
||||
Q_PROPERTY( QString restartNowCommand READ restartNowCommand CONSTANT FINAL )
|
||||
Q_PROPERTY( bool notifyOnFinished READ notifyOnFinished CONSTANT FINAL )
|
||||
|
||||
Q_PROPERTY( QString failureMessage READ failureMessage NOTIFY failureMessageChanged )
|
||||
Q_PROPERTY( QString failureDetails READ failureDetails NOTIFY failureDetailsChanged )
|
||||
Q_PROPERTY( bool failed READ hasFailed NOTIFY failureChanged )
|
||||
|
||||
public:
|
||||
Config( QObject* parent = nullptr );
|
||||
|
||||
enum class RestartMode
|
||||
{
|
||||
Never,
|
||||
UserDefaultUnchecked,
|
||||
UserDefaultChecked,
|
||||
Always
|
||||
};
|
||||
Q_ENUM( RestartMode )
|
||||
|
||||
void setConfigurationMap( const QVariantMap& configurationMap );
|
||||
|
||||
public Q_SLOTS:
|
||||
RestartMode restartNowMode() const { return m_restartNowMode; }
|
||||
void setRestartNowMode( RestartMode m );
|
||||
|
||||
bool restartNowWanted() const
|
||||
{
|
||||
if ( restartNowMode() == RestartMode::Never )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return ( restartNowMode() == RestartMode::Always ) || m_userWantsRestart;
|
||||
}
|
||||
void setRestartNowWanted( bool w );
|
||||
|
||||
QString restartNowCommand() const { return m_restartNowCommand; }
|
||||
bool notifyOnFinished() const { return m_notifyOnFinished; }
|
||||
|
||||
QString failureMessage() const { return m_failureMessage; }
|
||||
QString failureDetails() const { return m_failureDetails; }
|
||||
/// Failure is if any of the failure messages is non-empty
|
||||
bool hasFailed() const { return !m_failureMessage.isEmpty() || !m_failureDetails.isEmpty(); }
|
||||
|
||||
/** @brief Run the restart command, if desired.
|
||||
*
|
||||
* This should generally not be called somewhere during the
|
||||
* application's execution, but only in response to QApplication::quit()
|
||||
* or something like that when the user expects the system to restart.
|
||||
*
|
||||
* The "if desired" part is: only if the restart mode allows it,
|
||||
* **and** the user has checked the box (or done whatever to
|
||||
* turn on restartNowWanted()).
|
||||
*
|
||||
* - The one-argument form ignores what the user wants and restarts
|
||||
* if @p restartAnyway is @c true **unless** the mode is Never
|
||||
* - The no-argument form uses the user setting
|
||||
*/
|
||||
void doRestart( bool restartAnyway );
|
||||
void doRestart() { doRestart( restartNowWanted() ); }
|
||||
|
||||
/** @brief Send DBus notification
|
||||
*
|
||||
* At the end of installation (when the FinishedViewStep is activated),
|
||||
* send a desktop notification via DBus that the install is done.
|
||||
*
|
||||
* - The two-argument form sends success or failure, and can be
|
||||
* forced to send by setting @p sendAnyway to @c true.
|
||||
* - The one-argument form sends success or failure and takes
|
||||
* the notifyOnFinished() configuration into account.
|
||||
* - The no-argument form checks if a failure was signalled previously
|
||||
* and uses that to decide if it was a failure.
|
||||
*
|
||||
*/
|
||||
void doNotify( bool hasFailed, bool sendAnyway );
|
||||
void doNotify( bool hasFailed ) { doNotify( hasFailed, notifyOnFinished() ); }
|
||||
void doNotify() { doNotify( hasFailed() ); }
|
||||
|
||||
/** @brief Tell the config the install failed
|
||||
*
|
||||
* This should be connected to the JobQueue and is called by
|
||||
* the queue when the installation fails, with a suitable message.
|
||||
*/
|
||||
void onInstallationFailed( const QString& message, const QString& details );
|
||||
|
||||
signals:
|
||||
void restartModeChanged( RestartMode m );
|
||||
void restartNowWantedChanged( bool w );
|
||||
void failureMessageChanged( const QString& );
|
||||
void failureDetailsChanged( const QString& );
|
||||
void failureChanged( bool );
|
||||
|
||||
private:
|
||||
// Configuration parts
|
||||
QString m_restartNowCommand;
|
||||
RestartMode m_restartNowMode = RestartMode::Never;
|
||||
bool m_userWantsRestart = false;
|
||||
bool m_notifyOnFinished = false;
|
||||
|
||||
// Dynamic parts
|
||||
bool m_hasFailed = false;
|
||||
QString m_failureMessage;
|
||||
QString m_failureDetails;
|
||||
};
|
||||
|
||||
const NamedEnumTable< Config::RestartMode >& restartModes();
|
||||
|
||||
#endif
|
||||
@@ -4,33 +4,49 @@
|
||||
# Configuration for the "finishedq" page, which is usually shown only at
|
||||
# the end of the installation (successful or not).
|
||||
#
|
||||
# See the documentation for the "finished" module for a full explanation
|
||||
# of the configuration options; the description here applies primarily
|
||||
# to the use that the QML makes of them.
|
||||
# NOTE: finishedq module uses a different configuration from what
|
||||
# the finished module uses and is not compatible with
|
||||
# with the configurable shutdown actions.
|
||||
|
||||
---
|
||||
# DEPRECATED
|
||||
#
|
||||
# The finished page can hold a "restart system now" checkbox.
|
||||
# If this is false, no checkbox is shown and the system is not restarted
|
||||
# when Calamares exits.
|
||||
# restartNowEnabled: true
|
||||
|
||||
# DEPRECATED
|
||||
#
|
||||
# Initial state of the checkbox "restart now". Only relevant when the
|
||||
# checkbox is shown by restartNowEnabled.
|
||||
# restartNowChecked: false
|
||||
|
||||
# Behavior of the "restart system now" button.
|
||||
#
|
||||
# The example QML for this module offers a "Restart Now" button,
|
||||
# which the user can click on. It calls directly to the restart
|
||||
# function. If the user closes the installer in some other way,
|
||||
# (the "Done" button or close-window) a restart **might** happen:
|
||||
#
|
||||
# There are four usable values:
|
||||
# - never
|
||||
# Do not restart (this will also block the "Restart Now" button,
|
||||
# so it is not very useful)
|
||||
# Does not show the button and does not restart.
|
||||
# This matches the old behavior with restartNowEnabled=false.
|
||||
# - user-unchecked
|
||||
# Do not restart on other ways of closing the window. No checkbox
|
||||
# is shown in the example QML, so there is no way for the user to
|
||||
# express a choice -- except by clicking the "Restart Now" button.
|
||||
# Shows the button, defaults to unchecked, restarts if it is checked.
|
||||
# This matches the old behavior with restartNowEnabled=true and restartNowChecked=false.
|
||||
# - user-checked
|
||||
# Do restart on other ways of closing the window. This makes close
|
||||
# and "Restart Now" do the same thing. No checkbox is shown by the QML,
|
||||
# so the machine will **always** restart.
|
||||
# Shows the button, defaults to checked, restarts if it is checked.
|
||||
# This matches the old behavior with restartNowEnabled=true and restartNowChecked=true.
|
||||
# - always
|
||||
# Same as above.
|
||||
# Shows the button, checked, but the user cannot change it.
|
||||
# This is new behavior.
|
||||
#
|
||||
# For the **specific** example QML included with this module, only
|
||||
# *user-unchecked* really makes sense.
|
||||
# The three combinations of legacy values are still supported.
|
||||
restartNowMode: user-unchecked
|
||||
|
||||
# If the checkbox is shown, and the checkbox is checked, then when
|
||||
# Calamares exits from the finished-page it will run this command.
|
||||
# If not set, falls back to "shutdown -r now".
|
||||
restartNowCommand: "systemctl -i reboot"
|
||||
|
||||
# When the last page is (successfully) reached, send a DBus notification
|
||||
# to the desktop that the installation is done. This works only if the
|
||||
# user as whom Calamares is run, can reach the regular desktop session bus.
|
||||
notifyOnFinished: false
|
||||
|
||||
Reference in New Issue
Block a user