File indexing completed on 2024-05-12 04:20:44
0001 /* 0002 * SPDX-FileCopyrightText: 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved. 0003 * 0004 * This file is part of the KGantt library. 0005 * 0006 * SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "kganttlegend.h" 0010 #include "kganttlegend_p.h" 0011 0012 #include "kganttitemdelegate.h" 0013 0014 #include <QApplication> 0015 #include <QPainter> 0016 0017 #include <cassert> 0018 0019 using namespace KGantt; 0020 0021 0022 Legend::Legend( QWidget* parent ) 0023 : QAbstractItemView( parent ), 0024 _d( new Private ) 0025 { 0026 setItemDelegate( new ItemDelegate( this ) ); 0027 setFrameStyle( QFrame::NoFrame ); 0028 } 0029 0030 0031 Legend::~Legend() 0032 { 0033 delete _d; 0034 } 0035 0036 #define d d_func() 0037 0038 QModelIndex Legend::indexAt( const QPoint& point ) const 0039 { 0040 Q_UNUSED( point ); 0041 return QModelIndex(); 0042 } 0043 0044 QRect Legend::visualRect( const QModelIndex& index ) const 0045 { 0046 Q_UNUSED( index ); 0047 return QRect(); 0048 } 0049 0050 QSize Legend::sizeHint() const 0051 { 0052 return measureItem( rootIndex() ); 0053 } 0054 0055 QSize Legend::minimumSizeHint() const 0056 { 0057 return measureItem( rootIndex() ); 0058 } 0059 0060 void Legend::setModel( QAbstractItemModel* model ) 0061 { 0062 if ( this->model() != nullptr ) 0063 { 0064 disconnect( this->model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(modelDataChanged()) ); 0065 disconnect( this->model(), SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(modelDataChanged()) ); 0066 disconnect( this->model(), SIGNAL(columnsRemoved(QModelIndex,int,int)), this, SLOT(modelDataChanged()) ); 0067 } 0068 0069 QAbstractItemView::setModel( model ); 0070 d->proxyModel.setSourceModel( model ); 0071 0072 if ( this->model() != nullptr ) 0073 { 0074 connect( this->model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(modelDataChanged()) ); 0075 connect( this->model(), SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(modelDataChanged()) ); 0076 connect( this->model(), SIGNAL(columnsRemoved(QModelIndex,int,int)), this, SLOT(modelDataChanged()) ); 0077 } 0078 0079 } 0080 0081 0082 void Legend::modelDataChanged() 0083 { 0084 updateGeometry(); 0085 viewport()->update(); 0086 } 0087 0088 void Legend::paintEvent( QPaintEvent* event ) 0089 { 0090 Q_UNUSED( event ); 0091 // no model, no legend... 0092 if ( model() == nullptr ) 0093 return; 0094 0095 QPainter p( viewport() ); 0096 p.fillRect( viewport()->rect(), palette().color( QPalette::Window ) ); 0097 drawItem( &p, rootIndex() ); 0098 } 0099 0100 0101 StyleOptionGanttItem Legend::getStyleOption( const QModelIndex& index ) const 0102 { 0103 StyleOptionGanttItem opt; 0104 opt.displayPosition = StyleOptionGanttItem::Right; 0105 opt.displayAlignment = Qt::Alignment( d->proxyModel.data( index, Qt::TextAlignmentRole ).toInt() ); 0106 opt.text = index.model()->data( index, LegendRole ).toString(); 0107 opt.font = ( index.model()->data( index, Qt::FontRole ) ).value< QFont >(); 0108 return opt; 0109 } 0110 0111 0112 QRect Legend::drawItem( QPainter* painter, const QModelIndex& index, const QPoint& pos ) const 0113 { 0114 int xPos = pos.x(); 0115 int yPos = pos.y(); 0116 0117 if ( index.isValid() && index.model() == &d->proxyModel ) 0118 { 0119 ItemDelegate* const delegate = qobject_cast< ItemDelegate* >( itemDelegate( index ) ); 0120 assert( delegate != nullptr ); 0121 const QRect r( pos, measureItem( index, false ) ); 0122 StyleOptionGanttItem opt = getStyleOption( index ); 0123 opt.rect = r; 0124 opt.rect.setWidth( r.height() ); 0125 0126 const ItemType typ = static_cast<ItemType>( index.model()->data( index, ItemTypeRole ).toInt() ); 0127 const int dx = (typ == TypeEvent) ? (r.height() / 2) : 0; 0128 0129 opt.itemRect = opt.rect.adjusted(dx,0,dx,0); 0130 opt.boundingRect = r; 0131 opt.boundingRect.setWidth( r.width() + r.height() ); 0132 if ( !opt.text.isNull() ) 0133 delegate->paintGanttItem( painter, opt, index ); 0134 0135 xPos = r.right(); 0136 yPos = r.bottom(); 0137 } 0138 0139 0140 const int rowCount = d->proxyModel.rowCount( index ); 0141 for ( int row = 0; row < rowCount; ++row ) 0142 { 0143 const QRect r = drawItem( painter, d->proxyModel.index( row, 0, index ), QPoint( pos.x(), yPos ) ); 0144 xPos = qMax( xPos, r.right() ); 0145 yPos = qMax( yPos, r.bottom() ); 0146 } 0147 0148 return QRect( pos, QPoint( xPos, yPos ) ); 0149 } 0150 0151 0152 QSize Legend::measureItem( const QModelIndex& index, bool recursive ) const 0153 { 0154 if ( model() == nullptr ) 0155 return QSize(); 0156 0157 QSize baseSize; 0158 if ( index.model() != nullptr ) 0159 { 0160 QFontMetrics fm( ( index.model()->data( index, Qt::FontRole ) ).value< QFont >() ); 0161 const QString text = index.model()->data( index, LegendRole ).toString(); 0162 if ( !text.isEmpty() ) 0163 baseSize += QSize( fm.boundingRect( text ).width() + fm.height() + 2, fm.height() + 2 ); 0164 } 0165 0166 if ( !recursive ) 0167 return baseSize; 0168 0169 QSize childrenSize; 0170 0171 const int rowCount = d->proxyModel.rowCount( index ); 0172 for ( int row = 0; row < rowCount; ++row ) 0173 { 0174 const QSize childSize = measureItem( d->proxyModel.index( row, 0, index ) ); 0175 childrenSize.setWidth( qMax( childrenSize.width(), childSize.width() ) ); 0176 childrenSize.rheight() += childSize.height(); 0177 } 0178 return baseSize + childrenSize; 0179 }