qt_demoe/qwtdemo/examples/stockchart/legend.cpp

354 lines
8.9 KiB
C++

#include "legend.h"
#include <qwt_legend_data.h>
#include <qwt_text.h>
#include <qwt_plot_item.h>
#include <qtreeview.h>
#include <qlayout.h>
#include <qstyle.h>
#include <qstandarditemmodel.h>
#include <qitemdelegate.h>
#include <qpainter.h>
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<QStandardItem *> 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<QStandardItemModel *>( model() );
for ( int row = 0; row < mdl->rowCount(); row++ )
{
QStandardItem *item = mdl->item( row );
if ( item->data() == rtti )
return item;
}
return NULL;
}
QList<QStandardItem *> LegendTreeView::itemList(
const QwtPlotItem *plotItem )
{
QList<QStandardItem *> 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<qlonglong>() )
{
const qlonglong ptr = key.value<qlonglong>();
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<QStandardItemModel *>( 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<const QStandardItemModel *>( 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<const QStandardItemModel *>( 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<QwtLegendData> &data )
{
QwtPlotItem *plotItem = qvariant_cast<QwtPlotItem *>( itemInfo );
QStandardItem *rootItem = d_treeView->rootItem( plotItem->rtti() );
QList<QStandardItem *> 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<QwtText>() )
{
item->setText( title.text() );
title = titleValue.value<QwtText>();
}
else if ( titleValue.canConvert<QString>() )
{
title.setText( titleValue.value<QString>() );
}
item->setText( title.text() );
const QVariant iconValue = data.value( QwtLegendData::IconRole );
QPixmap pm;
if ( iconValue.canConvert<QPixmap>() )
pm = iconValue.value<QPixmap>();
item->setData(pm, Qt::DecorationRole);
}
void Legend::handleClick( const QModelIndex &index )
{
const QStandardItemModel *model =
qobject_cast<QStandardItemModel *>( d_treeView->model() );
const QStandardItem *item = model->itemFromIndex( index );
if ( item->isCheckable() )
{
const qlonglong ptr = item->data().value<qlonglong>();
Q_EMIT checked( (QwtPlotItem *)ptr,
item->checkState() == Qt::Checked, 0 );
}
}