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