From a4aef3bce5b2e7f05ad5a0ceacc581d1a5cdd9a2 Mon Sep 17 00:00:00 2001 From: Kyle Robertze Date: Mon, 23 Jan 2017 14:42:40 +0200 Subject: [PATCH] moved netinstall to a tree based ui --- src/modules/netinstall/CMakeLists.txt | 4 +- src/modules/netinstall/NetInstallPage.cpp | 76 +---- src/modules/netinstall/NetInstallPage.h | 33 +-- src/modules/netinstall/NetInstallViewStep.cpp | 33 +-- src/modules/netinstall/PackageModel.cpp | 266 ++++++++++++++++++ src/modules/netinstall/PackageModel.h | 64 +++++ src/modules/netinstall/PackageTreeItem.cpp | 203 +++++++++++++ src/modules/netinstall/PackageTreeItem.h | 79 ++++++ src/modules/netinstall/page_netinst.ui | 2 +- .../widgets/groupselectionwidget.cpp | 67 ----- .../netinstall/widgets/groupselectionwidget.h | 50 ---- .../widgets/groupselectionwidget.ui | 138 --------- 12 files changed, 642 insertions(+), 373 deletions(-) create mode 100644 src/modules/netinstall/PackageModel.cpp create mode 100644 src/modules/netinstall/PackageModel.h create mode 100644 src/modules/netinstall/PackageTreeItem.cpp create mode 100644 src/modules/netinstall/PackageTreeItem.h delete mode 100644 src/modules/netinstall/widgets/groupselectionwidget.cpp delete mode 100644 src/modules/netinstall/widgets/groupselectionwidget.h delete mode 100644 src/modules/netinstall/widgets/groupselectionwidget.ui diff --git a/src/modules/netinstall/CMakeLists.txt b/src/modules/netinstall/CMakeLists.txt index 2038a2658..1de1c7505 100644 --- a/src/modules/netinstall/CMakeLists.txt +++ b/src/modules/netinstall/CMakeLists.txt @@ -6,10 +6,10 @@ calamares_add_plugin( netinstall SOURCES NetInstallViewStep.cpp NetInstallPage.cpp - widgets/groupselectionwidget.cpp + PackageTreeItem.cpp + PackageModel.cpp UI page_netinst.ui - widgets/groupselectionwidget.ui RESOURCES netinstall.qrc LINK_PRIVATE_LIBRARIES diff --git a/src/modules/netinstall/NetInstallPage.cpp b/src/modules/netinstall/NetInstallPage.cpp index 5c02d0b1b..7d3681a2c 100644 --- a/src/modules/netinstall/NetInstallPage.cpp +++ b/src/modules/netinstall/NetInstallPage.cpp @@ -18,7 +18,8 @@ #include "NetInstallPage.h" -#include "widgets/groupselectionwidget.h" +#include "PackageModel.h" + #include "ui_page_netinst.h" #include "GlobalStorage.h" #include "JobQueue.h" @@ -33,6 +34,7 @@ #include #include +#include #include #include #include @@ -62,34 +64,9 @@ void NetInstallPage::readGroups( const QByteArray& yamlData ) { YAML::Node groups = YAML::Load( yamlData.constData() ); Q_ASSERT( groups.IsSequence() ); - - for ( YAML::const_iterator it = groups.begin(); it != groups.end(); ++it ) - { - const YAML::Node groupDefinition = *it; - - QString name( tr( yamlToVariant(groupDefinition["name"]).toByteArray() ) ); - QString description( tr( yamlToVariant(groupDefinition["description"]).toByteArray() ) ); - QStringList packages; - - for ( YAML::const_iterator it = groupDefinition["packages"].begin(); - it != groupDefinition["packages"].end(); ++it ) - packages.append( yamlToVariant(*it).toString() ); - - m_groups[name].name = name; - m_groups[name].description = description; - m_groups[name].packages = packages; - - if ( groupDefinition["selected"] ) - m_groups[name].selected = yamlToVariant( groupDefinition["selected"] ).toBool(); - - if ( groupDefinition["hidden"] ) - m_groups[name].hidden = yamlToVariant( groupDefinition["hidden"] ).toBool(); - - if ( groupDefinition["critical"] ) - m_groups[name].critical = yamlToVariant( groupDefinition["critical"] ).toBool(); - - m_groupOrder.append( name ); - } + QVariantList columnHeadings; + columnHeadings << tr( "Name" ) << tr( "Description" ); + m_groups = new PackageModel( groups, columnHeadings ); } void @@ -104,48 +81,17 @@ NetInstallPage::dataIsHere( QNetworkReply* reply ) readGroups( reply->readAll() ); - QSignalMapper* mapper = new QSignalMapper( this ); - foreach ( const QString& groupKey, m_groupOrder ) - { - Group group = m_groups[groupKey]; - if ( group.hidden ) - { - // Do not present on view. - continue; - } - - GroupSelectionWidget* groupWidget = new GroupSelectionWidget( group.name, group.description, group.packages, group.selected, this ); - m_groupWidgets.insert( groupKey, groupWidget ); - ui->groupswidget->layout()->addWidget( groupWidget ); - - mapper->setMapping( groupWidget, groupKey ); - connect( groupWidget, &GroupSelectionWidget::toggled, mapper, - static_cast(&QSignalMapper::map) ); - } + ui->groupswidget->setModel( m_groups ); + ui->groupswidget->header()->setSectionResizeMode( 0, QHeaderView::ResizeToContents ); + ui->groupswidget->header()->setSectionResizeMode( 1, QHeaderView::Stretch ); reply->deleteLater(); emit checkReady( isReady() ); } -QList NetInstallPage::selectedGroups() const +QList NetInstallPage::selectedPackages( bool isCritical ) const { - QList selectedGroups; - - // Add all the groups that are toggled in the view. - for ( auto it = m_groupWidgets.constBegin(); it != m_groupWidgets.constEnd(); it++ ) - { - if ( it.value()->isToggled() ) - selectedGroups += m_groups[it.key()]; - } - - // Add all groups that are hidden but selected. - for ( const Group& group : m_groups.values() ) - { - if ( group.hidden && group.selected ) - selectedGroups += group; - } - - return selectedGroups; + return m_groups->getPackages( isCritical ); } void NetInstallPage::loadGroupList() diff --git a/src/modules/netinstall/NetInstallPage.h b/src/modules/netinstall/NetInstallPage.h index 7460c9c11..0f4866770 100644 --- a/src/modules/netinstall/NetInstallPage.h +++ b/src/modules/netinstall/NetInstallPage.h @@ -19,6 +19,7 @@ #ifndef NETINSTALLPAGE_H #define NETINSTALLPAGE_H +#include "PackageModel.h" #include "Typedefs.h" #include #include @@ -28,36 +29,16 @@ class QByteArray; class QNetworkReply; class GroupSelectionWidget; +class PackageModel; namespace Ui { class Page_NetInst; } -// Representation of a package group. -struct Group -{ - Group() - : Group( "","",false, false, false ) { } - Group( QString name, QString description, bool selected, bool hidden, bool critical ) - : name( name ), description( description ), selected( selected ), hidden( hidden ), critical( critical ) { } - Group( QString name, QString description ) - : Group( name, description, false, false, false ) { } - - QString name; - QString description; - QStringList packages; - - // See README.md for a description of these fields. - bool selected = false; - bool hidden = false; - bool critical = false; -}; - class NetInstallPage : public QWidget { Q_OBJECT - public: NetInstallPage( QWidget* parent = nullptr ); @@ -70,9 +51,10 @@ public: // in the global storage. This should be called before displaying the page. void loadGroupList(); - // Return a list of groups currently selected. No data is cached here, so - // this function does not run in constant time. - QList selectedGroups() const; + // Returns the list of packages belonging to groups that are + // selected in the view in this given moment. No data is cached here, so + // this function does not have constant time. + QList selectedPackages( bool isCritical ) const; public slots: void dataIsHere( QNetworkReply* ); @@ -91,11 +73,10 @@ private: // Handles connection with the remote URL storing the configuration. QNetworkAccessManager m_networkManager; - QHash m_groups; + PackageModel* m_groups; // For each group name, store the selection widget to retrieve UI // properties. QHash m_groupWidgets; - QList m_groupOrder; }; #endif // NETINSTALLPAGE_H diff --git a/src/modules/netinstall/NetInstallViewStep.cpp b/src/modules/netinstall/NetInstallViewStep.cpp index 3313996b2..d29d9092e 100644 --- a/src/modules/netinstall/NetInstallViewStep.cpp +++ b/src/modules/netinstall/NetInstallViewStep.cpp @@ -125,32 +125,17 @@ NetInstallViewStep::onLeave() cDebug() << "Leaving netinstall, adding packages to be installed" << "to global storage"; - const QList& selectedGroups = m_widget->selectedGroups(); + QMap packagesWithOperation; + QList installPackages = m_widget->selectedPackages(true); + QList tryInstallPackages = m_widget->selectedPackages(false); - if ( !selectedGroups.empty() ) + if ( !installPackages.empty() ) + packagesWithOperation.insert( "install", installPackages ); + if ( !tryInstallPackages.empty() ) + packagesWithOperation.insert( "try-install", tryInstallPackages ); + + if ( !packagesWithOperation.isEmpty() ) { - QMap packagesWithOperation; - QStringList packages, critical_packages; - - // We have two types of groups: "critical" (failing to install any of - // the packages makes Calamares fail) and "non critical" (we only log - // an error if the installation fails). We distinguish them here and select - // the correct package operation. - for (const Group& group : selectedGroups) { - if (group.critical) { - critical_packages += group.packages; - } else { - packages += group.packages; - } - } - - if (!critical_packages.empty()) { - packagesWithOperation.insert( "install", critical_packages ); - } - if (!packages.empty()) { - packagesWithOperation.insert( "try_install", packages); - } - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); gs->insert( "packageOperations", QVariant( packagesWithOperation ) ); } diff --git a/src/modules/netinstall/PackageModel.cpp b/src/modules/netinstall/PackageModel.cpp new file mode 100644 index 000000000..390f207c8 --- /dev/null +++ b/src/modules/netinstall/PackageModel.cpp @@ -0,0 +1,266 @@ +/* === This file is part of Calamares - === + * + * Copyright (c) 2017, Kyle Robbertze + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#include "PackageModel.h" + +#include "utils/Logger.h" +#include "utils/YamlUtils.h" + +#include + +PackageModel::PackageModel( const YAML::Node& data, const QVariantList& columnHeadings, + QObject* parent ) : + QAbstractItemModel( parent ), + m_columnHeadings( columnHeadings ) +{ + QVariantList rootData; + m_rootItem = new PackageTreeItem( ); + setupModelData( data, m_rootItem ); +} + +PackageModel::~PackageModel() +{ + delete m_rootItem; +} + +QModelIndex +PackageModel::index( int row, int column, const QModelIndex& parent ) const +{ + if ( !hasIndex(row, column, parent ) ) + return QModelIndex(); + + PackageTreeItem* parentItem; + + if ( !parent.isValid() ) + parentItem = m_rootItem; + else + parentItem = static_cast( parent.internalPointer() ); + + PackageTreeItem* childItem = parentItem->child( row ); + if ( childItem ) + return createIndex( row, column, childItem ); + else + return QModelIndex(); +} + +QModelIndex +PackageModel::parent( const QModelIndex& index ) const +{ + if ( !index.isValid() ) + return QModelIndex(); + + PackageTreeItem* child = static_cast( index.internalPointer() ); + PackageTreeItem* parent = child->parentItem(); + + if ( parent == m_rootItem ) + return QModelIndex(); + return createIndex( parent->row(), 0, parent ); +} + +int +PackageModel::rowCount( const QModelIndex& parent ) const +{ + if ( parent.column() > 0 ) + return 0; + + PackageTreeItem* parentItem; + if ( !parent.isValid() ) + parentItem = m_rootItem; + else + parentItem = static_cast( parent.internalPointer() ); + + return parentItem->childCount(); +} + +int +PackageModel::columnCount( const QModelIndex& parent ) const +{ + if ( parent.isValid() ) + return static_cast( parent.internalPointer() )->columnCount(); + return m_rootItem->columnCount(); +} + +QVariant +PackageModel::data( const QModelIndex& index, int role ) const +{ + if ( !index.isValid() ) + { + return QVariant(); + } + PackageTreeItem* item = static_cast( index.internalPointer() ); + if ( index.column() == 0 && role == Qt::CheckStateRole ) + { + return item->isSelected(); + } + + if ( !item->childCount() ) // package + { + if ( !item->parentItem()->isHidden() && role == Qt::DisplayRole && + index.column() == 0 ) + return QVariant( item->packageName() ); + else if ( role == PackageTreeItem::PackageNameRole ) + return QVariant( item->packageName() ); + else + return QVariant(); + } + + if ( item->isHidden() && role == Qt::DisplayRole ) // Hidden group + { + return QVariant(); + } + + switch ( role ) + { + case Qt::DisplayRole: + return item->data( index.column() ); + case PackageTreeItem::PreScriptRole: + return QVariant( item->preScript() ); + case PackageTreeItem::PackageNameRole: + return QVariant( item->packageName() ); + case PackageTreeItem::PostScriptRole: + return QVariant( item->postScript() ); + default: + return QVariant(); + } +} + +bool +PackageModel::setData( const QModelIndex& index, const QVariant& value, int role ) +{ + if ( role == Qt::CheckStateRole && index.isValid() ) + { + PackageTreeItem* item = static_cast( index.internalPointer() ); + item->setSelected( static_cast( value.toInt() ) ); + + emit dataChanged( this->index(0, 0), index.sibling( index.column(), index.row() + 1 ), + QVector( Qt::CheckStateRole ) ); + } + return true; +} + +Qt::ItemFlags +PackageModel::flags( const QModelIndex& index ) const +{ + if ( !index.isValid() ) + return 0; + if ( index.column() == 0 ) + return Qt::ItemIsUserCheckable | QAbstractItemModel::flags( index ); + return QAbstractItemModel::flags( index ); +} + +QVariant +PackageModel::headerData( int section, Qt::Orientation orientation, int role ) const +{ + if ( orientation == Qt::Horizontal && role == Qt::DisplayRole ) + return m_columnHeadings.value( section ); + return QVariant(); +} + +QList +PackageModel::getPackages( bool isCritical ) const +{ + QList items = getItemPackages( m_rootItem, isCritical ); + for ( auto package : m_hiddenItems ) + items.append( getItemPackages( package, isCritical ) ); + QList packages; + for ( auto item : items ) + { + QMap itemMap; + itemMap.insert( "pre-script", item->parentItem()->preScript() ); // Only groups have hooks + itemMap.insert( "package", item->packageName() ); + itemMap.insert( "post-script", item->parentItem()->postScript() ); + packages.append( QVariant( itemMap ) ); + } + return packages; +} + +QList +PackageModel::getItemPackages( PackageTreeItem* item, bool isCritical ) const +{ + QList selectedPackages; + for ( int i = 0; i < item->childCount(); i++ ) + { + if ( item->child( i )->isSelected() == Qt::Unchecked || + item->child( i )->isCritical() != isCritical ) + continue; + + if ( !item->child( i )->childCount() ) // package + selectedPackages.append( item->child( i ) ); + else + selectedPackages.append( getItemPackages( item->child( i ), isCritical ) ); + } + return selectedPackages; + +} + +void +PackageModel::setupModelData( const YAML::Node& data, PackageTreeItem* parent ) +{ + for ( YAML::const_iterator it = data.begin(); it != data.end(); ++it ) + { + const YAML::Node itemDefinition = *it; + + QString name( + tr( CalamaresUtils::yamlToVariant( itemDefinition["name"] ).toByteArray() ) ); + QString description( + tr( CalamaresUtils::yamlToVariant( itemDefinition["description"] ).toByteArray() ) ); + + PackageTreeItem::ItemData itemData; + 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(); + PackageTreeItem* item = new PackageTreeItem(itemData, parent ); + + if ( itemDefinition["selected"] ) + item->setSelected( + CalamaresUtils::yamlToVariant( itemDefinition["selected"] ).toBool() ? + 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() ); + + 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 ); + + if ( item->isHidden() ) + m_hiddenItems.append( item ); + else + { + item->setCheckable( true ); + parent->appendChild( item ); + } + } +} diff --git a/src/modules/netinstall/PackageModel.h b/src/modules/netinstall/PackageModel.h new file mode 100644 index 000000000..5a6a656bf --- /dev/null +++ b/src/modules/netinstall/PackageModel.h @@ -0,0 +1,64 @@ +/* === This file is part of Calamares - === + * + * Copyright (c) 2017, Kyle Robbertze + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#ifndef PACKAGEMODEL_H +#define PACKAGEMODEL_H + +#include "PackageTreeItem.h" + +#include +#include +#include + +#include + +// Required forward declarations +class PackageTreeItem; + +class PackageModel : public QAbstractItemModel +{ + Q_OBJECT + + public: + explicit PackageModel( const YAML::Node& data, const QVariantList& columnHeadings, + QObject* parent = 0 ); + ~PackageModel(); + + QVariant data( const QModelIndex& index, int role ) const Q_DECL_OVERRIDE; + bool setData( const QModelIndex& index, const QVariant& value, + int role = Qt::EditRole) Q_DECL_OVERRIDE; + Qt::ItemFlags flags( const QModelIndex& index ) const Q_DECL_OVERRIDE; + QVariant headerData( int section, Qt::Orientation orientation, + int role = Qt::DisplayRole ) const Q_DECL_OVERRIDE; + QModelIndex index( int row, int column, + const QModelIndex& parent = QModelIndex() ) const Q_DECL_OVERRIDE; + QModelIndex parent( const QModelIndex& index ) const Q_DECL_OVERRIDE; + int rowCount( const QModelIndex& parent = QModelIndex() ) const Q_DECL_OVERRIDE; + int columnCount( const QModelIndex& parent = QModelIndex() ) const Q_DECL_OVERRIDE; + QList getPackages( bool isCritical ) const; + QList getItemPackages( PackageTreeItem* item, bool isCritical ) const; + + private: + void setupModelData( const YAML::Node& data, PackageTreeItem* parent ); + + PackageTreeItem* m_rootItem; + QList m_hiddenItems; + QVariantList m_columnHeadings; +}; + +#endif // PACKAGEMODEL_H diff --git a/src/modules/netinstall/PackageTreeItem.cpp b/src/modules/netinstall/PackageTreeItem.cpp new file mode 100644 index 000000000..d77e99687 --- /dev/null +++ b/src/modules/netinstall/PackageTreeItem.cpp @@ -0,0 +1,203 @@ +/* === This file is part of Calamares - === + * + * Copyright (c) 2017, Kyle Robbertze + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#include "PackageTreeItem.h" + +#include "utils/Logger.h" // TODO:Remove + +PackageTreeItem::PackageTreeItem( const ItemData& data, PackageTreeItem* parent ) : + m_data( data ), + m_parentItem( parent ) +{ } + +PackageTreeItem::PackageTreeItem( const QString packageName, PackageTreeItem* parent ) : + m_packageName( packageName ), + m_parentItem( parent ), + m_selected( parent->isSelected() ) +{ } + +PackageTreeItem::PackageTreeItem( PackageTreeItem* parent ) : + m_parentItem( parent ) +{ } + +PackageTreeItem::~PackageTreeItem() +{ + qDeleteAll( m_childItems ); +} + +void +PackageTreeItem::appendChild( PackageTreeItem* child ) +{ + m_childItems.append( child ); +} + +PackageTreeItem* +PackageTreeItem::child( int row ) +{ + return m_childItems.value( row ); +} + +int +PackageTreeItem::childCount() const +{ + return m_childItems.count(); +} + +int +PackageTreeItem::row() const +{ + if ( m_parentItem ) + return m_parentItem->m_childItems.indexOf( const_cast( this ) ); + return 0; +} + +int +PackageTreeItem::columnCount() const +{ + return m_columns; +} + +QVariant +PackageTreeItem::data( int column ) const +{ + if ( m_packageName != nullptr ) // package + { + if ( column == 1 ) + return QVariant( packageName() ); + return QVariant(); + } + switch( column ) // group + { + case 0: + return QVariant( prettyName() ); + case 1: + return QVariant( description() ); + default: + return QVariant(); + } +} + +PackageTreeItem* +PackageTreeItem::parentItem() +{ + return m_parentItem; +} + +QString +PackageTreeItem::prettyName() const +{ + return m_data.name; +} + +QString +PackageTreeItem::description() const +{ + return m_data.description; +} + +QString +PackageTreeItem::preScript() const +{ + return m_data.preScript; +} + +QString +PackageTreeItem::packageName() const +{ + return m_packageName; +} + +QString +PackageTreeItem::postScript() const +{ + return m_data.postScript; +} + +bool +PackageTreeItem::isHidden() const +{ + return m_hidden; +} + +void +PackageTreeItem::setHidden( bool isHidden ) +{ + m_hidden = isHidden; +} + +bool +PackageTreeItem::isCritical() const +{ + return m_critical; +} + +void +PackageTreeItem::setCritical( bool isCritical ) +{ + m_critical = isCritical; +} + +Qt::CheckState +PackageTreeItem::isSelected() const +{ + return m_selected; +} + +void +PackageTreeItem::setSelected( Qt::CheckState isSelected ) +{ + m_selected = isSelected; + setChildrenSelected( isSelected ); + PackageTreeItem* currentItem = parentItem(); + while ( currentItem != nullptr ) + { + int childrenSelected = 0; + bool isChildPartiallySelected = false; + for ( int i = 0; i < currentItem->childCount(); i++ ) + { + if ( currentItem->child( i )->isSelected() == Qt::Checked ) + childrenSelected++; + if ( currentItem->child( i )->isSelected() == Qt::PartiallyChecked ) + isChildPartiallySelected = true; + } + if ( !childrenSelected && !isChildPartiallySelected) + currentItem->m_selected = Qt::Unchecked; + else if ( childrenSelected == currentItem->childCount() ) + currentItem->m_selected = Qt::Checked; + else + currentItem->m_selected = Qt::PartiallyChecked; + currentItem = currentItem->parentItem(); + } +} + +void +PackageTreeItem::setChildrenSelected( Qt::CheckState isSelected ) +{ + if ( isSelected != Qt::PartiallyChecked ) + for ( auto child : m_childItems ) + { + child->m_selected = isSelected; + child->setChildrenSelected( isSelected ); + } +} + +int +PackageTreeItem::type() const +{ + return QStandardItem::UserType; +} diff --git a/src/modules/netinstall/PackageTreeItem.h b/src/modules/netinstall/PackageTreeItem.h new file mode 100644 index 000000000..49f0a0822 --- /dev/null +++ b/src/modules/netinstall/PackageTreeItem.h @@ -0,0 +1,79 @@ +/* === This file is part of Calamares - === + * + * Copyright (c) 2017, Kyle Robbertze + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#ifndef PACKAGETREEITEM_H +#define PACKAGETREEITEM_H + +#include "NetInstallPage.h" + +#include +#include +#include + +class PackageTreeItem : public QStandardItem +{ + public: + struct ItemData { + QString name; + QString description; + QString preScript; + QString postScript; + }; + explicit PackageTreeItem( const ItemData& data, PackageTreeItem* parent = 0 ); + explicit PackageTreeItem( const QString packageName, PackageTreeItem* parent = 0 ); + explicit PackageTreeItem( PackageTreeItem* parent = 0 ); + ~PackageTreeItem(); + + void appendChild( PackageTreeItem* child ); + PackageTreeItem* child( int row ); + int childCount() const; + int columnCount() const; + QVariant data( int column ) const Q_DECL_OVERRIDE; + int row() const; + PackageTreeItem* parentItem(); + QString prettyName() const; + QString description() const; + QString preScript() const; + QString packageName() const; + QString postScript() const; + bool isHidden() const; + void setHidden( bool isHidden); + bool isCritical() const; + void setCritical( bool isCritical); + Qt::CheckState isSelected() const; + void setSelected( Qt::CheckState isSelected ); + void setChildrenSelected( Qt::CheckState isSelected ); + int type() const Q_DECL_OVERRIDE; + + static const int PreScriptRole = Qt::UserRole; + static const int PackageNameRole = Qt::UserRole + 1; + static const int PostScriptRole = Qt::UserRole + 2; + private: + QList m_childItems; + ItemData m_data; + QString m_packageName; + + // See README.md for a description of these two fields. + Qt::CheckState m_selected = Qt::Unchecked; + bool m_hidden = false; + bool m_critical = false; + const int m_columns = 2; // Name, description + PackageTreeItem* m_parentItem; +}; + +#endif // PACKAGETREEITEM_H diff --git a/src/modules/netinstall/page_netinst.ui b/src/modules/netinstall/page_netinst.ui index 3b7a260ec..033f30889 100644 --- a/src/modules/netinstall/page_netinst.ui +++ b/src/modules/netinstall/page_netinst.ui @@ -25,7 +25,7 @@ true - + 0 diff --git a/src/modules/netinstall/widgets/groupselectionwidget.cpp b/src/modules/netinstall/widgets/groupselectionwidget.cpp deleted file mode 100644 index 3048fb01f..000000000 --- a/src/modules/netinstall/widgets/groupselectionwidget.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2016, Luca Giambonini - * Copyright 2016, Lisa Vitolo - * - * Calamares is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Calamares is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Calamares. If not, see . - */ - -#include "groupselectionwidget.h" - -#include - -GroupSelectionWidget::GroupSelectionWidget( QString name, QString description, QStringList packages, bool selected, QWidget* parent ) : - QWidget( parent ), - m_isToggled( false ) -{ - ui.setupUi( this ); - - connect( ui.group, &QCheckBox::toggled, this, &GroupSelectionWidget::toggleGroup ); - - ui.group->setText( name ); - ui.group->setChecked( selected ); // also triggers the toggleGroup slot - ui.description->setText( description ); - const int columns = 4; - const int rows = ( packages.size() - 1 ) / columns + 1; - ui.packageview->setRowCount( rows ); - ui.packageview->setColumnCount( columns ); - - ui.packageview->horizontalHeader()->setSectionResizeMode( QHeaderView::Stretch ); - - int r = 0, c = 0; - for ( int i = 0; i < packages.size(); ++i ) - { - ui.packageview->setItem( r++,c, new QTableWidgetItem( packages.at( i ) ) ); - if ( r == ui.packageview->rowCount() ) - { - ++c; - r = 0; - } - } - - int rowsShown = 6; - rowsShown = rows < rowsShown ? rows : 6; - ui.packageview->setFixedHeight( rowsShown * ui.packageview->rowHeight( 0 ) ); - ui.packageview->hide(); -} - -void GroupSelectionWidget::toggleGroup( bool isToggled ) -{ - m_isToggled = isToggled; - emit toggled( isToggled ); -} - -bool GroupSelectionWidget::isToggled() const -{ - return m_isToggled; -} diff --git a/src/modules/netinstall/widgets/groupselectionwidget.h b/src/modules/netinstall/widgets/groupselectionwidget.h deleted file mode 100644 index 1f7a0fc97..000000000 --- a/src/modules/netinstall/widgets/groupselectionwidget.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2016, Luca Giambonini - * Copyright 2016, Lisa Vitolo - * - * Calamares is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Calamares is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Calamares. If not, see . - */ - -#ifndef GROUPSELECTIONWIDGET_H -#define GROUPSELECTIONWIDGET_H - -#include "ui_groupselectionwidget.h" - -#include -#include - -// Represents a widget to display and select a group. -class GroupSelectionWidget : public QWidget -{ - Q_OBJECT -public: - explicit GroupSelectionWidget( QString name, QString description, QStringList packages, bool selected, QWidget* parent = nullptr ); - - // Current status of the group: is it selected in the view? - bool isToggled() const; - -signals: - void toggled( bool ); - -public slots: - void toggleGroup( bool isToggled ); - -private: - Ui::GroupSelectionWidget ui; - static QSignalMapper* m_mapper; - - bool m_isToggled; -}; - -#endif // GROUPSELECTIONWIDGET_H diff --git a/src/modules/netinstall/widgets/groupselectionwidget.ui b/src/modules/netinstall/widgets/groupselectionwidget.ui deleted file mode 100644 index 8093b48e1..000000000 --- a/src/modules/netinstall/widgets/groupselectionwidget.ui +++ /dev/null @@ -1,138 +0,0 @@ - - - GroupSelectionWidget - - - - 0 - 0 - 805 - 62 - - - - - 0 - 0 - - - - Frame - - - - - - - - - group - - - - - - - description - - - - - - - - 0 - 0 - - - - - - - - :/images/arrow-down.png:/images/arrow-down.png - - - true - - - false - - - - - - - - - - true - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 0 - - - - QAbstractItemView::NoEditTriggers - - - false - - - false - - - false - - - QAbstractItemView::NoSelection - - - false - - - false - - - - - - - - - - - pushButton - toggled(bool) - packageview - setVisible(bool) - - - 772 - 25 - - - 653 - 61 - - - - - - toggled(bool) - -