added the "autoProceed" instance attribute (refs #2229)

* When enabled on an instance, the "Next" button is automatically
  activated whenever it can be activated (is enabled).
  This will automatically show the ViewStep's next page or the next
  ViewStep if on the last page.
* Allows for partially or completely unattended installations.
  E.g. when set on the "partition" step and providing the necessary
  preset in partition.conf, the device can partitioned automatically without
  any user interaction.
This commit is contained in:
Robin Haberkorn
2025-09-18 14:45:27 +03:00
parent c9e4998865
commit 9c1e463bcc
6 changed files with 58 additions and 12 deletions

View File

@@ -54,6 +54,10 @@ modules-search: [ local ]
# weight overrides a weight given in the module descriptor. If no weight
# is given, uses the value from the module descriptor, or 1 if there
# isn't one there either.
# - *autoProceed* (optional) If true, automatically proceed to the next
# ViewStep page whenever the "Next" button is enabled. This allows fully
# automated (unattended) installations. It is disabled (false)
# by default.
#
# The primary goal of this mechanism is to allow loading multiple instances
# of the same module, with different configuration. If you don't need this,
@@ -86,9 +90,11 @@ modules-search: [ local ]
#
# YAML: list of maps of string:string key-value pairs.
#instances:
#- id: licenseq
# module: packagechooserq
# config: licenseq.conf
#- id: licenseq
# module: packagechooserq
# config: licenseq.conf
#- module: partition
# autoProceed: true
# Sequence section. This section describes the sequence of modules, both
# viewmodules and jobmodules, as they should appear and/or run.

View File

@@ -18,6 +18,7 @@
#include "DebugWindow.h"
#include "Settings.h"
#include "ViewManager.h"
#include "viewpages/ViewStep.h"
#include "progresstree/ProgressTreeView.h"
#include "utils/Gui.h"
#include "utils/Logger.h"
@@ -41,6 +42,8 @@
#endif
#include <QTreeView>
#include <algorithm>
static QSize
desktopSize( QWidget* w )
{
@@ -99,6 +102,28 @@ setButtonIcon( QPushButton* button, const QString& name )
}
}
/** @brief Enable the "Next" button and possibly auto-proceed to next page */
static inline void
setNextButtonEnabled( QPushButton* button, Calamares::ViewStep* step, bool enabled )
{
button->setEnabled( enabled );
if ( !enabled || !step )
{
return;
}
const auto instanceDescriptors = Calamares::Settings::instance()->moduleInstances();
auto targetKey = step->moduleInstanceKey();
auto moduleFinder
= [ &targetKey ]( const Calamares::InstanceDescription& d ) { return d.isValid() && d.key() == targetKey; };
const auto it = std::find_if( instanceDescriptors.constBegin(), instanceDescriptors.constEnd(), moduleFinder );
if ( it->autoProceed() )
{
button->click();
}
}
static QWidget*
getWidgetSidebar( Calamares::DebugWindowManager* debug,
Calamares::ViewManager* viewManager,
@@ -221,7 +246,11 @@ getWidgetNavigation( Calamares::DebugWindowManager*,
next->setObjectName( "view-button-next" );
next->setEnabled( viewManager->nextEnabled() );
QObject::connect( next, &QPushButton::clicked, viewManager, &Calamares::ViewManager::next );
QObject::connect( viewManager, &Calamares::ViewManager::nextEnabledChanged, next, &QPushButton::setEnabled );
QObject::connect( viewManager,
&Calamares::ViewManager::nextEnabledChanged,
next,
[ = ]( Calamares::ViewStep* step, bool enabled )
{ setNextButtonEnabled( next, step, enabled ); } );
QObject::connect( viewManager, &Calamares::ViewManager::nextLabelChanged, next, &QPushButton::setText );
QObject::connect(
viewManager, &Calamares::ViewManager::nextIconChanged, [ = ]( QString n ) { setButtonIcon( next, n ); } );

View File

@@ -96,6 +96,8 @@ InstanceDescription::fromSettings( const QVariantMap& m )
{
r.m_configFileName = c;
}
r.m_autoProceed = m.value( "autoProceed" ).toBool();
}
return r;
}

View File

@@ -63,11 +63,14 @@ public:
bool isCustom() const { return m_instanceKey.isCustom(); }
int weight() const { return m_weight < 0 ? 1 : m_weight; }
bool explicitWeight() const { return m_weight > 0; }
bool autoProceed() const { return m_autoProceed; }
private:
InstanceKey m_instanceKey;
QString m_configFileName;
int m_weight = 0;
/// @brief Whether to automatically proceed to the next ViewStep page
bool m_autoProceed = false;
};
class DLLEXPORT Settings : public QObject

View File

@@ -42,6 +42,13 @@
emit name##Changed( m_##name ); \
} while ( false )
#define UPDATE_NEXT_BUTTON_PROPERTY( step, value ) \
do \
{ \
m_nextEnabled = value; \
emit nextEnabledChanged( step, m_nextEnabled ); \
} while ( false )
namespace Calamares
{
@@ -112,8 +119,7 @@ ViewManager::addViewStep( ViewStep* step )
// If this is the first inserted view step, update status of "Next" button
if ( m_steps.count() == 1 )
{
m_nextEnabled = step->isNextEnabled();
emit nextEnabledChanged( m_nextEnabled );
UPDATE_NEXT_BUTTON_PROPERTY( step, step->isNextEnabled() );
}
}
@@ -231,8 +237,7 @@ ViewManager::updateNextStatus( bool status )
{
if ( vs == m_steps.at( m_currentStep ) )
{
m_nextEnabled = status;
emit nextEnabledChanged( m_nextEnabled );
UPDATE_NEXT_BUTTON_PROPERTY( vs, status );
}
}
}
@@ -374,7 +379,7 @@ ViewManager::next()
{
// Reached the end in a weird state (e.g. no finished step after an exec)
executing = false;
UPDATE_BUTTON_PROPERTY( nextEnabled, false );
UPDATE_NEXT_BUTTON_PROPERTY( NULL, false );
UPDATE_BUTTON_PROPERTY( backEnabled, false );
}
updateCancelEnabled( !settings->disableCancel() && !( executing && settings->disableCancelDuringExec() ) );
@@ -387,7 +392,8 @@ ViewManager::next()
if ( m_currentStep < m_steps.count() )
{
UPDATE_BUTTON_PROPERTY( nextEnabled, !executing && m_steps.at( m_currentStep )->isNextEnabled() );
UPDATE_NEXT_BUTTON_PROPERTY( m_steps.at( m_currentStep ),
!executing && m_steps.at( m_currentStep )->isNextEnabled() );
UPDATE_BUTTON_PROPERTY( backEnabled, !executing && m_steps.at( m_currentStep )->isBackEnabled() );
}
@@ -477,7 +483,7 @@ ViewManager::back()
return;
}
UPDATE_BUTTON_PROPERTY( nextEnabled, m_steps.at( m_currentStep )->isNextEnabled() );
UPDATE_NEXT_BUTTON_PROPERTY( m_steps.at( m_currentStep ), m_steps.at( m_currentStep )->isNextEnabled() );
UPDATE_BUTTON_PROPERTY( backEnabled,
( m_currentStep == 0 && m_steps.first()->isAtBeginning() )
? false

View File

@@ -224,7 +224,7 @@ signals:
void ensureSize( QSize size ) const; // See ViewStep::ensureSize()
void cancelEnabled( bool enabled ) const;
void nextEnabledChanged( bool ) const;
void nextEnabledChanged( ViewStep*, bool ) const;
void nextLabelChanged( QString ) const;
void nextIconChanged( QString ) const;