2017-12-20 14:39:09 +01:00
|
|
|
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
2014-07-29 13:37:32 +02:00
|
|
|
*
|
|
|
|
* Copyright 2014, Aurélien Gâteau <agateau@kde.org>
|
2016-01-13 15:15:26 +01:00
|
|
|
* Copyright 2015-2016, Teo Mrnjavac <teo@kde.org>
|
2014-07-29 13:37:32 +02: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/>.
|
|
|
|
*/
|
2015-12-03 19:38:56 +01:00
|
|
|
#include "gui/PartitionBarsView.h"
|
2014-07-29 13:37:32 +02:00
|
|
|
|
2014-08-08 13:25:56 +02:00
|
|
|
#include <core/PartitionModel.h>
|
2015-10-22 17:48:02 +02:00
|
|
|
#include <core/ColorUtils.h>
|
|
|
|
|
|
|
|
#include <kpmcore/core/device.h>
|
2014-07-29 13:37:32 +02:00
|
|
|
|
2015-12-04 18:02:19 +01:00
|
|
|
#include <utils/CalamaresUtilsGui.h>
|
|
|
|
#include <utils/Logger.h>
|
2015-04-17 17:24:28 +02:00
|
|
|
|
2015-10-22 17:48:02 +02:00
|
|
|
|
2014-07-29 13:37:32 +02:00
|
|
|
// Qt
|
|
|
|
#include <QDebug>
|
2016-02-16 14:09:44 +01:00
|
|
|
#include <QGuiApplication>
|
2015-12-04 18:02:19 +01:00
|
|
|
#include <QMouseEvent>
|
2014-07-29 13:37:32 +02:00
|
|
|
#include <QPainter>
|
|
|
|
|
|
|
|
|
2015-12-11 17:38:31 +01:00
|
|
|
static const int VIEW_HEIGHT = qMax( CalamaresUtils::defaultFontHeight() + 8, // wins out with big fonts
|
2017-09-21 10:04:01 +02:00
|
|
|
int( CalamaresUtils::defaultFontHeight() * 0.6 ) + 22 ); // wins out with small fonts
|
|
|
|
static constexpr int CORNER_RADIUS = 3;
|
2015-12-11 17:07:59 +01:00
|
|
|
static const int EXTENDED_PARTITION_MARGIN = qMax( 4, VIEW_HEIGHT / 6 );
|
2015-12-11 17:20:04 +01:00
|
|
|
|
|
|
|
// The SELECTION_MARGIN is applied within a hardcoded 2px padding anyway, so
|
|
|
|
// we start from EXTENDED_PARTITION_MARGIN - 2 in all cases.
|
|
|
|
// Then we try to ensure the selection rectangle fits exactly between the extended
|
|
|
|
// rectangle and the outer frame (the "/ 2" part), unless that's not possible, and in
|
|
|
|
// that case we at least make sure we have a 1px gap between the selection rectangle
|
|
|
|
// and the extended partition box (the "- 2" part).
|
|
|
|
// At worst, on low DPI systems, this will mean in order:
|
|
|
|
// 1px outer rect, 1 px gap, 1px selection rect, 1px gap, 1px extended partition rect.
|
|
|
|
static const int SELECTION_MARGIN = qMin( ( EXTENDED_PARTITION_MARGIN - 2 ) / 2,
|
|
|
|
( EXTENDED_PARTITION_MARGIN - 2 ) - 2 );
|
2014-07-29 13:37:32 +02:00
|
|
|
|
|
|
|
|
2015-12-03 17:19:02 +01:00
|
|
|
PartitionBarsView::PartitionBarsView( QWidget* parent )
|
2015-12-03 19:38:56 +01:00
|
|
|
: QAbstractItemView( parent )
|
2016-02-10 14:57:44 +01:00
|
|
|
, m_nestedPartitionsMode( NoNestedPartitions )
|
2016-01-15 16:55:23 +01:00
|
|
|
, canBeSelected( []( const QModelIndex& ) { return true; } )
|
2017-09-21 10:04:01 +02:00
|
|
|
, m_hoveredIndex( QModelIndex() )
|
2014-07-29 13:37:32 +02:00
|
|
|
{
|
|
|
|
setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
|
|
|
|
setFrameStyle( QFrame::NoFrame );
|
2015-12-10 16:13:31 +01:00
|
|
|
setSelectionBehavior( QAbstractItemView::SelectRows );
|
|
|
|
setSelectionMode( QAbstractItemView::SingleSelection );
|
2015-12-04 18:02:19 +01:00
|
|
|
|
|
|
|
// Debug
|
|
|
|
connect( this, &PartitionBarsView::clicked,
|
|
|
|
this, [=]( const QModelIndex& index )
|
|
|
|
{
|
2016-06-24 17:38:52 +02:00
|
|
|
cDebug() << "Clicked row" << index.row();
|
2015-12-04 18:02:19 +01:00
|
|
|
} );
|
|
|
|
setMouseTracking( true );
|
2014-07-29 13:37:32 +02:00
|
|
|
}
|
|
|
|
|
2015-04-17 12:40:56 +02:00
|
|
|
|
2015-12-03 17:19:02 +01:00
|
|
|
PartitionBarsView::~PartitionBarsView()
|
2014-07-29 13:37:32 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2015-04-17 12:40:56 +02:00
|
|
|
|
2016-02-10 14:57:44 +01:00
|
|
|
void
|
|
|
|
PartitionBarsView::setNestedPartitionsMode( PartitionBarsView::NestedPartitionsMode mode )
|
|
|
|
{
|
|
|
|
m_nestedPartitionsMode = mode;
|
|
|
|
viewport()->repaint();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-17 12:40:56 +02:00
|
|
|
QSize
|
2015-12-03 17:19:02 +01:00
|
|
|
PartitionBarsView::minimumSizeHint() const
|
2015-04-17 12:40:56 +02:00
|
|
|
{
|
|
|
|
return sizeHint();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-07-29 13:37:32 +02:00
|
|
|
QSize
|
2015-12-03 17:19:02 +01:00
|
|
|
PartitionBarsView::sizeHint() const
|
2014-07-29 13:37:32 +02:00
|
|
|
{
|
2015-04-22 11:17:22 +02:00
|
|
|
return QSize( -1, VIEW_HEIGHT );
|
2014-07-29 13:37:32 +02:00
|
|
|
}
|
|
|
|
|
2015-04-17 12:40:56 +02:00
|
|
|
|
2014-07-29 13:37:32 +02:00
|
|
|
void
|
2015-12-03 17:19:02 +01:00
|
|
|
PartitionBarsView::paintEvent( QPaintEvent* event )
|
2014-07-29 13:37:32 +02:00
|
|
|
{
|
|
|
|
QPainter painter( viewport() );
|
2014-07-29 15:56:25 +02:00
|
|
|
painter.fillRect( rect(), palette().window() );
|
|
|
|
painter.setRenderHint( QPainter::Antialiasing );
|
2015-04-17 17:24:28 +02:00
|
|
|
|
|
|
|
QRect partitionsRect = rect();
|
|
|
|
partitionsRect.setHeight( VIEW_HEIGHT );
|
|
|
|
|
|
|
|
painter.save();
|
|
|
|
drawPartitions( &painter, partitionsRect, QModelIndex() );
|
|
|
|
painter.restore();
|
2014-07-29 13:37:32 +02:00
|
|
|
}
|
|
|
|
|
2015-04-17 12:40:56 +02:00
|
|
|
|
2015-12-04 18:02:19 +01:00
|
|
|
void
|
|
|
|
PartitionBarsView::drawSection( QPainter* painter, const QRect& rect_, int x, int width, const QModelIndex& index )
|
2014-07-29 15:56:25 +02:00
|
|
|
{
|
2015-10-22 17:48:02 +02:00
|
|
|
QColor color = index.isValid() ?
|
|
|
|
index.data( Qt::DecorationRole ).value< QColor >() :
|
|
|
|
ColorUtils::unknownDisklabelColor();
|
|
|
|
bool isFreeSpace = index.isValid() ?
|
|
|
|
index.data( PartitionModel::IsFreeSpaceRole ).toBool() :
|
|
|
|
true;
|
2014-07-29 15:56:25 +02:00
|
|
|
|
|
|
|
QRect rect = rect_;
|
|
|
|
const int y = rect.y();
|
|
|
|
const int height = rect.height();
|
|
|
|
const int radius = qMax( 1, CORNER_RADIUS - ( VIEW_HEIGHT - height ) / 2 );
|
|
|
|
painter->setClipRect( x, y, width, height );
|
|
|
|
painter->translate( 0.5, 0.5 );
|
|
|
|
|
|
|
|
rect.adjust( 0, 0, -1, -1 );
|
2015-12-04 18:02:19 +01:00
|
|
|
|
|
|
|
|
2015-12-11 18:07:42 +01:00
|
|
|
if ( selectionMode() != QAbstractItemView::NoSelection && // no hover without selection
|
|
|
|
m_hoveredIndex.isValid() &&
|
2015-12-10 18:05:07 +01:00
|
|
|
index == m_hoveredIndex )
|
2015-12-10 16:13:31 +01:00
|
|
|
{
|
2016-02-16 13:55:44 +01:00
|
|
|
if ( canBeSelected( index ) )
|
|
|
|
painter->setBrush( color.lighter( 115 ) );
|
|
|
|
else
|
2016-02-16 14:06:28 +01:00
|
|
|
painter->setBrush( color );
|
2015-12-10 16:13:31 +01:00
|
|
|
}
|
2015-12-04 18:02:19 +01:00
|
|
|
else
|
2015-12-10 16:13:31 +01:00
|
|
|
{
|
2015-12-04 18:02:19 +01:00
|
|
|
painter->setBrush( color );
|
2015-12-10 16:13:31 +01:00
|
|
|
}
|
|
|
|
|
2015-12-11 16:52:06 +01:00
|
|
|
QColor borderColor = color.darker();
|
|
|
|
|
2015-12-10 16:13:31 +01:00
|
|
|
painter->setPen( borderColor );
|
2015-12-04 18:02:19 +01:00
|
|
|
|
2014-07-29 15:56:25 +02:00
|
|
|
painter->drawRoundedRect( rect, radius, radius );
|
|
|
|
|
|
|
|
// Draw shade
|
|
|
|
if ( !isFreeSpace )
|
|
|
|
rect.adjust( 2, 2, -2, -2 );
|
|
|
|
|
|
|
|
QLinearGradient gradient( 0, 0, 0, height / 2 );
|
|
|
|
|
|
|
|
qreal c = isFreeSpace ? 0 : 1;
|
|
|
|
gradient.setColorAt( 0, QColor::fromRgbF( c, c, c, 0.3 ) );
|
|
|
|
gradient.setColorAt( 1, QColor::fromRgbF( c, c, c, 0 ) );
|
|
|
|
|
|
|
|
painter->setPen( Qt::NoPen );
|
2015-12-11 16:52:06 +01:00
|
|
|
|
2014-07-29 15:56:25 +02:00
|
|
|
painter->setBrush( gradient );
|
|
|
|
painter->drawRoundedRect( rect, radius, radius );
|
|
|
|
|
2015-12-11 18:07:42 +01:00
|
|
|
if ( selectionMode() != QAbstractItemView::NoSelection &&
|
|
|
|
index.isValid() &&
|
2015-12-11 17:50:46 +01:00
|
|
|
selectionModel() &&
|
2015-12-11 17:49:45 +01:00
|
|
|
!selectionModel()->selectedIndexes().isEmpty() &&
|
|
|
|
selectionModel()->selectedIndexes().first() == index )
|
2015-12-11 16:52:06 +01:00
|
|
|
{
|
|
|
|
painter->setPen( QPen( borderColor, 1 ) );
|
|
|
|
QColor highlightColor = QPalette().highlight().color();
|
|
|
|
highlightColor = highlightColor.lighter( 500 );
|
|
|
|
highlightColor.setAlpha( 120 );
|
|
|
|
painter->setBrush( highlightColor );
|
|
|
|
|
|
|
|
QRect selectionRect = rect;
|
|
|
|
selectionRect.setX( x + 1 );
|
|
|
|
selectionRect.setWidth( width - 3 ); //account for the previous rect.adjust
|
|
|
|
|
|
|
|
if ( rect.x() > selectionRect.x() ) //hack for first item
|
|
|
|
selectionRect.adjust( rect.x() - selectionRect.x(), 0, 0, 0 );
|
|
|
|
|
|
|
|
if ( rect.right() < selectionRect.right() ) //hack for last item
|
|
|
|
selectionRect.adjust( 0, 0, - ( selectionRect.right() - rect.right() ), 0 );
|
|
|
|
|
2015-12-11 17:07:59 +01:00
|
|
|
selectionRect.adjust( SELECTION_MARGIN,
|
|
|
|
SELECTION_MARGIN,
|
|
|
|
-SELECTION_MARGIN,
|
|
|
|
-SELECTION_MARGIN );
|
2015-12-11 16:52:06 +01:00
|
|
|
|
|
|
|
painter->drawRoundedRect( selectionRect,
|
|
|
|
radius - 1,
|
|
|
|
radius - 1 );
|
|
|
|
}
|
|
|
|
|
2014-07-29 15:56:25 +02:00
|
|
|
painter->translate( -0.5, -0.5 );
|
|
|
|
}
|
|
|
|
|
2015-04-17 12:40:56 +02:00
|
|
|
|
2014-07-29 13:37:32 +02:00
|
|
|
void
|
2015-12-03 17:19:02 +01:00
|
|
|
PartitionBarsView::drawPartitions( QPainter* painter, const QRect& rect, const QModelIndex& parent )
|
2014-07-29 13:37:32 +02:00
|
|
|
{
|
2015-10-22 17:48:02 +02:00
|
|
|
PartitionModel* modl = qobject_cast< PartitionModel* >( model() );
|
2014-07-29 13:37:32 +02:00
|
|
|
if ( !modl )
|
|
|
|
return;
|
|
|
|
const int totalWidth = rect.width();
|
|
|
|
|
2015-12-04 18:02:19 +01:00
|
|
|
auto pair = computeItemsVector( parent );
|
|
|
|
QVector< PartitionBarsView::Item >& items = pair.first;
|
|
|
|
qreal& total = pair.second;
|
2014-07-29 13:37:32 +02:00
|
|
|
int x = rect.x();
|
2016-02-10 17:31:00 +01:00
|
|
|
for ( int row = 0; row < items.count(); ++row )
|
2014-07-29 13:37:32 +02:00
|
|
|
{
|
|
|
|
const auto& item = items[ row ];
|
|
|
|
int width;
|
2016-02-10 17:39:42 +01:00
|
|
|
if ( row < items.count() - 1 )
|
2014-07-29 13:37:32 +02:00
|
|
|
width = totalWidth * ( item.size / total );
|
|
|
|
else
|
|
|
|
// Make sure we fill the last pixel column
|
|
|
|
width = rect.right() - x + 1;
|
|
|
|
|
2016-02-10 15:33:31 +01:00
|
|
|
drawSection( painter, rect, x, width, item.index );
|
|
|
|
|
|
|
|
if ( m_nestedPartitionsMode == DrawNestedPartitions &&
|
|
|
|
modl->hasChildren( item.index ) )
|
2014-07-29 13:37:32 +02:00
|
|
|
{
|
2016-02-10 15:33:31 +01:00
|
|
|
QRect subRect(
|
|
|
|
x + EXTENDED_PARTITION_MARGIN,
|
|
|
|
rect.y() + EXTENDED_PARTITION_MARGIN,
|
|
|
|
width - 2 * EXTENDED_PARTITION_MARGIN,
|
|
|
|
rect.height() - 2 * EXTENDED_PARTITION_MARGIN
|
|
|
|
);
|
|
|
|
drawPartitions( painter, subRect, item.index );
|
2014-07-29 13:37:32 +02:00
|
|
|
}
|
|
|
|
x += width;
|
|
|
|
}
|
2015-10-22 17:48:02 +02:00
|
|
|
|
2016-02-10 17:39:42 +01:00
|
|
|
if ( !items.count() &&
|
2015-10-22 17:48:02 +02:00
|
|
|
!modl->device()->partitionTable() ) // No disklabel or unknown
|
|
|
|
{
|
|
|
|
int width = rect.right() - rect.x() + 1;
|
|
|
|
drawSection( painter, rect, rect.x(), width, QModelIndex() );
|
|
|
|
}
|
2014-07-29 13:37:32 +02:00
|
|
|
}
|
|
|
|
|
2015-04-17 12:40:56 +02:00
|
|
|
|
2014-07-29 13:37:32 +02:00
|
|
|
QModelIndex
|
2015-12-03 17:19:02 +01:00
|
|
|
PartitionBarsView::indexAt( const QPoint& point ) const
|
2014-07-29 13:37:32 +02:00
|
|
|
{
|
2015-12-04 18:02:19 +01:00
|
|
|
return indexAt( point, rect(), QModelIndex() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QModelIndex
|
2015-12-10 16:13:31 +01:00
|
|
|
PartitionBarsView::indexAt( const QPoint &point,
|
|
|
|
const QRect &rect,
|
|
|
|
const QModelIndex& parent ) const
|
2015-12-04 18:02:19 +01:00
|
|
|
{
|
|
|
|
PartitionModel* modl = qobject_cast< PartitionModel* >( model() );
|
|
|
|
if ( !modl )
|
|
|
|
return QModelIndex();
|
|
|
|
const int totalWidth = rect.width();
|
|
|
|
|
|
|
|
auto pair = computeItemsVector( parent );
|
|
|
|
QVector< PartitionBarsView::Item >& items = pair.first;
|
|
|
|
qreal& total = pair.second;
|
|
|
|
int x = rect.x();
|
2016-02-10 17:31:00 +01:00
|
|
|
for ( int row = 0; row < items.count(); ++row )
|
2015-12-04 18:02:19 +01:00
|
|
|
{
|
|
|
|
const auto& item = items[ row ];
|
|
|
|
int width;
|
2016-02-10 17:39:42 +01:00
|
|
|
if ( row < items.count() - 1 )
|
2015-12-04 18:02:19 +01:00
|
|
|
width = totalWidth * ( item.size / total );
|
|
|
|
else
|
|
|
|
// Make sure we fill the last pixel column
|
|
|
|
width = rect.right() - x + 1;
|
|
|
|
|
|
|
|
QRect thisItemRect( x, rect.y(), width, rect.height() );
|
|
|
|
if ( thisItemRect.contains( point ) )
|
|
|
|
{
|
2016-02-10 15:33:31 +01:00
|
|
|
if ( m_nestedPartitionsMode == DrawNestedPartitions &&
|
|
|
|
modl->hasChildren( item.index ) )
|
2015-12-04 18:02:19 +01:00
|
|
|
{
|
2016-02-10 15:33:31 +01:00
|
|
|
QRect subRect(
|
|
|
|
x + EXTENDED_PARTITION_MARGIN,
|
|
|
|
rect.y() + EXTENDED_PARTITION_MARGIN,
|
|
|
|
width - 2 * EXTENDED_PARTITION_MARGIN,
|
|
|
|
rect.height() - 2 * EXTENDED_PARTITION_MARGIN
|
|
|
|
);
|
2016-02-10 14:57:44 +01:00
|
|
|
|
2015-12-04 18:02:19 +01:00
|
|
|
if ( subRect.contains( point ) )
|
2015-12-10 19:20:27 +01:00
|
|
|
{
|
2015-12-04 18:02:19 +01:00
|
|
|
return indexAt( point, subRect, item.index );
|
2015-12-10 19:20:27 +01:00
|
|
|
}
|
2015-12-04 18:02:19 +01:00
|
|
|
return item.index;
|
|
|
|
}
|
|
|
|
else // contains but no children, we win
|
2015-12-10 19:20:27 +01:00
|
|
|
{
|
2015-12-04 18:02:19 +01:00
|
|
|
return item.index;
|
2015-12-10 19:20:27 +01:00
|
|
|
}
|
2015-12-04 18:02:19 +01:00
|
|
|
}
|
|
|
|
x += width;
|
|
|
|
}
|
|
|
|
|
2014-07-29 13:37:32 +02:00
|
|
|
return QModelIndex();
|
|
|
|
}
|
|
|
|
|
2015-04-17 12:40:56 +02:00
|
|
|
|
2014-07-29 13:37:32 +02:00
|
|
|
QRect
|
2015-12-03 17:19:02 +01:00
|
|
|
PartitionBarsView::visualRect( const QModelIndex& index ) const
|
2014-07-29 13:37:32 +02:00
|
|
|
{
|
2015-12-10 16:13:31 +01:00
|
|
|
return visualRect( index, rect(), QModelIndex() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QRect
|
|
|
|
PartitionBarsView::visualRect( const QModelIndex& index,
|
|
|
|
const QRect& rect,
|
|
|
|
const QModelIndex& parent ) const
|
|
|
|
{
|
|
|
|
PartitionModel* modl = qobject_cast< PartitionModel* >( model() );
|
|
|
|
if ( !modl )
|
|
|
|
return QRect();
|
|
|
|
const int totalWidth = rect.width();
|
|
|
|
|
|
|
|
auto pair = computeItemsVector( parent );
|
|
|
|
QVector< PartitionBarsView::Item >& items = pair.first;
|
|
|
|
qreal& total = pair.second;
|
|
|
|
int x = rect.x();
|
2016-02-10 17:31:00 +01:00
|
|
|
for ( int row = 0; row < items.count(); ++row )
|
2015-12-10 16:13:31 +01:00
|
|
|
{
|
|
|
|
const auto& item = items[ row ];
|
|
|
|
int width;
|
2016-02-10 17:39:42 +01:00
|
|
|
if ( row < items.count() - 1 )
|
2015-12-10 16:13:31 +01:00
|
|
|
width = totalWidth * ( item.size / total );
|
|
|
|
else
|
|
|
|
// Make sure we fill the last pixel column
|
|
|
|
width = rect.right() - x + 1;
|
|
|
|
|
|
|
|
QRect thisItemRect( x, rect.y(), width, rect.height() );
|
|
|
|
if ( item.index == index )
|
|
|
|
return thisItemRect;
|
|
|
|
|
2016-02-10 15:33:31 +01:00
|
|
|
if ( m_nestedPartitionsMode == DrawNestedPartitions &&
|
|
|
|
modl->hasChildren( item.index ) &&
|
2015-12-10 16:13:31 +01:00
|
|
|
index.parent() == item.index )
|
|
|
|
{
|
2016-02-10 15:33:31 +01:00
|
|
|
QRect subRect(
|
|
|
|
x + EXTENDED_PARTITION_MARGIN,
|
|
|
|
rect.y() + EXTENDED_PARTITION_MARGIN,
|
|
|
|
width - 2 * EXTENDED_PARTITION_MARGIN,
|
|
|
|
rect.height() - 2 * EXTENDED_PARTITION_MARGIN
|
|
|
|
);
|
2016-02-10 14:57:44 +01:00
|
|
|
|
2015-12-10 16:13:31 +01:00
|
|
|
QRect candidateVisualRect = visualRect( index, subRect, item.index );
|
|
|
|
if ( !candidateVisualRect.isNull() )
|
|
|
|
return candidateVisualRect;
|
|
|
|
}
|
|
|
|
|
|
|
|
x += width;
|
|
|
|
}
|
|
|
|
|
2014-07-29 13:37:32 +02:00
|
|
|
return QRect();
|
|
|
|
}
|
|
|
|
|
2015-04-17 12:40:56 +02:00
|
|
|
|
2014-07-29 13:37:32 +02:00
|
|
|
QRegion
|
2015-12-03 17:19:02 +01:00
|
|
|
PartitionBarsView::visualRegionForSelection( const QItemSelection& selection ) const
|
2014-07-29 13:37:32 +02:00
|
|
|
{
|
|
|
|
return QRegion();
|
|
|
|
}
|
|
|
|
|
2015-04-17 12:40:56 +02:00
|
|
|
|
2014-07-29 13:37:32 +02:00
|
|
|
int
|
2015-12-03 17:19:02 +01:00
|
|
|
PartitionBarsView::horizontalOffset() const
|
2014-07-29 13:37:32 +02:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-04-17 12:40:56 +02:00
|
|
|
|
2014-07-29 13:37:32 +02:00
|
|
|
int
|
2015-12-03 17:19:02 +01:00
|
|
|
PartitionBarsView::verticalOffset() const
|
2014-07-29 13:37:32 +02:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-04-17 12:40:56 +02:00
|
|
|
|
2014-07-29 13:37:32 +02:00
|
|
|
void
|
2015-12-03 17:19:02 +01:00
|
|
|
PartitionBarsView::scrollTo( const QModelIndex& index, ScrollHint hint )
|
2014-07-29 13:37:32 +02:00
|
|
|
{
|
2015-12-10 16:13:31 +01:00
|
|
|
Q_UNUSED( index )
|
|
|
|
Q_UNUSED( hint )
|
2014-07-29 13:37:32 +02:00
|
|
|
}
|
|
|
|
|
2015-04-17 12:40:56 +02:00
|
|
|
|
2016-01-13 15:15:26 +01:00
|
|
|
void
|
|
|
|
PartitionBarsView::setSelectionModel( QItemSelectionModel* selectionModel )
|
|
|
|
{
|
|
|
|
QAbstractItemView::setSelectionModel( selectionModel );
|
|
|
|
connect( selectionModel, &QItemSelectionModel::selectionChanged,
|
|
|
|
this, [=]
|
|
|
|
{
|
|
|
|
viewport()->repaint();
|
|
|
|
} );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-15 16:55:23 +01:00
|
|
|
void
|
|
|
|
PartitionBarsView::setSelectionFilter( std::function< bool ( const QModelIndex& ) > canBeSelected )
|
|
|
|
{
|
|
|
|
this->canBeSelected = canBeSelected;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-07-29 13:37:32 +02:00
|
|
|
QModelIndex
|
2017-09-21 10:04:01 +02:00
|
|
|
PartitionBarsView::moveCursor( CursorAction, Qt::KeyboardModifiers )
|
2014-07-29 13:37:32 +02:00
|
|
|
{
|
|
|
|
return QModelIndex();
|
|
|
|
}
|
|
|
|
|
2015-04-17 12:40:56 +02:00
|
|
|
|
2014-07-29 13:37:32 +02:00
|
|
|
bool
|
2017-09-21 10:04:01 +02:00
|
|
|
PartitionBarsView::isIndexHidden( const QModelIndex& ) const
|
2014-07-29 13:37:32 +02:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-04-17 12:40:56 +02:00
|
|
|
|
2014-07-29 13:37:32 +02:00
|
|
|
void
|
2015-12-03 17:19:02 +01:00
|
|
|
PartitionBarsView::setSelection( const QRect& rect, QItemSelectionModel::SelectionFlags flags )
|
2014-07-29 13:37:32 +02:00
|
|
|
{
|
2015-12-11 20:35:04 +01:00
|
|
|
//HACK: this is an utterly awful workaround, which is unfortunately necessary.
|
|
|
|
// QAbstractItemView::mousePressedEvent calls setSelection, but before that,
|
|
|
|
// for some mental reason, it works under the assumption that every item is a
|
|
|
|
// rectangle. This rectangle is provided by visualRect, and the idea mostly
|
|
|
|
// works, except when the item is an extended partition item, which is of course
|
|
|
|
// a rectangle with a rectangular hole in the middle.
|
|
|
|
// QAbstractItemView::mousePressEvent builds a QRect with x1, y1 in the center
|
|
|
|
// of said visualRect, and x2, y2 in the real QMouseEvent position.
|
|
|
|
// This may very well yield a QRect with negative size, which is meaningless.
|
|
|
|
// Therefore the QRect we get here is totally bogus, and its topLeft is outside
|
|
|
|
// the actual area of the item we need.
|
|
|
|
// What we need are the real coordinates of the QMouseEvent, and the only way to
|
|
|
|
// get them is by fetching the private x2, y2 from the rect.
|
|
|
|
// TL;DR: this sucks, look away. -- Teo 12/2015
|
2015-12-11 20:23:28 +01:00
|
|
|
int x1, y1, x2, y2;
|
|
|
|
rect.getCoords( &x1, &y1, &x2, &y2 );
|
2016-01-15 16:55:23 +01:00
|
|
|
|
|
|
|
QModelIndex eventIndex = indexAt( QPoint( x2, y2 ) );
|
|
|
|
if ( canBeSelected( eventIndex ) )
|
|
|
|
selectionModel()->select( eventIndex, flags );
|
|
|
|
|
2016-01-12 13:44:18 +01:00
|
|
|
viewport()->repaint();
|
2014-07-29 13:37:32 +02:00
|
|
|
}
|
|
|
|
|
2015-04-23 18:00:56 +02:00
|
|
|
|
2015-12-04 18:02:19 +01:00
|
|
|
void
|
|
|
|
PartitionBarsView::mouseMoveEvent( QMouseEvent* event )
|
|
|
|
{
|
|
|
|
QModelIndex candidateIndex = indexAt( event->pos() );
|
2015-12-10 18:05:07 +01:00
|
|
|
QPersistentModelIndex oldHoveredIndex = m_hoveredIndex;
|
2015-12-04 18:02:19 +01:00
|
|
|
if ( candidateIndex.isValid() )
|
|
|
|
{
|
2015-12-10 18:05:07 +01:00
|
|
|
m_hoveredIndex = candidateIndex;
|
2015-12-04 18:02:19 +01:00
|
|
|
}
|
|
|
|
else
|
2016-02-16 14:19:22 +01:00
|
|
|
{
|
2015-12-10 18:05:07 +01:00
|
|
|
m_hoveredIndex = QModelIndex();
|
2016-02-16 14:19:22 +01:00
|
|
|
QGuiApplication::restoreOverrideCursor();
|
|
|
|
}
|
2015-12-04 18:02:19 +01:00
|
|
|
|
2015-12-10 18:05:07 +01:00
|
|
|
if ( oldHoveredIndex != m_hoveredIndex )
|
2015-12-04 18:02:19 +01:00
|
|
|
{
|
2016-02-16 14:50:01 +01:00
|
|
|
if ( m_hoveredIndex.isValid() && !canBeSelected( m_hoveredIndex ) )
|
2016-02-16 14:27:54 +01:00
|
|
|
QGuiApplication::setOverrideCursor( Qt::ForbiddenCursor );
|
|
|
|
else
|
|
|
|
QGuiApplication::restoreOverrideCursor();
|
|
|
|
|
2015-12-04 18:02:19 +01:00
|
|
|
viewport()->repaint();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2017-09-21 10:04:01 +02:00
|
|
|
PartitionBarsView::leaveEvent( QEvent* )
|
2015-12-04 18:02:19 +01:00
|
|
|
{
|
2016-02-16 14:27:54 +01:00
|
|
|
QGuiApplication::restoreOverrideCursor();
|
2015-12-10 18:05:07 +01:00
|
|
|
if ( m_hoveredIndex.isValid() )
|
2015-12-04 18:02:19 +01:00
|
|
|
{
|
2015-12-10 18:05:07 +01:00
|
|
|
m_hoveredIndex = QModelIndex();
|
2015-12-04 18:02:19 +01:00
|
|
|
viewport()->repaint();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-15 18:35:19 +01:00
|
|
|
void
|
|
|
|
PartitionBarsView::mousePressEvent( QMouseEvent* event )
|
|
|
|
{
|
|
|
|
QModelIndex candidateIndex = indexAt( event->pos() );
|
|
|
|
if ( canBeSelected( candidateIndex ) )
|
|
|
|
QAbstractItemView::mousePressEvent( event );
|
|
|
|
else
|
|
|
|
event->accept();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-23 18:00:56 +02:00
|
|
|
void
|
2015-12-03 17:19:02 +01:00
|
|
|
PartitionBarsView::updateGeometries()
|
2015-04-23 18:00:56 +02:00
|
|
|
{
|
|
|
|
updateGeometry(); //get a new rect() for redrawing all the labels
|
|
|
|
}
|
2015-12-04 18:02:19 +01:00
|
|
|
|
|
|
|
|
|
|
|
QPair< QVector< PartitionBarsView::Item >, qreal >
|
|
|
|
PartitionBarsView::computeItemsVector( const QModelIndex& parent ) const
|
|
|
|
{
|
2016-02-10 15:33:31 +01:00
|
|
|
int count = model()->rowCount( parent );
|
|
|
|
QVector< PartitionBarsView::Item > items;
|
2015-12-04 18:02:19 +01:00
|
|
|
|
|
|
|
qreal total = 0;
|
|
|
|
for ( int row = 0; row < count; ++row )
|
|
|
|
{
|
|
|
|
QModelIndex index = model()->index( row, 0, parent );
|
2016-02-10 15:33:31 +01:00
|
|
|
if ( m_nestedPartitionsMode == NoNestedPartitions &&
|
|
|
|
model()->hasChildren( index ) )
|
|
|
|
{
|
|
|
|
QPair< QVector< PartitionBarsView::Item >, qreal > childVect =
|
|
|
|
computeItemsVector( index );
|
|
|
|
items += childVect.first;
|
|
|
|
total += childVect.second;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
qreal size = index.data( PartitionModel::SizeRole ).toLongLong();
|
|
|
|
total += size;
|
|
|
|
items.append( { size, index } );
|
|
|
|
}
|
2015-12-04 18:02:19 +01:00
|
|
|
}
|
|
|
|
|
2016-02-10 15:33:31 +01:00
|
|
|
count = items.count();
|
|
|
|
|
2016-01-08 17:55:04 +01:00
|
|
|
// The sizes we have are perfect, but now we have to hardcode a minimum size for small
|
|
|
|
// partitions and compensate for it in the total.
|
|
|
|
qreal adjustedTotal = total;
|
|
|
|
for ( int row = 0; row < count; ++row )
|
|
|
|
{
|
2016-01-08 18:09:19 +01:00
|
|
|
if ( items[ row ].size < 0.01 * total ) // If this item is smaller than 1% of everything,
|
|
|
|
{ // force its width to 1%.
|
2016-01-08 17:55:04 +01:00
|
|
|
adjustedTotal -= items[ row ].size;
|
2016-02-10 16:00:24 +01:00
|
|
|
items[ row ].size = 0.01 * total;
|
2016-01-08 17:55:04 +01:00
|
|
|
adjustedTotal += items[ row ].size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return qMakePair( items, adjustedTotal );
|
2015-12-04 18:02:19 +01:00
|
|
|
}
|
|
|
|
|