From 698cff45c8ce5bf61ce9e38b1f7c5011bb860765 Mon Sep 17 00:00:00 2001 From: Teo Mrnjavac Date: Tue, 1 Jul 2014 17:45:28 +0200 Subject: [PATCH] Lots of model/view/delegate changes. Created delegate for ProgressTreeView. No more columns, only roles throughout the model. Added row types and some user roles to the model. Look and feel changes to ProgressTreeView. --- src/calamares/CMakeLists.txt | 1 + src/calamares/ViewManager.cpp | 25 ++++ src/calamares/ViewManager.h | 7 +- src/calamares/progresstree/CategoryItem.cpp | 12 +- src/calamares/progresstree/CategoryItem.h | 2 +- .../progresstree/ProgressTreeDelegate.cpp | 134 ++++++++++++++++++ .../progresstree/ProgressTreeDelegate.h | 48 +++++++ .../progresstree/ProgressTreeItem.cpp | 9 +- src/calamares/progresstree/ProgressTreeItem.h | 4 +- .../progresstree/ProgressTreeModel.cpp | 51 ++++++- .../progresstree/ProgressTreeModel.h | 17 +++ .../progresstree/ProgressTreeView.cpp | 22 +++ src/calamares/progresstree/ProgressTreeView.h | 3 + src/calamares/progresstree/ViewStepItem.cpp | 15 +- src/calamares/progresstree/ViewStepItem.h | 2 +- src/calamares/viewpages/ViewStep.h | 1 - 16 files changed, 335 insertions(+), 18 deletions(-) create mode 100644 src/calamares/progresstree/ProgressTreeDelegate.cpp create mode 100644 src/calamares/progresstree/ProgressTreeDelegate.h diff --git a/src/calamares/CMakeLists.txt b/src/calamares/CMakeLists.txt index 93cf10a38..1bc5c0f57 100644 --- a/src/calamares/CMakeLists.txt +++ b/src/calamares/CMakeLists.txt @@ -19,6 +19,7 @@ set( calamaresSources modulesystem/ViewModule.cpp progresstree/CategoryItem.cpp + progresstree/ProgressTreeDelegate.cpp progresstree/ProgressTreeItem.cpp progresstree/ProgressTreeModel.cpp progresstree/ProgressTreeView.cpp diff --git a/src/calamares/ViewManager.cpp b/src/calamares/ViewManager.cpp index 58cadd78e..d0e9521d6 100644 --- a/src/calamares/ViewManager.cpp +++ b/src/calamares/ViewManager.cpp @@ -89,6 +89,29 @@ ViewManager::addViewStep( ViewStep* step ) connect( step, &ViewStep::nextStatusChanged, m_next, &QPushButton::setEnabled ); + + emit currentStepChanged(); +} + + +QList< ViewStep* > +ViewManager::steps() const +{ + return m_steps; +} + + +ViewStep* +ViewManager::currentStep() const +{ + return m_steps.value( m_currentStep ); +} + + +int +ViewManager::currentStepIndex() const +{ + return m_currentStep; } @@ -100,6 +123,7 @@ ViewManager::next() { m_currentStep++; m_stack->setCurrentIndex( m_currentStep ); + emit currentStepChanged(); } else if ( !step->isAtEnd() ) { @@ -120,6 +144,7 @@ ViewManager::back() { m_currentStep--; m_stack->setCurrentIndex( m_currentStep ); + emit currentStepChanged(); } else if ( !step->isAtBeginning() ) { diff --git a/src/calamares/ViewManager.h b/src/calamares/ViewManager.h index eac31fdbc..a9bd04a2c 100644 --- a/src/calamares/ViewManager.h +++ b/src/calamares/ViewManager.h @@ -44,12 +44,17 @@ public: void addViewStep( ViewStep* step ); - QList< ViewStep* > steps() const { return m_steps; } + QList< ViewStep* > steps() const; + ViewStep* currentStep() const; + int currentStepIndex() const; public slots: void next(); void back(); +signals: + void currentStepChanged(); + private: static ViewManager* s_instance; diff --git a/src/calamares/progresstree/CategoryItem.cpp b/src/calamares/progresstree/CategoryItem.cpp index db0a6e473..396849815 100644 --- a/src/calamares/progresstree/CategoryItem.cpp +++ b/src/calamares/progresstree/CategoryItem.cpp @@ -18,6 +18,7 @@ #include "CategoryItem.h" +#include "ProgressTreeModel.h" CategoryItem::CategoryItem( const QString& text, ProgressTreeItem* parent ) : ProgressTreeItem( parent ) @@ -26,8 +27,13 @@ CategoryItem::CategoryItem( const QString& text, ProgressTreeItem* parent ) QVariant -CategoryItem::data( int column ) const +CategoryItem::data( int role ) const { - Q_UNUSED( column ); - return m_text; + if ( role == ProgressTreeModel::ProgressTreeItemTypeRole ) + return ProgressTreeModel::Category; + if ( role == ProgressTreeModel::ProgressTreeItemRole ) + return this; + if ( role == Qt::DisplayRole ) + return m_text; + return QVariant(); } diff --git a/src/calamares/progresstree/CategoryItem.h b/src/calamares/progresstree/CategoryItem.h index 4de539e36..d15e55d02 100644 --- a/src/calamares/progresstree/CategoryItem.h +++ b/src/calamares/progresstree/CategoryItem.h @@ -27,7 +27,7 @@ class CategoryItem : public ProgressTreeItem public: explicit CategoryItem( const QString& text, ProgressTreeItem* parent = nullptr ); - virtual QVariant data( int column ) const override; + virtual QVariant data( int role ) const override; private: QString m_text; diff --git a/src/calamares/progresstree/ProgressTreeDelegate.cpp b/src/calamares/progresstree/ProgressTreeDelegate.cpp new file mode 100644 index 000000000..02d6f4b57 --- /dev/null +++ b/src/calamares/progresstree/ProgressTreeDelegate.cpp @@ -0,0 +1,134 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, 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 "ProgressTreeDelegate.h" + +#include "../CalamaresApplication.h" +#include "../CalamaresWindow.h" +#include "ViewStepItem.h" +#include "ProgressTreeModel.h" +#include "../ViewManager.h" + +#include +#include + +ProgressTreeDelegate::ProgressTreeDelegate( QAbstractItemView* parent ) + : QStyledItemDelegate( parent ) + , m_parent( parent ) +{ +} + + +QSize +ProgressTreeDelegate::sizeHint( const QStyleOptionViewItem& option, + const QModelIndex& index ) const +{ + ProgressTreeModel::RowType type = + static_cast< ProgressTreeModel::RowType >( + index.data( ProgressTreeModel::ProgressTreeItemTypeRole ).toInt() ); + if ( type == ProgressTreeModel::Invalid ) + return option.rect.size(); + + QFont font = qApp->font(); + + if ( type == ProgressTreeModel::Category ) + { + font.setPointSize( font.pointSize() + 5 ); + } + else if ( type == ProgressTreeModel::ViewStep ) + { + font.setPointSize( font.pointSize() + 2 ); + } + QFontMetrics fm( font ); + int height = fm.height(); + + height += 2*12; //margin + + return QSize( option.rect.width(), height ); +} + + +void +ProgressTreeDelegate::paint( QPainter* painter, + const QStyleOptionViewItem& option, + const QModelIndex& index) const +{ + QStyleOptionViewItemV4 opt = option; + + painter->save(); + + ProgressTreeModel::RowType type = + static_cast< ProgressTreeModel::RowType >( + index.data( ProgressTreeModel::ProgressTreeItemTypeRole ).toInt() ); + if ( type == ProgressTreeModel::Invalid ) + return; + + initStyleOption( &opt, index ); + opt.text.clear(); + + painter->setBrush( QColor( "#292F34" ) ); + painter->setPen( QColor( "#FFFFFF" ) ); + + if ( type == ProgressTreeModel::Category ) + paintCategory( painter, opt, index ); + else if ( type == ProgressTreeModel::ViewStep ) + paintViewStep( painter, opt, index ); + + painter->restore(); +} + + +void +ProgressTreeDelegate::paintCategory( QPainter* painter, + const QStyleOptionViewItem& option, + const QModelIndex& index ) const +{ + QRect textRect = option.rect.adjusted( 12, 12, 12, 12 ); + + QFont font = qApp->font(); + font.setPointSize( font.pointSize() + 5 ); + font.setBold( false ); + painter->setFont( font ); + + painter->drawText( textRect, index.data().toString() ); +} + + +void +ProgressTreeDelegate::paintViewStep( QPainter* painter, + const QStyleOptionViewItem& option, + const QModelIndex& index ) const +{ + QRect textRect = option.rect.adjusted( 12 + 32 /*indentation*/, 12, 12, 12 ); + QFont font = qApp->font(); + font.setPointSize( font.pointSize() + 2 ); + font.setBold( false ); + painter->setFont( font ); + + bool isCurrent = false; + isCurrent = index.data( ProgressTreeModel::ProgressTreeItemCurrentRole ).toBool(); + + if ( isCurrent ) + { + painter->setPen( QColor( "#292F34" ) ); + painter->setBrush( APP->mainWindow()->palette().background() ); + } + + painter->fillRect( option.rect, painter->brush().color() ); + painter->drawText( textRect, index.data().toString() ); +} diff --git a/src/calamares/progresstree/ProgressTreeDelegate.h b/src/calamares/progresstree/ProgressTreeDelegate.h new file mode 100644 index 000000000..660623267 --- /dev/null +++ b/src/calamares/progresstree/ProgressTreeDelegate.h @@ -0,0 +1,48 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, 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 PROGRESSTREEDELEGATE_H +#define PROGRESSTREEDELEGATE_H + +#include + +class ProgressTreeDelegate : public QStyledItemDelegate +{ + Q_OBJECT +public: + explicit ProgressTreeDelegate( QAbstractItemView* parent = nullptr ); + +protected: + QSize sizeHint( const QStyleOptionViewItem& option, + const QModelIndex& index ) const override; + void paint( QPainter* painter, + const QStyleOptionViewItem& option, + const QModelIndex& index ) const override; + +private: + void paintCategory( QPainter* painter, + const QStyleOptionViewItem& option, + const QModelIndex& index ) const; + void paintViewStep( QPainter* painter, + const QStyleOptionViewItem& option, + const QModelIndex& index ) const; + + QAbstractItemView* m_parent; +}; + +#endif // PROGRESSTREEDELEGATE_H diff --git a/src/calamares/progresstree/ProgressTreeItem.cpp b/src/calamares/progresstree/ProgressTreeItem.cpp index 7316fc2f8..5d0dd9789 100644 --- a/src/calamares/progresstree/ProgressTreeItem.cpp +++ b/src/calamares/progresstree/ProgressTreeItem.cpp @@ -18,6 +18,8 @@ #include "ProgressTreeItem.h" +#include "ProgressTreeModel.h" + ProgressTreeItem::ProgressTreeItem( ProgressTreeItem* parent ) { @@ -82,8 +84,11 @@ ProgressTreeRoot::ProgressTreeRoot() QVariant -ProgressTreeRoot::data( int column ) const +ProgressTreeRoot::data( int role ) const { - Q_UNUSED( column ); + if ( role == ProgressTreeModel::ProgressTreeItemTypeRole ) + return ProgressTreeModel::Invalid; + if ( role == ProgressTreeModel::ProgressTreeItemRole ) + return this; return QVariant(); } diff --git a/src/calamares/progresstree/ProgressTreeItem.h b/src/calamares/progresstree/ProgressTreeItem.h index 332d3e7ae..66c07863a 100644 --- a/src/calamares/progresstree/ProgressTreeItem.h +++ b/src/calamares/progresstree/ProgressTreeItem.h @@ -34,7 +34,7 @@ public: virtual ProgressTreeItem* child( int row ); virtual int childCount() const; virtual int columnCount() const; - virtual QVariant data( int column ) const = 0; + virtual QVariant data( int role ) const = 0; virtual int row() const; virtual ProgressTreeItem* parent(); @@ -48,7 +48,7 @@ class ProgressTreeRoot : public ProgressTreeItem public: explicit ProgressTreeRoot(); - virtual QVariant data( int column ) const; + virtual QVariant data( int role ) const; }; #endif // PROGRESSTREEITEM_H diff --git a/src/calamares/progresstree/ProgressTreeModel.cpp b/src/calamares/progresstree/ProgressTreeModel.cpp index 01bd7c4a0..6ac44261e 100644 --- a/src/calamares/progresstree/ProgressTreeModel.cpp +++ b/src/calamares/progresstree/ProgressTreeModel.cpp @@ -88,12 +88,9 @@ ProgressTreeModel::data( const QModelIndex& index, int role ) const if ( !index.isValid() ) return QVariant(); - if ( role != Qt::DisplayRole ) - return QVariant(); - ProgressTreeItem *item = static_cast< ProgressTreeItem* >( index.internalPointer() ); - return item->data( index.column() ); + return item->data( role ); } @@ -147,3 +144,49 @@ ProgressTreeModel::setupModelData() m_rootItem->appendChild( new CategoryItem( tr( "Install" ), m_rootItem ) ); m_rootItem->appendChild( new CategoryItem( tr( "Finish" ), m_rootItem ) ); } + + +QModelIndex +ProgressTreeModel::indexFromItem( ProgressTreeItem* item ) +{ + if ( !item || !item->parent() ) + return QModelIndex(); + + + // Reconstructs a QModelIndex from a ProgressTreeItem that is somewhere in the tree. + // Traverses the item to the root node, then rebuilds the qmodeindices from there + // back down; each int is the row of that item in the parent. + /** + * In this diagram, if the \param item is G, childIndexList will contain [0, 2, 0] + * + * A + * D + * E + * F + * G + * H + * B + * C + * + **/ + QList< int > childIndexList; + ProgressTreeItem* curItem = item; + while ( curItem != m_rootItem ) { + int row = curItem->row(); //relative to its parent + if ( row < 0 ) // something went wrong, bail + return QModelIndex(); + + childIndexList << row; + + curItem = curItem->parent(); + } + + // Now we rebuild the QModelIndex we need + QModelIndex idx; + for ( int i = childIndexList.size() - 1; i >= 0 ; i-- ) + { + idx = index( childIndexList[ i ], 0, idx ); + } + + return idx; +} diff --git a/src/calamares/progresstree/ProgressTreeModel.h b/src/calamares/progresstree/ProgressTreeModel.h index 1cef8548e..fade29de3 100644 --- a/src/calamares/progresstree/ProgressTreeModel.h +++ b/src/calamares/progresstree/ProgressTreeModel.h @@ -22,14 +22,30 @@ #include class ProgressTreeRoot; +class ProgressTreeItem; class ProgressTreeModel : public QAbstractItemModel { Q_OBJECT public: + enum RowType + { + Invalid = -1, + Category = 0, + ViewStep = 1 + }; + + enum Role + { + ProgressTreeItemRole = Qt::UserRole + 10, + ProgressTreeItemTypeRole = Qt::UserRole + 11, + ProgressTreeItemCurrentRole = Qt::UserRole + 12 + }; + explicit ProgressTreeModel( QObject* parent = nullptr ); virtual ~ProgressTreeModel(); + // Reimplemented from QAbstractItemModel Qt::ItemFlags flags( const QModelIndex& index ) const override; QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const override; QModelIndex parent( const QModelIndex& index ) const override; @@ -40,6 +56,7 @@ public: private: void setupModelData(); + QModelIndex indexFromItem( ProgressTreeItem* item ); ProgressTreeRoot* m_rootItem; }; diff --git a/src/calamares/progresstree/ProgressTreeView.cpp b/src/calamares/progresstree/ProgressTreeView.cpp index 1fa1eb3f1..88ec5f9bb 100644 --- a/src/calamares/progresstree/ProgressTreeView.cpp +++ b/src/calamares/progresstree/ProgressTreeView.cpp @@ -18,6 +18,9 @@ #include "ProgressTreeView.h" +#include "ProgressTreeDelegate.h" +#include "ViewManager.h" + ProgressTreeView* ProgressTreeView::s_instance = nullptr; ProgressTreeView* @@ -43,7 +46,15 @@ ProgressTreeView::ProgressTreeView( QWidget* parent ) setAcceptDrops( false ); setUniformRowHeights( false ); + setIndentation( 0 ); setSortingEnabled( false ); + + m_delegate = new ProgressTreeDelegate( this ); + setItemDelegate( m_delegate ); + + QPalette plt = palette(); + plt.setColor( QPalette::Base, QColor( "#292F34" ) ); + setPalette( plt ); } @@ -56,6 +67,17 @@ ProgressTreeView::~ProgressTreeView() void ProgressTreeView::setModel( QAbstractItemModel* model ) { + if ( ProgressTreeView::model() ) + return; + QTreeView::setModel( model ); expandAll(); + + connect( Calamares::ViewManager::instance(), + &Calamares::ViewManager::currentStepChanged, + this, [this]() + { + viewport()->update(); + }, + Qt::UniqueConnection ); } diff --git a/src/calamares/progresstree/ProgressTreeView.h b/src/calamares/progresstree/ProgressTreeView.h index 382ad3f5d..b908449c2 100644 --- a/src/calamares/progresstree/ProgressTreeView.h +++ b/src/calamares/progresstree/ProgressTreeView.h @@ -21,6 +21,8 @@ #include +class ProgressTreeDelegate; + class ProgressTreeView : public QTreeView { Q_OBJECT @@ -34,6 +36,7 @@ public: private: static ProgressTreeView* s_instance; + ProgressTreeDelegate* m_delegate; }; #endif // PROGRESSTREEVIEW_H diff --git a/src/calamares/progresstree/ViewStepItem.cpp b/src/calamares/progresstree/ViewStepItem.cpp index d5be94241..6310e8589 100644 --- a/src/calamares/progresstree/ViewStepItem.cpp +++ b/src/calamares/progresstree/ViewStepItem.cpp @@ -18,6 +18,8 @@ #include "ViewStepItem.h" +#include "ProgressTreeModel.h" +#include "ViewManager.h" #include "viewpages/ViewStep.h" @@ -36,8 +38,15 @@ ViewStepItem::appendChild( ProgressTreeItem* item ) QVariant -ViewStepItem::data( int column ) const +ViewStepItem::data( int role ) const { - Q_UNUSED( column ); - return m_step->prettyName(); + if ( role == ProgressTreeModel::ProgressTreeItemTypeRole ) + return ProgressTreeModel::ViewStep; + if ( role == ProgressTreeModel::ProgressTreeItemRole ) + return this; + if ( role == Qt::DisplayRole ) + return m_step->prettyName(); + if ( role == ProgressTreeModel::ProgressTreeItemCurrentRole ) + return Calamares::ViewManager::instance()->currentStep() == m_step; + return QVariant(); } diff --git a/src/calamares/progresstree/ViewStepItem.h b/src/calamares/progresstree/ViewStepItem.h index a3c58a33f..e465d88d9 100644 --- a/src/calamares/progresstree/ViewStepItem.h +++ b/src/calamares/progresstree/ViewStepItem.h @@ -33,7 +33,7 @@ public: void appendChild( ProgressTreeItem* item ) override; - QVariant data( int column ) const override; + QVariant data( int role ) const override; private: const Calamares::ViewStep* m_step; diff --git a/src/calamares/viewpages/ViewStep.h b/src/calamares/viewpages/ViewStep.h index 76b9a8637..5382c0d5e 100644 --- a/src/calamares/viewpages/ViewStep.h +++ b/src/calamares/viewpages/ViewStep.h @@ -49,7 +49,6 @@ public: signals: void nextStatusChanged( bool status ); void done(); - }; }