diff --git a/src/modules/partition/CMakeLists.txt b/src/modules/partition/CMakeLists.txt index 9ff1208b8..252d3b7c5 100644 --- a/src/modules/partition/CMakeLists.txt +++ b/src/modules/partition/CMakeLists.txt @@ -38,6 +38,7 @@ calamares_add_plugin( partition gui/DeviceInfoWidget.cpp gui/PartitionPage.cpp gui/PartitionBarsView.cpp + gui/PartitionLabelsView.cpp gui/PartitionSizeController.cpp gui/PartitionSplitterWidget.cpp gui/PartitionViewStep.cpp diff --git a/src/modules/partition/gui/PartitionBarsView.cpp b/src/modules/partition/gui/PartitionBarsView.cpp index 5d3409c5b..3ebde12c7 100644 --- a/src/modules/partition/gui/PartitionBarsView.cpp +++ b/src/modules/partition/gui/PartitionBarsView.cpp @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License * along with Calamares. If not, see . */ -#include +#include "gui/PartitionBarsView.h" #include #include @@ -25,33 +25,19 @@ #include "utils/CalamaresUtilsGui.h" -#include // Qt #include #include -#include static const int VIEW_HEIGHT = CalamaresUtils::defaultFontHeight() + 8; -static const int LAYOUT_MARGIN = 8; static const int CORNER_RADIUS = 3; static const int EXTENDED_PARTITION_MARGIN = 4; -static const int LABELS_MARGIN = 40; -static const int LABEL_PARTITION_SQUARE_MARGIN = - qMax( QFontMetrics( CalamaresUtils::defaultFont() ).ascent() - 2, 18 ); -QStringList -buildUnknownDisklabelTexts( Device* dev ) -{ - QStringList texts = { QObject::tr( "Unpartitioned space or unknown partition table" ), - KFormat().formatByteSize( dev->totalSectors() * dev->logicalSectorSize() ) }; - return texts; -} PartitionBarsView::PartitionBarsView( QWidget* parent ) - : m_showLabels( false ) - , QAbstractItemView( parent ) + : QAbstractItemView( parent ) { setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ); setFrameStyle( QFrame::NoFrame ); @@ -73,12 +59,6 @@ PartitionBarsView::minimumSizeHint() const QSize PartitionBarsView::sizeHint() const { - QAbstractItemModel* modl = model(); - if ( m_showLabels && modl ) - { - return QSize( -1, VIEW_HEIGHT + LAYOUT_MARGIN + - sizeForAllLabels( rect().width() ).height() ); - } return QSize( -1, VIEW_HEIGHT ); } @@ -92,13 +72,10 @@ PartitionBarsView::paintEvent( QPaintEvent* event ) QRect partitionsRect = rect(); partitionsRect.setHeight( VIEW_HEIGHT ); - QRect labelsRect = rect().adjusted( 0, VIEW_HEIGHT + LAYOUT_MARGIN, 0, 0 ); painter.save(); drawPartitions( &painter, partitionsRect, QModelIndex() ); painter.restore(); - if ( m_showLabels ) - drawLabels( &painter, labelsRect, QModelIndex() ); } @@ -201,171 +178,6 @@ PartitionBarsView::drawPartitions( QPainter* painter, const QRect& rect, const Q } -static void -drawPartitionSquare( QPainter* painter, const QRect& rect, const QBrush& brush ) -{ - painter->fillRect( rect.adjusted( 1, 1, -1, -1 ), brush ); - painter->setRenderHint( QPainter::Antialiasing, true ); - painter->setPen( QPalette().shadow().color() ); - painter->translate( .5, .5 ); - painter->drawRoundedRect( rect.adjusted( 0, 0, -1, -1 ), 2, 2 ); - painter->translate( -.5, -.5 ); -} - - -QModelIndexList -PartitionBarsView::getIndexesToDraw( const QModelIndex& parent ) const -{ - QModelIndexList list; - - QAbstractItemModel* modl = model(); - if ( !modl ) - return list; - - for ( int row = 0; row < modl->rowCount( parent ); ++row ) - { - QModelIndex index = modl->index( row, 0, parent ); - if ( modl->hasChildren( index ) ) - list.append( getIndexesToDraw( index ) ); - else - list.append( index ); - } - return list; -} - - -void -PartitionBarsView::drawLabels( QPainter* painter, const QRect& rect, const QModelIndex& parent ) -{ - PartitionModel* modl = qobject_cast< PartitionModel* >( model() ); - if ( !modl ) - return; - - QModelIndexList indexesToDraw = getIndexesToDraw( parent ); - - int label_x = rect.x(); - int label_y = rect.y(); - foreach ( const QModelIndex& index, indexesToDraw ) - { - QStringList texts = { index.data().toString(), - index.sibling( index.row(), PartitionModel::SizeColumn ).data().toString() }; - - QSize labelSize = sizeForLabel( texts ); - - QColor labelColor = index.data( Qt::DecorationRole ).value< QColor >(); - - if ( label_x + labelSize.width() > rect.width() ) //wrap to new line if overflow - { - label_x = rect.x(); - label_y += labelSize.height(); - } - drawLabel( painter, texts, labelColor, QPoint( label_x, label_y ) ); - - label_x += labelSize.width() + LABELS_MARGIN; - } - - if ( !modl->rowCount() && - !modl->device()->partitionTable() ) // No disklabel or unknown - { - QStringList texts = buildUnknownDisklabelTexts( modl->device() ); - QSize labelSize = sizeForLabel( texts ); - QColor labelColor = ColorUtils::unknownDisklabelColor(); - drawLabel( painter, texts, labelColor, QPoint( rect.x(), rect.y() ) ); - } -} - - -QSize -PartitionBarsView::sizeForAllLabels( int maxLineWidth ) const -{ - PartitionModel* modl = qobject_cast< PartitionModel* >( model() ); - if ( !modl ) - return QSize(); - - QModelIndexList indexesToDraw = getIndexesToDraw( QModelIndex() ); - - int lineLength = 0; - int numLines = 1; - int singleLabelHeight = 0; - foreach ( const QModelIndex& index, indexesToDraw ) - { - QStringList texts = { index.data().toString(), - index.sibling( index.row(), - PartitionModel::SizeColumn ) - .data().toString() }; - QSize labelSize = sizeForLabel( texts ); - - if ( lineLength + labelSize.width() > maxLineWidth ) - { - numLines++; - lineLength = labelSize.width(); - } - else - { - lineLength += LABELS_MARGIN + labelSize.width(); - } - - singleLabelHeight = qMax( singleLabelHeight, labelSize.height() ); - } - - if ( !modl->rowCount() && - !modl->device()->partitionTable() ) // Unknown or no disklabel - { - singleLabelHeight = sizeForLabel( buildUnknownDisklabelTexts( modl->device() ) ) - .height(); - } - - int totalHeight = numLines * singleLabelHeight; - - return QSize( maxLineWidth, totalHeight ); -} - - -QSize -PartitionBarsView::sizeForLabel( const QStringList& text ) const -{ - int vertOffset = 0; - int width = 0; - foreach ( const QString& textLine, text ) - { - QSize textSize = fontMetrics().size( Qt::TextSingleLine, textLine ); - - vertOffset += textSize.height(); - width = qMax( width, textSize.width() ); - } - width += LABEL_PARTITION_SQUARE_MARGIN; //for the color square - return QSize( width, vertOffset ); -} - - -void -PartitionBarsView::drawLabel( QPainter* painter, - const QStringList& text, - const QColor& color, - const QPoint& pos ) -{ - painter->setPen( Qt::black ); - int vertOffset = 0; - int width = 0; - foreach ( const QString& textLine, text ) - { - QSize textSize = painter->fontMetrics().size( Qt::TextSingleLine, textLine ); - painter->drawText( pos.x()+LABEL_PARTITION_SQUARE_MARGIN, - pos.y() + vertOffset + textSize.height() / 2, - textLine ); - vertOffset += textSize.height(); - painter->setPen( Qt::gray ); - width = qMax( width, textSize.width() ); - } - drawPartitionSquare( painter, QRect( pos.x(), - pos.y() - 3, - LABEL_PARTITION_SQUARE_MARGIN - 5, - LABEL_PARTITION_SQUARE_MARGIN - 5 ), - color ); - painter->setPen( Qt::black ); -} - - QModelIndex PartitionBarsView::indexAt( const QPoint& point ) const { @@ -407,15 +219,6 @@ PartitionBarsView::scrollTo( const QModelIndex& index, ScrollHint hint ) } -void -PartitionBarsView::setLabelsVisible( bool visible ) -{ - m_showLabels = visible; - updateGeometry(); - repaint(); -} - - QModelIndex PartitionBarsView::moveCursor( CursorAction cursorAction, Qt::KeyboardModifiers modifiers ) { diff --git a/src/modules/partition/gui/PartitionBarsView.h b/src/modules/partition/gui/PartitionBarsView.h index f23e8270b..aa6cf3c69 100644 --- a/src/modules/partition/gui/PartitionBarsView.h +++ b/src/modules/partition/gui/PartitionBarsView.h @@ -32,7 +32,7 @@ class PartitionBarsView : public QAbstractItemView { public: explicit PartitionBarsView( QWidget* parent = nullptr ); - ~PartitionBarsView(); + virtual ~PartitionBarsView(); QSize minimumSizeHint() const override; @@ -45,8 +45,6 @@ public: QRect visualRect( const QModelIndex& index ) const override; void scrollTo( const QModelIndex& index, ScrollHint hint = EnsureVisible ) override; - void setLabelsVisible( bool visible = true ); - protected: // QAbstractItemView API QRegion visualRegionForSelection( const QItemSelection& selection ) const override; @@ -61,13 +59,6 @@ protected slots: private: void drawPartitions( QPainter* painter, const QRect& rect, const QModelIndex& parent ); - void drawLabels( QPainter* painter, const QRect& rect, const QModelIndex& parent ); - QSize sizeForAllLabels( int maxLineWidth ) const; - QSize sizeForLabel( const QStringList& text ) const; - void drawLabel( QPainter* painter, const QStringList& text, const QColor& color, const QPoint& pos ); - QModelIndexList getIndexesToDraw( const QModelIndex& parent ) const; - - bool m_showLabels; }; #endif /* PARTITIONPREVIEW_H */ diff --git a/src/modules/partition/gui/PartitionLabelsView.cpp b/src/modules/partition/gui/PartitionLabelsView.cpp new file mode 100644 index 000000000..af5b702ba --- /dev/null +++ b/src/modules/partition/gui/PartitionLabelsView.cpp @@ -0,0 +1,330 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Aurélien Gâteau + * Copyright 2015, Teo Mrnjavac + * + * 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 "PartitionLabelsView.h" + +#include +#include + +#include + +#include + +#include + +// Qt +#include + + +static const int LAYOUT_MARGIN = 4; +static const int LABELS_MARGIN = 40; +static const int LABEL_PARTITION_SQUARE_MARGIN = + qMax( QFontMetrics( CalamaresUtils::defaultFont() ).ascent() - 2, 18 ); + + +QStringList +buildUnknownDisklabelTexts( Device* dev ) +{ + QStringList texts = { QObject::tr( "Unpartitioned space or unknown partition table" ), + KFormat().formatByteSize( dev->totalSectors() * dev->logicalSectorSize() ) }; + return texts; +} + + +PartitionLabelsView::PartitionLabelsView( QWidget* parent ) + : QAbstractItemView( parent ) +{ + setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ); + setFrameStyle( QFrame::NoFrame ); +} + + +PartitionLabelsView::~PartitionLabelsView() +{ +} + + +QSize +PartitionLabelsView::minimumSizeHint() const +{ + return sizeHint(); +} + + + +QSize +PartitionLabelsView::sizeHint() const +{ + QAbstractItemModel* modl = model(); + if ( modl ) + { + return QSize( -1, LAYOUT_MARGIN + sizeForAllLabels( rect().width() ).height() ); + } + return QSize(); +} + + +void +PartitionLabelsView::paintEvent( QPaintEvent* event ) +{ + QPainter painter( viewport() ); + painter.fillRect( rect(), palette().window() ); + painter.setRenderHint( QPainter::Antialiasing ); + + QRect labelsRect = rect().adjusted( 0, LAYOUT_MARGIN, 0, 0 ); + + drawLabels( &painter, labelsRect, QModelIndex() ); +} + + +static void +drawPartitionSquare( QPainter* painter, const QRect& rect, const QBrush& brush ) +{ + painter->fillRect( rect.adjusted( 1, 1, -1, -1 ), brush ); + painter->setRenderHint( QPainter::Antialiasing, true ); + painter->setPen( QPalette().shadow().color() ); + painter->translate( .5, .5 ); + painter->drawRoundedRect( rect.adjusted( 0, 0, -1, -1 ), 2, 2 ); + painter->translate( -.5, -.5 ); +} + + +QModelIndexList +PartitionLabelsView::getIndexesToDraw( const QModelIndex& parent ) const +{ + QModelIndexList list; + + QAbstractItemModel* modl = model(); + if ( !modl ) + return list; + + for ( int row = 0; row < modl->rowCount( parent ); ++row ) + { + QModelIndex index = modl->index( row, 0, parent ); + if ( modl->hasChildren( index ) ) + list.append( getIndexesToDraw( index ) ); + else + list.append( index ); + } + return list; +} + + +void +PartitionLabelsView::drawLabels( QPainter* painter, + const QRect& rect, + const QModelIndex& parent ) +{ + PartitionModel* modl = qobject_cast< PartitionModel* >( model() ); + if ( !modl ) + return; + + QModelIndexList indexesToDraw = getIndexesToDraw( parent ); + + int label_x = rect.x(); + int label_y = rect.y(); + foreach ( const QModelIndex& index, indexesToDraw ) + { + QStringList texts = { index.data().toString(), + index.sibling( index.row(), + PartitionModel::SizeColumn ) + .data().toString() }; + + QSize labelSize = sizeForLabel( texts ); + + QColor labelColor = index.data( Qt::DecorationRole ).value< QColor >(); + + if ( label_x + labelSize.width() > rect.width() ) //wrap to new line if overflow + { + label_x = rect.x(); + label_y += labelSize.height(); + } + drawLabel( painter, texts, labelColor, QPoint( label_x, label_y ) ); + + label_x += labelSize.width() + LABELS_MARGIN; + } + + if ( !modl->rowCount() && + !modl->device()->partitionTable() ) // No disklabel or unknown + { + QStringList texts = buildUnknownDisklabelTexts( modl->device() ); + QSize labelSize = sizeForLabel( texts ); + QColor labelColor = ColorUtils::unknownDisklabelColor(); + drawLabel( painter, texts, labelColor, QPoint( rect.x(), rect.y() ) ); + } +} + + +QSize +PartitionLabelsView::sizeForAllLabels( int maxLineWidth ) const +{ + PartitionModel* modl = qobject_cast< PartitionModel* >( model() ); + if ( !modl ) + return QSize(); + + QModelIndexList indexesToDraw = getIndexesToDraw( QModelIndex() ); + + int lineLength = 0; + int numLines = 1; + int singleLabelHeight = 0; + foreach ( const QModelIndex& index, indexesToDraw ) + { + QStringList texts = { index.data().toString(), + index.sibling( index.row(), + PartitionModel::SizeColumn ) + .data().toString() }; + QSize labelSize = sizeForLabel( texts ); + + if ( lineLength + labelSize.width() > maxLineWidth ) + { + numLines++; + lineLength = labelSize.width(); + } + else + { + lineLength += LABELS_MARGIN + labelSize.width(); + } + + singleLabelHeight = qMax( singleLabelHeight, labelSize.height() ); + } + + if ( !modl->rowCount() && + !modl->device()->partitionTable() ) // Unknown or no disklabel + { + singleLabelHeight = sizeForLabel( buildUnknownDisklabelTexts( modl->device() ) ) + .height(); + } + + int totalHeight = numLines * singleLabelHeight; + + return QSize( maxLineWidth, totalHeight ); +} + + +QSize +PartitionLabelsView::sizeForLabel( const QStringList& text ) const +{ + int vertOffset = 0; + int width = 0; + foreach ( const QString& textLine, text ) + { + QSize textSize = fontMetrics().size( Qt::TextSingleLine, textLine ); + + vertOffset += textSize.height(); + width = qMax( width, textSize.width() ); + } + width += LABEL_PARTITION_SQUARE_MARGIN; //for the color square + return QSize( width, vertOffset ); +} + + +void +PartitionLabelsView::drawLabel( QPainter* painter, + const QStringList& text, + const QColor& color, + const QPoint& pos ) +{ + painter->setPen( Qt::black ); + int vertOffset = 0; + int width = 0; + foreach ( const QString& textLine, text ) + { + QSize textSize = painter->fontMetrics().size( Qt::TextSingleLine, textLine ); + painter->drawText( pos.x()+LABEL_PARTITION_SQUARE_MARGIN, + pos.y() + vertOffset + textSize.height() / 2, + textLine ); + vertOffset += textSize.height(); + painter->setPen( Qt::gray ); + width = qMax( width, textSize.width() ); + } + drawPartitionSquare( painter, QRect( pos.x(), + pos.y() - 3, + LABEL_PARTITION_SQUARE_MARGIN - 5, + LABEL_PARTITION_SQUARE_MARGIN - 5 ), + color ); + painter->setPen( Qt::black ); +} + + +QModelIndex +PartitionLabelsView::indexAt( const QPoint& point ) const +{ + return QModelIndex(); +} + + +QRect +PartitionLabelsView::visualRect( const QModelIndex& index ) const +{ + return QRect(); +} + + +QRegion +PartitionLabelsView::visualRegionForSelection( const QItemSelection& selection ) const +{ + return QRegion(); +} + + +int +PartitionLabelsView::horizontalOffset() const +{ + return 0; +} + + +int +PartitionLabelsView::verticalOffset() const +{ + return 0; +} + + +void +PartitionLabelsView::scrollTo( const QModelIndex& index, ScrollHint hint ) +{ +} + + +QModelIndex +PartitionLabelsView::moveCursor( CursorAction cursorAction, Qt::KeyboardModifiers modifiers ) +{ + return QModelIndex(); +} + + +bool +PartitionLabelsView::isIndexHidden( const QModelIndex& index ) const +{ + return false; +} + + +void +PartitionLabelsView::setSelection( const QRect& rect, QItemSelectionModel::SelectionFlags flags ) +{ +} + + +void +PartitionLabelsView::updateGeometries() +{ + updateGeometry(); //get a new rect() for redrawing all the labels +} diff --git a/src/modules/partition/gui/PartitionLabelsView.h b/src/modules/partition/gui/PartitionLabelsView.h new file mode 100644 index 000000000..b3dd0d541 --- /dev/null +++ b/src/modules/partition/gui/PartitionLabelsView.h @@ -0,0 +1,71 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Aurélien Gâteau + * Copyright 2015, Teo Mrnjavac + * + * 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 PARTITIONLABELSVIEW_H +#define PARTITIONLABELSVIEW_H + +#include + +/** + * A Qt model view which displays colored labels for partitions. + * + * It has been created to be used with a PartitionModel instance, but does not + * call any PartitionModel-specific methods: it should be usable with other + * models as long as they provide the same roles PartitionModel provides. + */ +class PartitionLabelsView : public QAbstractItemView +{ +public: + explicit PartitionLabelsView( QWidget* parent = nullptr ); + virtual ~PartitionLabelsView(); + + QSize minimumSizeHint() const override; + + QSize sizeHint() const override; + + void paintEvent( QPaintEvent* event ) override; + + // QAbstractItemView API + QModelIndex indexAt( const QPoint& point ) const override; + QRect visualRect( const QModelIndex& index ) const override; + void scrollTo( const QModelIndex& index, ScrollHint hint = EnsureVisible ) override; + + void setLabelsVisible( bool visible = true ); + +protected: + // QAbstractItemView API + QRegion visualRegionForSelection( const QItemSelection& selection ) const override; + int horizontalOffset() const override; + int verticalOffset() const override; + bool isIndexHidden( const QModelIndex& index ) const override; + QModelIndex moveCursor( CursorAction cursorAction, Qt::KeyboardModifiers modifiers ) override; + void setSelection( const QRect& rect, QItemSelectionModel::SelectionFlags flags ) override; + +protected slots: + void updateGeometries() override; + +private: + void drawLabels( QPainter* painter, const QRect& rect, const QModelIndex& parent ); + QSize sizeForAllLabels( int maxLineWidth ) const; + QSize sizeForLabel( const QStringList& text ) const; + void drawLabel( QPainter* painter, const QStringList& text, const QColor& color, const QPoint& pos ); + QModelIndexList getIndexesToDraw( const QModelIndex& parent ) const; +}; + +#endif // PARTITIONLABELSVIEW_H