Changeset 8127 in ntrip for trunk/BNC/qwt/qwt_legend.cpp


Ignore:
Timestamp:
May 10, 2017, 3:20:54 PM (7 years ago)
Author:
stoecker
Message:

update qwt and qwtpolar, many QT5 fixes (unfinished)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/BNC/qwt/qwt_legend.cpp

    r4271 r8127  
    99
    1010#include "qwt_legend.h"
    11 #include "qwt_legend_itemmanager.h"
    12 #include "qwt_legend_item.h"
     11#include "qwt_legend_label.h"
    1312#include "qwt_dyngrid_layout.h"
    1413#include "qwt_math.h"
     14#include "qwt_plot_item.h"
     15#include "qwt_painter.h"
    1516#include <qapplication.h>
    16 #include <qmap.h>
    1717#include <qscrollbar.h>
    1818#include <qscrollarea.h>
     19#include <qpainter.h>
     20#include <qstyle.h>
     21#include <qstyleoption.h>
     22
     23class QwtLegendMap
     24{
     25public:
     26    inline bool isEmpty() const { return d_entries.isEmpty(); }
     27
     28    void insert( const QVariant &, const QList<QWidget *> & );
     29    void remove( const QVariant & );
     30
     31    void removeWidget( const QWidget * );
     32
     33    QList<QWidget *> legendWidgets( const QVariant & ) const;
     34    QVariant itemInfo( const QWidget * ) const;
     35
     36private:
     37    // we don't know anything about itemInfo and therefore don't have
     38    // any key that can be used for a map or hashtab.
     39    // But a simple linear list is o.k. here, as we will never have
     40    // more than a few entries.
     41
     42    class Entry
     43    {
     44    public:
     45        QVariant itemInfo;
     46        QList<QWidget *> widgets;
     47    };
     48
     49    QList< Entry > d_entries;
     50};
     51
     52void QwtLegendMap::insert( const QVariant &itemInfo,
     53    const QList<QWidget *> &widgets )
     54{
     55    for ( int i = 0; i < d_entries.size(); i++ )
     56    {
     57        Entry &entry = d_entries[i];
     58        if ( entry.itemInfo == itemInfo )
     59        {
     60            entry.widgets = widgets;
     61            return;
     62        }
     63    }
     64
     65    Entry newEntry;
     66    newEntry.itemInfo = itemInfo;
     67    newEntry.widgets = widgets;
     68
     69    d_entries += newEntry;
     70}
     71
     72void QwtLegendMap::remove( const QVariant &itemInfo )
     73{
     74    for ( int i = 0; i < d_entries.size(); i++ )
     75    {
     76        Entry &entry = d_entries[i];
     77        if ( entry.itemInfo == itemInfo )
     78        {
     79            d_entries.removeAt( i );
     80            return;
     81        }
     82    }
     83}
     84
     85void QwtLegendMap::removeWidget( const QWidget *widget )
     86{
     87    QWidget *w = const_cast<QWidget *>( widget );
     88
     89    for ( int i = 0; i < d_entries.size(); i++ )
     90        d_entries[ i ].widgets.removeAll( w );
     91}
     92
     93QVariant QwtLegendMap::itemInfo( const QWidget *widget ) const
     94{
     95    if ( widget != NULL )
     96    {
     97        QWidget *w = const_cast<QWidget *>( widget );
     98
     99        for ( int i = 0; i < d_entries.size(); i++ )
     100        {
     101            const Entry &entry = d_entries[i];
     102            if ( entry.widgets.indexOf( w ) >= 0 )
     103                return entry.itemInfo;
     104        }
     105    }
     106
     107    return QVariant();
     108}
     109
     110QList<QWidget *> QwtLegendMap::legendWidgets( const QVariant &itemInfo ) const
     111{
     112    if ( itemInfo.isValid() )
     113    {
     114        for ( int i = 0; i < d_entries.size(); i++ )
     115        {
     116            const Entry &entry = d_entries[i];
     117            if ( entry.itemInfo == itemInfo )
     118                return entry.widgets;
     119        }
     120    }
     121
     122    return QList<QWidget *>();
     123}
    19124
    20125class QwtLegend::PrivateData
    21126{
    22127public:
    23     class LegendMap
    24     {
    25     public:
    26         void insert( const QwtLegendItemManager *, QWidget * );
    27 
    28         void remove( const QwtLegendItemManager * );
    29         void remove( QWidget * );
    30 
    31         void clear();
    32 
    33         uint count() const;
    34 
    35         inline const QWidget *find( const QwtLegendItemManager * ) const;
    36         inline QWidget *find( const QwtLegendItemManager * );
    37 
    38         inline const QwtLegendItemManager *find( const QWidget * ) const;
    39         inline QwtLegendItemManager *find( const QWidget * );
    40 
    41         const QMap<QWidget *, const QwtLegendItemManager *> &widgetMap() const;
    42         QMap<QWidget *, const QwtLegendItemManager *> &widgetMap();
    43 
    44     private:
    45         QMap<QWidget *, const QwtLegendItemManager *> d_widgetMap;
    46         QMap<const QwtLegendItemManager *, QWidget *> d_itemMap;
    47     };
    48 
    49     QwtLegend::LegendItemMode itemMode;
    50 
    51     LegendMap map;
     128    PrivateData():
     129        itemMode( QwtLegendData::ReadOnly ),
     130        view( NULL )
     131    {
     132    }
     133
     134    QwtLegendData::Mode itemMode;
     135    QwtLegendMap itemMap;
    52136
    53137    class LegendView;
     
    61145        QScrollArea( parent )
    62146    {
    63         setFocusPolicy( Qt::NoFocus );
    64 
    65147        contentsWidget = new QWidget( this );
    66148        contentsWidget->setObjectName( "QwtLegendViewContents" );
     
    77159    }
    78160
    79     virtual bool viewportEvent( QEvent *e )
    80     {
    81         bool ok = QScrollArea::viewportEvent( e );
    82 
    83         if ( e->type() == QEvent::Resize )
    84         {
    85             QEvent event( QEvent::LayoutRequest );
    86             QApplication::sendEvent( contentsWidget, &event );
     161    virtual bool event( QEvent *event )
     162    {
     163        if ( event->type() == QEvent::PolishRequest )
     164        {
     165            setFocusPolicy( Qt::NoFocus );
     166        }
     167
     168        if ( event->type() == QEvent::Resize )
     169        {
     170            // adjust the size to en/disable the scrollbars
     171            // before QScrollArea adjusts the viewport size
     172
     173            const QRect cr = contentsRect();
     174
     175            int w = cr.width();
     176            int h = contentsWidget->heightForWidth( cr.width() );
     177            if ( h > w )
     178            {
     179                w -= verticalScrollBar()->sizeHint().width();
     180                h = contentsWidget->heightForWidth( w );
     181            }
     182
     183            contentsWidget->resize( w, h );
     184        }
     185
     186        return QScrollArea::event( event );
     187    }
     188
     189    virtual bool viewportEvent( QEvent *event )
     190    {
     191        bool ok = QScrollArea::viewportEvent( event );
     192
     193        if ( event->type() == QEvent::Resize )
     194        {
     195            layoutContents();
    87196        }
    88197        return ok;
     
    112221    }
    113222
     223    void layoutContents()
     224    {
     225        const QwtDynGridLayout *tl = qobject_cast<QwtDynGridLayout *>(
     226            contentsWidget->layout() );
     227        if ( tl == NULL )
     228            return;
     229
     230        const QSize visibleSize = viewport()->contentsRect().size();
     231
     232        const int minW = int( tl->maxItemWidth() ) + 2 * tl->margin();
     233
     234        int w = qMax( visibleSize.width(), minW );
     235        int h = qMax( tl->heightForWidth( w ), visibleSize.height() );
     236
     237        const int vpWidth = viewportSize( w, h ).width();
     238        if ( w > vpWidth )
     239        {
     240            w = qMax( vpWidth, minW );
     241            h = qMax( tl->heightForWidth( w ), visibleSize.height() );
     242        }
     243
     244        contentsWidget->resize( w, h );
     245    }
     246
    114247    QWidget *contentsWidget;
    115248};
    116249
    117 void QwtLegend::PrivateData::LegendMap::insert(
    118     const QwtLegendItemManager *item, QWidget *widget )
    119 {
    120     d_itemMap.insert( item, widget );
    121     d_widgetMap.insert( widget, item );
    122 }
    123 
    124 void QwtLegend::PrivateData::LegendMap::remove( const QwtLegendItemManager *item )
    125 {
    126     QWidget *widget = d_itemMap[item];
    127     d_itemMap.remove( item );
    128     d_widgetMap.remove( widget );
    129 }
    130 
    131 void QwtLegend::PrivateData::LegendMap::remove( QWidget *widget )
    132 {
    133     const QwtLegendItemManager *item = d_widgetMap[widget];
    134     d_itemMap.remove( item );
    135     d_widgetMap.remove( widget );
    136 }
    137 
    138 void QwtLegend::PrivateData::LegendMap::clear()
    139 {
    140 
    141     /*
    142        We can't delete the widgets in the following loop, because
    143        we would get ChildRemoved events, changing d_itemMap, while
    144        we are iterating.
    145      */
    146 
    147     QList<const QWidget *> widgets;
    148 
    149     QMap<const QwtLegendItemManager *, QWidget *>::const_iterator it;
    150     for ( it = d_itemMap.begin(); it != d_itemMap.end(); ++it )
    151         widgets.append( it.value() );
    152 
    153     d_itemMap.clear();
    154     d_widgetMap.clear();
    155 
    156     for ( int i = 0; i < widgets.size(); i++ )
    157         delete widgets[i];
    158 }
    159 
    160 uint QwtLegend::PrivateData::LegendMap::count() const
    161 {
    162     return d_itemMap.count();
    163 }
    164 
    165 inline const QWidget *QwtLegend::PrivateData::LegendMap::find(
    166     const QwtLegendItemManager *item ) const
    167 {
    168     if ( !d_itemMap.contains( item ) )
    169         return NULL;
    170 
    171     return d_itemMap[item];
    172 }
    173 
    174 inline QWidget *QwtLegend::PrivateData::LegendMap::find(
    175     const QwtLegendItemManager *item )
    176 {
    177     if ( !d_itemMap.contains( item ) )
    178         return NULL;
    179 
    180     return d_itemMap[item];
    181 }
    182 
    183 inline const QwtLegendItemManager *QwtLegend::PrivateData::LegendMap::find(
    184     const QWidget *widget ) const
    185 {
    186     QWidget *w = const_cast<QWidget *>( widget );
    187     if ( !d_widgetMap.contains( w ) )
    188         return NULL;
    189 
    190     return d_widgetMap[w];
    191 }
    192 
    193 inline QwtLegendItemManager *QwtLegend::PrivateData::LegendMap::find(
    194     const QWidget *widget )
    195 {
    196     QWidget *w = const_cast<QWidget *>( widget );
    197     if ( !d_widgetMap.contains( w ) )
    198         return NULL;
    199 
    200     return const_cast<QwtLegendItemManager *>( d_widgetMap[w] );
    201 }
    202 
    203 inline const QMap<QWidget *, const QwtLegendItemManager *> &
    204 QwtLegend::PrivateData::LegendMap::widgetMap() const
    205 {
    206     return d_widgetMap;
    207 }
    208 
    209 inline QMap<QWidget *, const QwtLegendItemManager *> &
    210 QwtLegend::PrivateData::LegendMap::widgetMap()
    211 {
    212     return d_widgetMap;
    213 }
    214 
    215250/*!
    216251  Constructor
    217 
    218252  \param parent Parent widget
    219253*/
    220254QwtLegend::QwtLegend( QWidget *parent ):
    221     QFrame( parent )
     255    QwtAbstractLegend( parent )
    222256{
    223257    setFrameStyle( NoFrame );
    224258
    225259    d_data = new QwtLegend::PrivateData;
    226     d_data->itemMode = QwtLegend::ReadOnlyItem;
    227260
    228261    d_data->view = new QwtLegend::PrivateData::LegendView( this );
     
    247280}
    248281
    249 //! \sa LegendItemMode
    250 void QwtLegend::setItemMode( LegendItemMode mode )
     282/*!
     283  \brief Set the maximum number of entries in a row
     284
     285  F.e when the maximum is set to 1 all items are aligned
     286  vertically. 0 means unlimited
     287
     288  \param numColums Maximum number of entries in a row
     289
     290  \sa maxColumns(), QwtDynGridLayout::setMaxColumns()
     291 */
     292void QwtLegend::setMaxColumns( uint numColums )
     293{
     294    QwtDynGridLayout *tl = qobject_cast<QwtDynGridLayout *>(
     295        d_data->view->contentsWidget->layout() );
     296    if ( tl )
     297        tl->setMaxColumns( numColums );
     298}
     299
     300/*!
     301  \return Maximum number of entries in a row
     302  \sa setMaxColumns(), QwtDynGridLayout::maxColumns()
     303 */
     304uint QwtLegend::maxColumns() const
     305{
     306    uint maxCols = 0;
     307
     308    const QwtDynGridLayout *tl = qobject_cast<const QwtDynGridLayout *>(
     309        d_data->view->contentsWidget->layout() );
     310    if ( tl )
     311        maxCols = tl->maxColumns();
     312
     313    return maxCols;
     314}
     315
     316/*!
     317  \brief Set the default mode for legend labels
     318
     319  Legend labels will be constructed according to the
     320  attributes in a QwtLegendData object. When it doesn't
     321  contain a value for the QwtLegendData::ModeRole the
     322  label will be initialized with the default mode of the legend.
     323
     324  \param mode Default item mode
     325
     326  \sa itemMode(), QwtLegendData::value(), QwtPlotItem::legendData()
     327  \note Changing the mode doesn't have any effect on existing labels.
     328 */
     329void QwtLegend::setDefaultItemMode( QwtLegendData::Mode mode )
    251330{
    252331    d_data->itemMode = mode;
    253332}
    254333
    255 //! \sa LegendItemMode
    256 QwtLegend::LegendItemMode QwtLegend::itemMode() const
     334/*!
     335  \return Default item mode
     336  \sa setDefaultItemMode()
     337*/
     338QwtLegendData::Mode QwtLegend::defaultItemMode() const
    257339{
    258340    return d_data->itemMode;
     
    261343/*!
    262344  The contents widget is the only child of the viewport of
    263   the internal QScrollArea  and the parent widget of all legend items.
     345  the internal QScrollArea and the parent widget of all legend items.
    264346
    265347  \return Container widget of the legend items
     
    290372/*!
    291373  The contents widget is the only child of the viewport of
    292   the internal QScrollArea  and the parent widget of all legend items.
     374  the internal QScrollArea and the parent widget of all legend items.
    293375
    294376  \return Container widget of the legend items
     
    301383
    302384/*!
    303   Insert a new item for a plot item
    304   \param plotItem Plot item
    305   \param legendItem New legend item
    306   \note The parent of item will be changed to contentsWidget()
    307 */
    308 void QwtLegend::insert( const QwtLegendItemManager *plotItem, QWidget *legendItem )
    309 {
    310     if ( legendItem == NULL || plotItem == NULL )
    311         return;
    312 
    313     QWidget *contentsWidget = d_data->view->contentsWidget;
    314 
    315     if ( legendItem->parent() != contentsWidget )
    316         legendItem->setParent( contentsWidget );
    317 
    318     legendItem->show();
    319 
    320     d_data->map.insert( plotItem, legendItem );
    321 
    322     layoutContents();
    323 
    324     if ( contentsWidget->layout() )
    325     {
    326         contentsWidget->layout()->addWidget( legendItem );
    327 
     385  \brief Update the entries for an item
     386
     387  \param itemInfo Info for an item
     388  \param data List of legend entry attributes for the item
     389 */
     390void QwtLegend::updateLegend( const QVariant &itemInfo,
     391    const QList<QwtLegendData> &data )
     392{
     393    QList<QWidget *> widgetList = legendWidgets( itemInfo );
     394
     395    if ( widgetList.size() != data.size() )
     396    {
     397        QLayout *contentsLayout = d_data->view->contentsWidget->layout();
     398
     399        while ( widgetList.size() > data.size() )
     400        {
     401            QWidget *w = widgetList.takeLast();
     402
     403            contentsLayout->removeWidget( w );
     404
     405            // updates might be triggered by signals from the legend widget
     406            // itself. So we better don't delete it here.
     407
     408            w->hide();
     409            w->deleteLater();
     410        }
     411
     412        for ( int i = widgetList.size(); i < data.size(); i++ )
     413        {
     414            QWidget *widget = createWidget( data[i] );
     415
     416            if ( contentsLayout )
     417                contentsLayout->addWidget( widget );
     418
     419            if ( isVisible() )
     420            {
     421                // QLayout does a delayed show, with the effect, that
     422                // the size hint will be wrong, when applications
     423                // call replot() right after changing the list
     424                // of plot items. So we better do the show now.
     425
     426                widget->setVisible( true );
     427            }
     428
     429            widgetList += widget;
     430        }
     431
     432        if ( widgetList.isEmpty() )
     433        {
     434            d_data->itemMap.remove( itemInfo );
     435        }
     436        else
     437        {
     438            d_data->itemMap.insert( itemInfo, widgetList );
     439        }
     440
     441        updateTabOrder();
     442    }
     443   
     444    for ( int i = 0; i < data.size(); i++ )
     445        updateWidget( widgetList[i], data[i] );
     446}
     447
     448/*!
     449  \brief Create a widget to be inserted into the legend
     450
     451  The default implementation returns a QwtLegendLabel.
     452
     453  \param data Attributes of the legend entry
     454  \return Widget representing data on the legend
     455 
     456  \note updateWidget() will called soon after createWidget()
     457        with the same attributes.
     458 */
     459QWidget *QwtLegend::createWidget( const QwtLegendData &data ) const
     460{
     461    Q_UNUSED( data );
     462
     463    QwtLegendLabel *label = new QwtLegendLabel();
     464    label->setItemMode( defaultItemMode() );
     465
     466    connect( label, SIGNAL( clicked() ), SLOT( itemClicked() ) );
     467    connect( label, SIGNAL( checked( bool ) ), SLOT( itemChecked( bool ) ) );
     468
     469    return label;
     470}
     471
     472/*!
     473  \brief Update the widget
     474
     475  \param widget Usually a QwtLegendLabel
     476  \param data Attributes to be displayed
     477
     478  \sa createWidget()
     479  \note When widget is no QwtLegendLabel updateWidget() does nothing.
     480 */
     481void QwtLegend::updateWidget( QWidget *widget, const QwtLegendData &data )
     482{
     483    QwtLegendLabel *label = qobject_cast<QwtLegendLabel *>( widget );
     484    if ( label )
     485    {
     486        label->setData( data );
     487        if ( !data.value( QwtLegendData::ModeRole ).isValid() )
     488        {
     489            // use the default mode, when there is no specific
     490            // hint from the legend data
     491
     492            label->setItemMode( defaultItemMode() );
     493        }
     494    }
     495}
     496
     497void QwtLegend::updateTabOrder()
     498{
     499    QLayout *contentsLayout = d_data->view->contentsWidget->layout();
     500    if ( contentsLayout )
     501    {
    328502        // set tab focus chain
    329503
    330504        QWidget *w = NULL;
    331505
    332         for ( int i = 0; i < contentsWidget->layout()->count(); i++ )
    333         {
    334             QLayoutItem *item = contentsWidget->layout()->itemAt( i );
     506        for ( int i = 0; i < contentsLayout->count(); i++ )
     507        {
     508            QLayoutItem *item = contentsLayout->itemAt( i );
    335509            if ( w && item->widget() )
    336510                QWidget::setTabOrder( w, item->widget() );
     
    339513        }
    340514    }
    341     if ( parentWidget() && parentWidget()->layout() == NULL )
    342     {
    343         /*
    344            updateGeometry() doesn't post LayoutRequest in certain
    345            situations, like when we are hidden. But we want the
    346            parent widget notified, so it can show/hide the legend
    347            depending on its items.
    348          */
    349         QApplication::postEvent( parentWidget(),
    350             new QEvent( QEvent::LayoutRequest ) );
    351     }
    352 }
    353 
    354 /*!
    355   Find the widget that represents a plot item
    356 
    357   \param plotItem Plot item
    358   \return Widget on the legend, or NULL
    359 */
    360 QWidget *QwtLegend::find( const QwtLegendItemManager *plotItem ) const
    361 {
    362     return d_data->map.find( plotItem );
    363 }
    364 
    365 /*!
    366   Find the widget that represents a plot item
    367 
    368   \param legendItem Legend item
    369   \return Widget on the legend, or NULL
    370 */
    371 QwtLegendItemManager *QwtLegend::find( const QWidget *legendItem ) const
    372 {
    373     return d_data->map.find( legendItem );
    374 }
    375 
    376 /*!
    377    Find the corresponding item for a plotItem and remove it
    378    from the item list.
    379 
    380    \param plotItem Plot item
    381 */
    382 void QwtLegend::remove( const QwtLegendItemManager *plotItem )
    383 {
    384     QWidget *legendItem = d_data->map.find( plotItem );
    385     d_data->map.remove( legendItem );
    386     delete legendItem;
    387 }
    388 
    389 //! Remove all items.
    390 void QwtLegend::clear()
    391 {
    392     bool doUpdate = updatesEnabled();
    393     if ( doUpdate )
    394         setUpdatesEnabled( false );
    395 
    396     d_data->map.clear();
    397 
    398     if ( doUpdate )
    399         setUpdatesEnabled( true );
    400 
    401     update();
    402515}
    403516
     
    412525
    413526/*!
    414   \return The preferred height, for the width w.
     527  \return The preferred height, for a width.
    415528  \param width Width
    416529*/
     
    426539}
    427540
    428 /*!
    429   Adjust contents widget and item layout to the size of the viewport().
    430 */
    431 void QwtLegend::layoutContents()
    432 {
    433     const QSize visibleSize =
    434         d_data->view->viewport()->contentsRect().size();
    435 
    436     const QwtDynGridLayout *tl = qobject_cast<QwtDynGridLayout *>(
    437         d_data->view->contentsWidget->layout() );
    438     if ( tl )
    439     {
    440         const int minW = int( tl->maxItemWidth() ) + 2 * tl->margin();
    441 
    442         int w = qMax( visibleSize.width(), minW );
    443         int h = qMax( tl->heightForWidth( w ), visibleSize.height() );
    444 
    445         const int vpWidth = d_data->view->viewportSize( w, h ).width();
    446         if ( w > vpWidth )
    447         {
    448             w = qMax( vpWidth, minW );
    449             h = qMax( tl->heightForWidth( w ), visibleSize.height() );
    450         }
    451 
    452         d_data->view->contentsWidget->resize( w, h );
    453     }
    454 }
    455541
    456542/*!
     
    460546  \param object Object to be filtered
    461547  \param event Event
     548
     549  \return Forwarded to QwtAbstractLegend::eventFilter()
    462550*/
    463551bool QwtLegend::eventFilter( QObject *object, QEvent *event )
     
    474562                {
    475563                    QWidget *w = static_cast< QWidget * >( ce->child() );
    476                     d_data->map.remove( w );
     564                    d_data->itemMap.removeWidget( w );
    477565                }
    478566                break;
     
    480568            case QEvent::LayoutRequest:
    481569            {
    482                 layoutContents();
     570                d_data->view->layoutContents();
     571
     572                if ( parentWidget() && parentWidget()->layout() == NULL )
     573                {
     574                    /*
     575                       We want the parent widget ( usually QwtPlot ) to recalculate
     576                       its layout, when the contentsWidget has changed. But
     577                       because of the scroll view we have to forward the LayoutRequest
     578                       event manually.
     579
     580                       We don't use updateGeometry() because it doesn't post LayoutRequest
     581                       events when the legend is hidden. But we want the
     582                       parent widget notified, so it can show/hide the legend
     583                       depending on its items.
     584                     */
     585                    QApplication::postEvent( parentWidget(),
     586                        new QEvent( QEvent::LayoutRequest ) );
     587                }               
    483588                break;
    484589            }
     
    488593    }
    489594
    490     return QFrame::eventFilter( object, event );
    491 }
    492 
    493 
    494 //! Return true, if there are no legend items.
     595    return QwtAbstractLegend::eventFilter( object, event );
     596}
     597
     598/*!
     599  Called internally when the legend has been clicked on.
     600  Emits a clicked() signal.
     601*/
     602void QwtLegend::itemClicked()
     603{
     604    QWidget *w = qobject_cast<QWidget *>( sender() );
     605    if ( w )
     606    {
     607        const QVariant itemInfo = d_data->itemMap.itemInfo( w );
     608        if ( itemInfo.isValid() )
     609        {
     610            const QList<QWidget *> widgetList =
     611                d_data->itemMap.legendWidgets( itemInfo );
     612
     613            const int index = widgetList.indexOf( w );
     614            if ( index >= 0 )
     615                Q_EMIT clicked( itemInfo, index );
     616        }
     617    }
     618}
     619
     620/*!
     621  Called internally when the legend has been checked
     622  Emits a checked() signal.
     623*/
     624void QwtLegend::itemChecked( bool on )
     625{
     626    QWidget *w = qobject_cast<QWidget *>( sender() );
     627    if ( w )
     628    {
     629        const QVariant itemInfo = d_data->itemMap.itemInfo( w );
     630        if ( itemInfo.isValid() )
     631        {
     632            const QList<QWidget *> widgetList =
     633                d_data->itemMap.legendWidgets( itemInfo );
     634
     635            const int index = widgetList.indexOf( w );
     636            if ( index >= 0 )
     637                Q_EMIT checked( itemInfo, on, index );
     638        }
     639    }
     640}
     641
     642/*!
     643  Render the legend into a given rectangle.
     644
     645  \param painter Painter
     646  \param rect Bounding rectangle
     647  \param fillBackground When true, fill rect with the widget background
     648
     649  \sa renderLegend() is used by QwtPlotRenderer - not by QwtLegend itself
     650*/
     651void QwtLegend::renderLegend( QPainter *painter,
     652    const QRectF &rect, bool fillBackground ) const
     653{
     654    if ( d_data->itemMap.isEmpty() )
     655        return;
     656
     657    if ( fillBackground )
     658    {
     659        if ( autoFillBackground() ||
     660            testAttribute( Qt::WA_StyledBackground ) )
     661        {
     662            QwtPainter::drawBackgound( painter, rect, this );
     663        }
     664    }
     665
     666    const QwtDynGridLayout *legendLayout =
     667        qobject_cast<QwtDynGridLayout *>( contentsWidget()->layout() );
     668    if ( legendLayout == NULL )
     669        return;
     670
     671    int left, right, top, bottom;
     672    getContentsMargins( &left, &top, &right, &bottom );
     673
     674    QRect layoutRect;
     675    layoutRect.setLeft( qCeil( rect.left() ) + left );
     676    layoutRect.setTop( qCeil( rect.top() ) + top );
     677    layoutRect.setRight( qFloor( rect.right() ) - right );
     678    layoutRect.setBottom( qFloor( rect.bottom() ) - bottom );
     679
     680    uint numCols = legendLayout->columnsForWidth( layoutRect.width() );
     681    QList<QRect> itemRects =
     682        legendLayout->layoutItems( layoutRect, numCols );
     683
     684    int index = 0;
     685
     686    for ( int i = 0; i < legendLayout->count(); i++ )
     687    {
     688        QLayoutItem *item = legendLayout->itemAt( i );
     689        QWidget *w = item->widget();
     690        if ( w )
     691        {
     692            painter->save();
     693
     694            painter->setClipRect( itemRects[index], Qt::IntersectClip );
     695            renderItem( painter, w, itemRects[index], fillBackground );
     696
     697            index++;
     698            painter->restore();
     699        }
     700    }
     701}
     702
     703/*!
     704  Render a legend entry into a given rectangle.
     705
     706  \param painter Painter
     707  \param widget Widget representing a legend entry
     708  \param rect Bounding rectangle
     709  \param fillBackground When true, fill rect with the widget background
     710
     711  \note When widget is not derived from QwtLegendLabel renderItem
     712        does nothing beside the background
     713*/
     714void QwtLegend::renderItem( QPainter *painter,
     715    const QWidget *widget, const QRectF &rect, bool fillBackground ) const
     716{
     717    if ( fillBackground )
     718    {
     719        if ( widget->autoFillBackground() ||
     720            widget->testAttribute( Qt::WA_StyledBackground ) )
     721        {
     722            QwtPainter::drawBackgound( painter, rect, widget );
     723        }
     724    }
     725
     726    const QwtLegendLabel *label = qobject_cast<const QwtLegendLabel *>( widget );
     727    if ( label )
     728    {
     729        // icon
     730
     731        const QwtGraphic &icon = label->data().icon();
     732        const QSizeF sz = icon.defaultSize();
     733
     734        const QRectF iconRect( rect.x() + label->margin(),
     735            rect.center().y() - 0.5 * sz.height(),
     736            sz.width(), sz.height() );
     737
     738        icon.render( painter, iconRect, Qt::KeepAspectRatio );
     739
     740        // title
     741
     742        QRectF titleRect = rect;
     743        titleRect.setX( iconRect.right() + 2 * label->spacing() );
     744
     745        painter->setFont( label->font() );
     746        painter->setPen( label->palette().color( QPalette::Text ) );
     747        const_cast< QwtLegendLabel *>( label )->drawText( painter, titleRect );
     748    }
     749}
     750
     751/*!
     752  \return List of widgets associated to a item
     753  \param itemInfo Info about an item
     754  \sa legendWidget(), itemInfo(), QwtPlot::itemToInfo()
     755 */
     756QList<QWidget *> QwtLegend::legendWidgets( const QVariant &itemInfo ) const
     757{
     758    return d_data->itemMap.legendWidgets( itemInfo );
     759}
     760
     761/*!
     762  \return First widget in the list of widgets associated to an item
     763  \param itemInfo Info about an item
     764  \sa itemInfo(), QwtPlot::itemToInfo()
     765  \note Almost all types of items have only one widget
     766*/
     767QWidget *QwtLegend::legendWidget( const QVariant &itemInfo ) const
     768{
     769    const QList<QWidget *> list = d_data->itemMap.legendWidgets( itemInfo );
     770    if ( list.isEmpty() )
     771        return NULL;
     772
     773    return list[0];
     774}
     775
     776/*!
     777  Find the item that is associated to a widget
     778
     779  \param widget Widget on the legend
     780  \return Associated item info
     781  \sa legendWidget()
     782 */
     783QVariant QwtLegend::itemInfo( const QWidget *widget ) const
     784{
     785    return d_data->itemMap.itemInfo( widget );
     786}
     787
     788//! \return True, when no item is inserted
    495789bool QwtLegend::isEmpty() const
    496790{
    497     return d_data->map.count() == 0;
    498 }
    499 
    500 //! Return the number of legend items.
    501 uint QwtLegend::itemCount() const
    502 {
    503     return d_data->map.count();
    504 }
    505 
    506 //! Return a list of all legend items
    507 QList<QWidget *> QwtLegend::legendItems() const
    508 {
    509     const QMap<QWidget *, const QwtLegendItemManager *> &map =
    510         d_data->map.widgetMap();
    511 
    512     QList<QWidget *> list;
    513 
    514     QMap<QWidget *, const QwtLegendItemManager *>::const_iterator it;
    515     for ( it = map.begin(); it != map.end(); ++it )
    516         list += it.key();
    517 
    518     return list;
    519 }
     791    return d_data->itemMap.isEmpty();
     792}
     793
     794/*!
     795    Return the extent, that is needed for the scrollbars
     796
     797    \param orientation Orientation (
     798    \return The width of the vertical scrollbar for Qt::Horizontal and v.v.
     799 */
     800int QwtLegend::scrollExtent( Qt::Orientation orientation ) const
     801{
     802    int extent = 0;
     803
     804    if ( orientation == Qt::Horizontal )
     805        extent = verticalScrollBar()->sizeHint().width();
     806    else
     807        extent = horizontalScrollBar()->sizeHint().height();
     808
     809    return extent;
     810}
     811
Note: See TracChangeset for help on using the changeset viewer.