calamares/src/modules/netinstall/PackageTreeItem.cpp

258 lines
6.4 KiB
C++
Raw Normal View History

/* === This file is part of Calamares - <https://github.com/calamares> ===
2017-01-23 13:42:40 +01:00
*
* Copyright (c) 2017, Kyle Robbertze <kyle@aims.ac.za>
2020-02-18 17:40:15 +01:00
* Copyright 2017, 2020, Adriaan de Groot <groot@kde.org>
2017-01-23 13:42:40 +01:00
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "PackageTreeItem.h"
#include "utils/Logger.h"
#include "utils/Variant.h"
static Qt::CheckState
parentCheckState( PackageTreeItem* parent )
2017-01-25 09:34:18 +01:00
{
if ( parent )
2020-02-18 11:02:53 +01:00
{
// Avoid partially-checked .. a package can't be partial
return parent->isSelected() == Qt::Unchecked ? Qt::Unchecked : Qt::Checked;
2020-02-18 11:02:53 +01:00
}
2017-01-25 09:34:18 +01:00
else
2020-02-18 11:02:53 +01:00
{
return Qt::Unchecked;
2020-02-18 11:02:53 +01:00
}
2017-01-25 09:34:18 +01:00
}
2017-01-23 13:42:40 +01:00
PackageTreeItem::PackageTreeItem( const QString& packageName, PackageTreeItem* parent )
: m_parentItem( parent )
, m_packageName( packageName )
, m_selected( parentCheckState( parent ) )
{
}
PackageTreeItem::PackageTreeItem( const QVariantMap& groupData, PackageTreeItem* parent )
: m_parentItem( parent )
, m_name( CalamaresUtils::getString( groupData, "name" ) )
, m_selected( parentCheckState( parent ) )
, m_description( CalamaresUtils::getString( groupData, "description" ) )
, m_preScript( CalamaresUtils::getString( groupData, "pre-install" ) )
, m_postScript( CalamaresUtils::getString( groupData, "post-install" ) )
, m_isCritical( CalamaresUtils::getBool( groupData, "critical", false ) )
, m_isHidden( CalamaresUtils::getBool( groupData, "hidden", false ) )
, m_showReadOnly( CalamaresUtils::getBool( groupData, "immutable", false ) )
, m_startExpanded( CalamaresUtils::getBool( groupData, "expanded", false ) )
{
}
2020-02-18 11:02:53 +01:00
PackageTreeItem::PackageTreeItem::PackageTreeItem()
: PackageTreeItem( QString(), nullptr )
{
m_selected = Qt::Checked;
m_name = QLatin1String( "<root>" );
}
2017-01-23 13:42:40 +01:00
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 )
2020-02-18 11:02:53 +01:00
{
return m_parentItem->m_childItems.indexOf( const_cast< PackageTreeItem* >( this ) );
}
2017-01-23 13:42:40 +01:00
return 0;
}
QVariant
PackageTreeItem::data( int column ) const
{
if ( !packageName().isEmpty() ) // packages have a packagename, groups don't
2017-01-23 13:42:40 +01:00
{
switch ( column )
2020-02-18 11:02:53 +01:00
{
case 0:
2017-01-23 13:42:40 +01:00
return QVariant( packageName() );
default:
return QVariant();
2020-02-18 11:02:53 +01:00
}
2017-01-23 13:42:40 +01:00
}
else
2017-01-23 13:42:40 +01:00
{
switch ( column ) // group
{
case 0:
return QVariant( name() );
case 1:
return QVariant( description() );
default:
return QVariant();
}
2017-01-23 13:42:40 +01:00
}
}
PackageTreeItem*
PackageTreeItem::parentItem()
{
return m_parentItem;
}
const PackageTreeItem*
PackageTreeItem::parentItem() const
{
return m_parentItem;
}
bool
PackageTreeItem::hiddenSelected() const
{
if ( !m_isHidden )
{
return m_selected;
}
if ( !m_selected )
2020-02-18 11:02:53 +01:00
{
return false;
2020-02-18 11:02:53 +01:00
}
const PackageTreeItem* currentItem = parentItem();
while ( currentItem != nullptr )
{
if ( !currentItem->isHidden() )
2020-02-18 11:02:53 +01:00
{
return currentItem->isSelected() != Qt::Unchecked;
2020-02-18 11:02:53 +01:00
}
currentItem = currentItem->parentItem();
}
/* Has no non-hiddent parents */
return m_selected;
}
2017-01-23 13:42:40 +01:00
void
PackageTreeItem::setSelected( Qt::CheckState isSelected )
{
if ( parentItem() == nullptr )
2020-02-18 11:02:53 +01:00
{
// This is the root, it is always checked so don't change state
return;
2020-02-18 11:02:53 +01:00
}
m_selected = isSelected;
2017-01-23 13:42:40 +01:00
setChildrenSelected( isSelected );
// Look for suitable parent item which may change checked-state
// when one of its children changes.
2017-01-23 13:42:40 +01:00
PackageTreeItem* currentItem = parentItem();
while ( ( currentItem != nullptr ) && ( currentItem->childCount() == 0 ) )
2017-01-23 13:42:40 +01:00
{
currentItem = currentItem->parentItem();
}
if ( currentItem == nullptr )
2020-02-18 11:02:53 +01:00
// Reached the root .. don't bother
{
return;
2020-02-18 11:02:53 +01:00
}
// Figure out checked-state based on the children
int childrenSelected = 0;
int childrenPartiallySelected = 0;
for ( int i = 0; i < currentItem->childCount(); i++ )
{
if ( currentItem->child( i )->isSelected() == Qt::Checked )
2020-02-18 11:02:53 +01:00
{
childrenSelected++;
2020-02-18 11:02:53 +01:00
}
if ( currentItem->child( i )->isSelected() == Qt::PartiallyChecked )
2020-02-18 11:02:53 +01:00
{
childrenPartiallySelected++;
2020-02-18 11:02:53 +01:00
}
}
2020-02-18 11:02:53 +01:00
if ( !childrenSelected && !childrenPartiallySelected )
{
currentItem->setSelected( Qt::Unchecked );
2020-02-18 11:02:53 +01:00
}
else if ( childrenSelected == currentItem->childCount() )
2020-02-18 11:02:53 +01:00
{
currentItem->setSelected( Qt::Checked );
2020-02-18 11:02:53 +01:00
}
else
2020-02-18 11:02:53 +01:00
{
currentItem->setSelected( Qt::PartiallyChecked );
2020-02-18 11:02:53 +01:00
}
2017-01-23 13:42:40 +01:00
}
void
PackageTreeItem::setChildrenSelected( Qt::CheckState isSelected )
{
if ( isSelected != Qt::PartiallyChecked )
// Children are never root; don't need to use setSelected on them.
2017-01-23 13:42:40 +01:00
for ( auto child : m_childItems )
{
child->m_selected = isSelected;
2017-01-23 13:42:40 +01:00
child->setChildrenSelected( isSelected );
}
}
int
PackageTreeItem::type() const
{
return QStandardItem::UserType;
}
QVariant
PackageTreeItem::toOperation() const
{
// If it's a package with a pre- or post-script, replace
// with the more complicated datastructure.
if ( !m_preScript.isEmpty() || !m_postScript.isEmpty() )
{
QMap< QString, QVariant > sdetails;
sdetails.insert( "pre-script", m_preScript );
sdetails.insert( "package", m_packageName );
sdetails.insert( "post-script", m_postScript );
return sdetails;
}
else
{
return m_packageName;
}
}