#include "legend.h" #include #include #include #include #include #include #include #include #include static void qwtRenderBackground( QPainter *painter, const QRectF &rect, const QWidget *widget ) { if ( widget->testAttribute( Qt::WA_StyledBackground ) ) { QStyleOption opt; opt.initFrom( widget ); opt.rect = rect.toAlignedRect(); widget->style()->drawPrimitive( QStyle::PE_Widget, &opt, painter, widget); } else { const QBrush brush = widget->palette().brush( widget->backgroundRole() ); painter->fillRect( rect, brush ); } } class LegendTreeView: public QTreeView { public: LegendTreeView( Legend * ); QStandardItem *rootItem( int rtti ); QStandardItem *insertRootItem( int rtti ); QList itemList( const QwtPlotItem * ); virtual QSize sizeHint() const; virtual QSize minimumSizeHint() const; }; LegendTreeView::LegendTreeView( Legend *legend ): QTreeView( legend ) { setFrameStyle( NoFrame ); viewport()->setBackgroundRole(QPalette::Background); viewport()->setAutoFillBackground( false ); setRootIsDecorated( true ); setHeaderHidden( true ); QStandardItemModel *model = new QStandardItemModel(); setModel( model ); // we want unstyled items setItemDelegate( new QItemDelegate( this ) ); } QStandardItem *LegendTreeView::rootItem( int rtti ) { QStandardItemModel *mdl = qobject_cast( model() ); for ( int row = 0; row < mdl->rowCount(); row++ ) { QStandardItem *item = mdl->item( row ); if ( item->data() == rtti ) return item; } return NULL; } QList LegendTreeView::itemList( const QwtPlotItem *plotItem ) { QList itemList; const QStandardItem *rootItem = this->rootItem( plotItem->rtti() ); if ( rootItem ) { for ( int i = 0; i < rootItem->rowCount(); i++ ) { QStandardItem *item = rootItem->child( i ); const QVariant key = item->data(); if ( key.canConvert() ) { const qlonglong ptr = key.value(); if ( ptr == qlonglong( plotItem ) ) itemList += item; } } } return itemList; } QStandardItem *LegendTreeView::insertRootItem( int rtti ) { QStandardItem *item = new QStandardItem(); item->setEditable( false ); item->setData( rtti ); switch( rtti ) { case QwtPlotItem::Rtti_PlotTradingCurve: { item->setText( "Curves" ); break; } case QwtPlotItem::Rtti_PlotZone: { item->setText( "Zones" ); break; } case QwtPlotItem::Rtti_PlotMarker: { item->setText( "Events" ); break; } default: break; } QStandardItemModel *mdl = qobject_cast( model() ); mdl->appendRow( item ); setExpanded( mdl->index( mdl->rowCount() - 1, 0 ), true ); return item; } QSize LegendTreeView::minimumSizeHint() const { return QSize( -1, -1 ); } QSize LegendTreeView::sizeHint() const { QStyleOptionViewItem styleOption; styleOption.initFrom( this ); const QAbstractItemDelegate *delegate = itemDelegate(); const QStandardItemModel *mdl = qobject_cast( model() ); int w = 0; int h = 0; for ( int row = 0; row < mdl->rowCount(); row++ ) { const QStandardItem *rootItem = mdl->item( row ); int wRow = 0; for ( int i = 0; i < rootItem->rowCount(); i++ ) { const QSize hint = delegate->sizeHint( styleOption, rootItem->child( i )->index() ); wRow = qMax( wRow, hint.width() ); h += hint.height(); } const QSize rootHint = delegate->sizeHint( styleOption, rootItem->index() ); wRow = qMax( wRow + indentation(), rootHint.width() ); if ( wRow > w ) w = wRow; if ( rootIsDecorated() ) w += indentation(); h += rootHint.height(); } int left, right, top, bottom; getContentsMargins( &left, &top, &right, &bottom ); w += left + right; h += top + bottom; return QSize( w, h ); } Legend::Legend( QWidget *parent ): QwtAbstractLegend( parent ) { d_treeView = new LegendTreeView( this ); QVBoxLayout *layout = new QVBoxLayout( this ); layout->setContentsMargins( 0, 0, 0, 0 ); layout->addWidget( d_treeView ); connect( d_treeView, SIGNAL( clicked( const QModelIndex & ) ), this, SLOT( handleClick( const QModelIndex & ) ) ); } Legend::~Legend() { } void Legend::renderLegend( QPainter *painter, const QRectF &rect, bool fillBackground ) const { if ( fillBackground ) { if ( autoFillBackground() || testAttribute( Qt::WA_StyledBackground ) ) { qwtRenderBackground( painter, rect, d_treeView ); } } QStyleOptionViewItem styleOption; styleOption.initFrom( this ); styleOption.decorationAlignment = Qt::AlignCenter; const QAbstractItemDelegate *delegate = d_treeView->itemDelegate(); const QStandardItemModel *mdl = qobject_cast( d_treeView->model() ); painter->save(); painter->translate( rect.topLeft() ); for ( int row = 0; row < mdl->rowCount(); row++ ) { const QStandardItem *rootItem = mdl->item( row ); styleOption.rect = d_treeView->visualRect( rootItem->index() ); if ( !styleOption.rect.isEmpty() ) delegate->paint( painter, styleOption, rootItem->index() ); for ( int i = 0; i < rootItem->rowCount(); i++ ) { const QStandardItem *item = rootItem->child( i ); styleOption.rect = d_treeView->visualRect( item->index() ); if ( !styleOption.rect.isEmpty() ) { delegate->paint( painter, styleOption, item->index() ); } } } painter->restore(); } bool Legend::isEmpty() const { return d_treeView->model()->rowCount() == 0; } int Legend::scrollExtent( Qt::Orientation orientation ) const { Q_UNUSED( orientation ); return style()->pixelMetric( QStyle::PM_ScrollBarExtent ); } void Legend::updateLegend( const QVariant &itemInfo, const QList &data ) { QwtPlotItem *plotItem = qvariant_cast( itemInfo ); QStandardItem *rootItem = d_treeView->rootItem( plotItem->rtti() ); QList itemList = d_treeView->itemList( plotItem ); while ( itemList.size() > data.size() ) { QStandardItem *item = itemList.takeLast(); rootItem->removeRow( item->row() ); } if ( !data.isEmpty() ) { if ( rootItem == NULL ) rootItem = d_treeView->insertRootItem( plotItem->rtti() ); while ( itemList.size() < data.size() ) { QStandardItem *item = new QStandardItem(); item->setEditable( false ); item->setData( qlonglong( plotItem ) ); item->setCheckable( true ); item->setCheckState( plotItem->isVisible() ? Qt::Checked : Qt::Unchecked ); itemList += item; rootItem->appendRow( item ); } for ( int i = 0; i < itemList.size(); i++ ) updateItem( itemList[i], data[i] ); } else { if ( rootItem && rootItem->rowCount() == 0 ) d_treeView->model()->removeRow( rootItem->row() ); } d_treeView->updateGeometry(); } void Legend::updateItem( QStandardItem *item, const QwtLegendData &data ) { const QVariant titleValue = data.value( QwtLegendData::TitleRole ); QwtText title; if ( titleValue.canConvert() ) { item->setText( title.text() ); title = titleValue.value(); } else if ( titleValue.canConvert() ) { title.setText( titleValue.value() ); } item->setText( title.text() ); const QVariant iconValue = data.value( QwtLegendData::IconRole ); QPixmap pm; if ( iconValue.canConvert() ) pm = iconValue.value(); item->setData(pm, Qt::DecorationRole); } void Legend::handleClick( const QModelIndex &index ) { const QStandardItemModel *model = qobject_cast( d_treeView->model() ); const QStandardItem *item = model->itemFromIndex( index ); if ( item->isCheckable() ) { const qlonglong ptr = item->data().value(); Q_EMIT checked( (QwtPlotItem *)ptr, item->checkState() == Qt::Checked, 0 ); } }