diff --git a/CHANGES b/CHANGES
index ad1aa55e8..e219bf3d3 100644
--- a/CHANGES
+++ b/CHANGES
@@ -15,6 +15,9 @@ This release contains contributions from (alphabetically by first name):
## Modules ##
- *packages* now reports more details in the installation progress-bar.
+ - *netinstall* module supports and `expanded` key, which will pre-expand
+ a group (as if the user had pressed the arrow-button in the tree-view).
+ This only affects the UI.
# 3.2.20 (2020-02-27) #
diff --git a/src/calamares/progresstree/ViewStepItem.cpp b/src/calamares/progresstree/ViewStepItem.cpp
index 885b81dfc..bbb2846ce 100644
--- a/src/calamares/progresstree/ViewStepItem.cpp
+++ b/src/calamares/progresstree/ViewStepItem.cpp
@@ -65,9 +65,9 @@ ViewStepItem::data( int role ) const
toolTip.append( "
Type:\tViewStep" );
toolTip.append( QString( "
Pretty:\t%1" ).arg( m_step->prettyName() ) );
toolTip.append( QString( "
Status:\t%1" ).arg( m_step->prettyStatus() ) );
- toolTip.append(
- QString( "
Source:\t%1" )
- .arg( m_step->moduleInstanceKey().isValid() ? m_step->moduleInstanceKey().toString() : QStringLiteral("built-in") ) );
+ toolTip.append( QString( "
Source:\t%1" )
+ .arg( m_step->moduleInstanceKey().isValid() ? m_step->moduleInstanceKey().toString()
+ : QStringLiteral( "built-in" ) ) );
}
else
{
@@ -77,7 +77,9 @@ ViewStepItem::data( int role ) const
return toolTip;
}
if ( role == ProgressTreeModel::ProgressTreeItemCurrentRole )
+ {
return m_step ? ( Calamares::ViewManager::instance()->currentStep() == m_step )
: ( Calamares::ViewManager::instance()->currentStep() == m_accessor() );
+ }
return QVariant();
}
diff --git a/src/modules/netinstall/NetInstallPage.cpp b/src/modules/netinstall/NetInstallPage.cpp
index 735610c3d..352eb9f3e 100644
--- a/src/modules/netinstall/NetInstallPage.cpp
+++ b/src/modules/netinstall/NetInstallPage.cpp
@@ -154,6 +154,16 @@ NetInstallPage::dataIsHere()
ui->groupswidget->header()->setSectionResizeMode( 0, QHeaderView::ResizeToContents );
ui->groupswidget->header()->setSectionResizeMode( 1, QHeaderView::Stretch );
+ // Go backwards because expanding a group may cause rows to appear below it
+ for ( int i = m_groups->rowCount() - 1; i >= 0; --i )
+ {
+ auto index = m_groups->index(i,0);
+ if ( m_groups->data(index, PackageModel::MetaExpandRole).toBool() )
+ {
+ ui->groupswidget->setExpanded(index, true);
+ }
+ }
+
emit checkReady( true );
}
diff --git a/src/modules/netinstall/PackageModel.cpp b/src/modules/netinstall/PackageModel.cpp
index 0805a8135..215ac2912 100644
--- a/src/modules/netinstall/PackageModel.cpp
+++ b/src/modules/netinstall/PackageModel.cpp
@@ -21,9 +21,6 @@
#include "utils/Yaml.h"
-// TODO: see headerData(), remove after 3.2.19
-#include
-
PackageModel::PackageModel( const YAML::Node& data, QObject* parent )
: QAbstractItemModel( parent )
{
@@ -120,21 +117,17 @@ PackageModel::data( const QModelIndex& index, int role ) const
}
PackageTreeItem* item = static_cast< PackageTreeItem* >( index.internalPointer() );
- if ( index.column() == 0 && role == Qt::CheckStateRole )
- {
- return item->isSelected();
- }
-
- if ( item->isHidden() && role == Qt::DisplayRole ) // Hidden group
+ switch ( role )
{
+ case Qt::CheckStateRole:
+ return index.column() == NameColumn ? item->isSelected() : QVariant();
+ case Qt::DisplayRole:
+ return item->isHidden() ? QVariant() : item->data( index.column() );
+ case MetaExpandRole:
+ return item->isHidden() ? false : item->expandOnStart();
+ default:
return QVariant();
}
-
- if ( role == Qt::DisplayRole )
- {
- return item->data( index.column() );
- }
- return QVariant();
}
bool
@@ -159,7 +152,7 @@ PackageModel::flags( const QModelIndex& index ) const
{
return Qt::ItemFlags();
}
- if ( index.column() == 0 )
+ if ( index.column() == NameColumn )
{
return Qt::ItemIsUserCheckable | QAbstractItemModel::flags( index );
}
@@ -171,12 +164,7 @@ PackageModel::headerData( int section, Qt::Orientation orientation, int role ) c
{
if ( orientation == Qt::Horizontal && role == Qt::DisplayRole )
{
- // Unusual translation call uses the existing translation from the NetInstallPage
- // class (now removed).
- //
- // TODO: after 3.2.19, change this to just tr() and push TX
- return ( section == 0 ) ? QCoreApplication::translate( "NetInstallPage", "Name" )
- : QCoreApplication::translate( "NetInstallPage", "Description" );
+ return ( section == NameColumn ) ? tr( "Name" ) : tr( "Description" );
}
return QVariant();
}
@@ -226,6 +214,18 @@ PackageModel::getItemPackages( PackageTreeItem* item ) const
return selectedPackages;
}
+static QString
+getString( const YAML::Node& itemDefinition, const char* key )
+{
+ return itemDefinition[ key ] ? CalamaresUtils::yamlToVariant( itemDefinition[ key ] ).toString() : QString();
+}
+
+static bool
+getBool( const YAML::Node& itemDefinition, const char* key )
+{
+ return itemDefinition[ key ] ? CalamaresUtils::yamlToVariant( itemDefinition[ key ] ).toBool() : false;
+}
+
void
PackageModel::setupModelData( const YAML::Node& data, PackageTreeItem* parent )
{
@@ -240,41 +240,33 @@ PackageModel::setupModelData( const YAML::Node& data, PackageTreeItem* parent )
itemData.name = name;
itemData.description = description;
- if ( itemDefinition[ "pre-install" ] )
- {
- itemData.preScript = CalamaresUtils::yamlToVariant( itemDefinition[ "pre-install" ] ).toString();
- }
- if ( itemDefinition[ "post-install" ] )
- {
- itemData.postScript = CalamaresUtils::yamlToVariant( itemDefinition[ "post-install" ] ).toString();
- }
+ itemData.preScript = getString( itemDefinition, "pre-install" );
+ itemData.postScript = getString( itemDefinition, "post-install" );
+ itemData.isCritical = getBool( itemDefinition, "critical" );
+ itemData.isHidden = getBool( itemDefinition, "hidden" );
+ itemData.startExpanded = getBool( itemDefinition, "expanded" );
+
PackageTreeItem* item = new PackageTreeItem( itemData, parent );
if ( itemDefinition[ "selected" ] )
- item->setSelected( CalamaresUtils::yamlToVariant( itemDefinition[ "selected" ] ).toBool() ? Qt::Checked
- : Qt::Unchecked );
+ {
+ item->setSelected( getBool( itemDefinition, "selected" ) ? Qt::Checked : Qt::Unchecked );
+ }
else
{
item->setSelected( parent->isSelected() ); // Inherit from it's parent
}
- if ( itemDefinition[ "hidden" ] )
- {
- item->setHidden( CalamaresUtils::yamlToVariant( itemDefinition[ "hidden" ] ).toBool() );
- }
-
- if ( itemDefinition[ "critical" ] )
- {
- item->setCritical( CalamaresUtils::yamlToVariant( itemDefinition[ "critical" ] ).toBool() );
- }
-
if ( itemDefinition[ "packages" ] )
+ {
for ( YAML::const_iterator packageIt = itemDefinition[ "packages" ].begin();
packageIt != itemDefinition[ "packages" ].end();
++packageIt )
+ {
item->appendChild(
new PackageTreeItem( CalamaresUtils::yamlToVariant( *packageIt ).toString(), item ) );
-
+ }
+ }
if ( itemDefinition[ "subgroups" ] )
{
setupModelData( itemDefinition[ "subgroups" ], item );
diff --git a/src/modules/netinstall/PackageModel.h b/src/modules/netinstall/PackageModel.h
index 25965cb7f..b76a58a42 100644
--- a/src/modules/netinstall/PackageModel.h
+++ b/src/modules/netinstall/PackageModel.h
@@ -39,6 +39,16 @@ class PackageModel : public QAbstractItemModel
public:
using PackageItemDataList = QList< PackageTreeItem::ItemData >;
+ // Names for columns (unused in the code)
+ static constexpr const int NameColumn = 0;
+ static constexpr const int DescriptionColumn = 1;
+
+ /* The only interesting roles are DisplayRole (with text depending
+ * on the column, and MetaExpandRole which tells if an index
+ * should be initially expanded.
+ */
+ static constexpr const int MetaExpandRole = Qt::UserRole + 1;
+
explicit PackageModel( const YAML::Node& data, QObject* parent = nullptr );
~PackageModel() override;
diff --git a/src/modules/netinstall/PackageTreeItem.cpp b/src/modules/netinstall/PackageTreeItem.cpp
index 59e82a659..7e20d63e1 100644
--- a/src/modules/netinstall/PackageTreeItem.cpp
+++ b/src/modules/netinstall/PackageTreeItem.cpp
@@ -108,22 +108,27 @@ PackageTreeItem::row() const
QVariant
PackageTreeItem::data( int column ) const
{
- if ( packageName() != nullptr ) // package
+ if ( !packageName().isEmpty() ) // packages have a packagename, groups don't
{
- if ( !column )
+ switch ( column )
{
+ case 0:
return QVariant( packageName() );
+ default:
+ return QVariant();
}
- return QVariant();
}
- switch ( column ) // group
+ else
{
- case 0:
- return QVariant( prettyName() );
- case 1:
- return QVariant( description() );
- default:
- return QVariant();
+ switch ( column ) // group
+ {
+ case 0:
+ return QVariant( prettyName() );
+ case 1:
+ return QVariant( description() );
+ default:
+ return QVariant();
+ }
}
}
@@ -176,12 +181,6 @@ PackageTreeItem::isHidden() const
return m_data.isHidden;
}
-void
-PackageTreeItem::setHidden( bool isHidden )
-{
- m_data.isHidden = isHidden;
-}
-
bool
PackageTreeItem::hiddenSelected() const
{
@@ -212,12 +211,6 @@ PackageTreeItem::isCritical() const
return m_data.isCritical;
}
-void
-PackageTreeItem::setCritical( bool isCritical )
-{
- m_data.isCritical = isCritical;
-}
-
Qt::CheckState
PackageTreeItem::isSelected() const
{
diff --git a/src/modules/netinstall/PackageTreeItem.h b/src/modules/netinstall/PackageTreeItem.h
index 18a509861..d9c1f9ec2 100644
--- a/src/modules/netinstall/PackageTreeItem.h
+++ b/src/modules/netinstall/PackageTreeItem.h
@@ -36,6 +36,7 @@ public:
QString postScript;
bool isCritical = false;
bool isHidden = false;
+ bool startExpanded = false; // Only for groups
Qt::CheckState selected = Qt::Unchecked;
/** @brief Turns this item into a variant for PackageOperations use
@@ -66,10 +67,14 @@ public:
QString packageName() const;
QString postScript() const;
+ /** @brief Is this item hidden?
+ *
+ * Hidden items (generally only groups) are maintained separately,
+ * not shown to the user, but do enter into the package-installation process.
+ */
bool isHidden() const;
- void setHidden( bool isHidden );
- /**
- * @brief Is this hidden item, considered "selected"?
+
+ /** @brief Is this hidden item, considered "selected"?
*
* This asserts when called on a non-hidden item.
* A hidden item has its own selected state, but really
@@ -77,8 +82,20 @@ public:
*/
bool hiddenSelected() const;
+ /** @brief Is this group critical?
+ *
+ * A critical group must be successfully installed, for the Calamares
+ * installation to continue.
+ */
bool isCritical() const;
- void setCritical( bool isCritical );
+
+ /** @brief Is this group expanded on start?
+ *
+ * This does not affect installation, only the UI. A group
+ * that expands on start is shown expanded (not collapsed)
+ * in the treeview when the page is loaded.
+ */
+ bool expandOnStart() const { return m_data.startExpanded; }
Qt::CheckState isSelected() const;
void setSelected( Qt::CheckState isSelected );
diff --git a/src/modules/netinstall/README.md b/src/modules/netinstall/README.md
index 855754822..a8803edd5 100644
--- a/src/modules/netinstall/README.md
+++ b/src/modules/netinstall/README.md
@@ -1,16 +1,16 @@
# Netinstall module
The netinstall module allows distribution maintainers to ship minimal ISOs with
-only a basic set of preinstall packages. At installation time, the user is
+only a basic set of preinstalled packages. At installation time, the user is
presented with the choice to install groups of packages from a predefined list.
-Calamares will then invoke the correct backend to install the packages.
+Calamares will then use the *packages* module to install the packages.
## Module Configuration
The `netinstall.conf` file is self-describing, and at the very
-lease should contain a *groupsUrl* key:
+least should contain a *groupsUrl* key:
```
----
@@ -18,13 +18,13 @@ lease should contain a *groupsUrl* key:
```
The URL must point to a YAML file, the *groups* file. See below for
-the format of that groups file. The URL may be a local file.
+the format of that groups file. The URL may be a local file (e.g.
+scheme `file:///`) or a regular HTTP(s) URL.
## Groups Configuration
- Here is a short example
-of how the YAML file should look.
+Here is a short example of how the YAML file should look.
```
- name: "Group name"
@@ -45,9 +45,11 @@ More keys (per group) are supported:
- *hidden*: if true, do not show the group on the page. Defaults to false.
- *selected*: if true, display the group as selected. Defaults to false.
- - critical*: if true, make the installation process fail if installing
+ - *critical*: if true, make the installation process fail if installing
any of the packages in the group fails. Otherwise, just log a warning.
Defaults to false.
+ - *expanded*: if true, the group is shown in an expanded form (that is,
+ not-collapsed) in the treeview on start.
- *subgroups*: if present this follows the same structure as the top level
of the YAML file, allowing there to be sub-groups of packages to an
arbitary depth