1
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
3
* Copyright (C) 1997 Josef Wilgen
4
* Copyright (C) 2002 Uwe Rathmann
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the Qwt License, Version 1.0
8
*****************************************************************************/
12
#include <qapplication.h>
14
#if QT_VERSION >= 0x040000
15
#include <qscrollbar.h>
18
#include "qwt_dyngrid_layout.h"
19
#include "qwt_plot_item.h"
20
#include "qwt_legend_item.h"
21
#include "qwt_legend.h"
23
class QwtLegend::PrivateData
29
void insert(const QwtPlotItem *, QWidget *);
31
void remove(const QwtPlotItem *);
32
void remove(QWidget *);
38
inline const QWidget *find(const QwtPlotItem *) const;
39
inline QWidget *find(const QwtPlotItem *);
41
inline const QwtPlotItem *find(const QWidget *) const;
42
inline QwtPlotItem *find(const QWidget *);
44
const QMap<QWidget *, const QwtPlotItem *> &widgetMap() const;
45
QMap<QWidget *, const QwtPlotItem *> &widgetMap();
48
QMap<QWidget *, const QwtPlotItem *> d_widgetMap;
49
QMap<const QwtPlotItem *, QWidget *> d_itemMap;
52
QwtLegend::LegendItemMode itemMode;
53
QwtLegend::LegendDisplayPolicy displayPolicy;
62
#if QT_VERSION < 0x040000
63
#include <qscrollview.h>
65
class QwtLegend::PrivateData::LegendView: public QScrollView
68
LegendView(QWidget *parent):
71
setResizePolicy(Manual);
73
viewport()->setBackgroundMode(Qt::NoBackground); // Avoid flicker
75
contentsWidget = new QWidget(viewport());
77
addChild(contentsWidget);
80
void viewportResizeEvent(QResizeEvent *e)
82
QScrollView::viewportResizeEvent(e);
84
// It's not safe to update the layout now, because
85
// we are in an internal update of the scrollview framework.
86
// So we delay the update by posting a LayoutHint.
88
QApplication::postEvent(contentsWidget,
89
new QEvent(QEvent::LayoutHint));
92
QWidget *contentsWidget;
95
#else // QT_VERSION >= 0x040000
97
#include <qscrollarea.h>
99
class QwtLegend::PrivateData::LegendView: public QScrollArea
102
LegendView(QWidget *parent):
105
contentsWidget = new QWidget(this);
107
setWidget(contentsWidget);
108
setWidgetResizable(false);
109
setFocusPolicy(Qt::NoFocus);
112
virtual bool viewportEvent(QEvent *e)
114
bool ok = QScrollArea::viewportEvent(e);
116
if ( e->type() == QEvent::Resize )
118
QEvent event(QEvent::LayoutRequest);
119
QApplication::sendEvent(contentsWidget, &event);
124
QSize viewportSize(int w, int h) const
126
const int sbHeight = horizontalScrollBar()->sizeHint().height();
127
const int sbWidth = verticalScrollBar()->sizeHint().width();
129
const int cw = contentsRect().width();
130
const int ch = contentsRect().height();
141
if ( w > vw && vh == ch )
144
return QSize(vw, vh);
147
QWidget *contentsWidget;
153
void QwtLegend::PrivateData::LegendMap::insert(
154
const QwtPlotItem *item, QWidget *widget)
156
d_itemMap.insert(item, widget);
157
d_widgetMap.insert(widget, item);
160
void QwtLegend::PrivateData::LegendMap::remove(const QwtPlotItem *item)
162
QWidget *widget = d_itemMap[item];
163
d_itemMap.remove(item);
164
d_widgetMap.remove(widget);
167
void QwtLegend::PrivateData::LegendMap::remove(QWidget *widget)
169
const QwtPlotItem *item = d_widgetMap[widget];
170
d_itemMap.remove(item);
171
d_widgetMap.remove(widget);
174
void QwtLegend::PrivateData::LegendMap::clear()
178
We can't delete the widgets in the following loop, because
179
we would get ChildRemoved events, changing d_itemMap, while
183
#if QT_VERSION < 0x040000
184
QValueList<QWidget *> widgets;
186
QMap<const QwtPlotItem *, QWidget *>::const_iterator it;
187
for ( it = d_itemMap.begin(); it != d_itemMap.end(); ++it )
188
widgets.append(it.data());
190
QList<QWidget *> widgets;
192
QMap<const QwtPlotItem *, QWidget *>::const_iterator it;
193
for ( it = d_itemMap.begin(); it != d_itemMap.end(); ++it )
194
widgets.append(it.value());
200
for ( int i = 0; i < (int)widgets.size(); i++ )
204
uint QwtLegend::PrivateData::LegendMap::count() const
206
return d_itemMap.count();
209
inline const QWidget *QwtLegend::PrivateData::LegendMap::find(const QwtPlotItem *item) const
211
if ( !d_itemMap.contains((QwtPlotItem *)item) )
214
return d_itemMap[(QwtPlotItem *)item];
217
inline QWidget *QwtLegend::PrivateData::LegendMap::find(const QwtPlotItem *item)
219
if ( !d_itemMap.contains((QwtPlotItem *)item) )
222
return d_itemMap[(QwtPlotItem *)item];
225
inline const QwtPlotItem *QwtLegend::PrivateData::LegendMap::find(
226
const QWidget *widget) const
228
if ( !d_widgetMap.contains((QWidget *)widget) )
231
return d_widgetMap[(QWidget *)widget];
234
inline QwtPlotItem *QwtLegend::PrivateData::LegendMap::find(
235
const QWidget *widget)
237
if ( !d_widgetMap.contains((QWidget *)widget) )
240
return (QwtPlotItem *)d_widgetMap[(QWidget *)widget];
243
inline const QMap<QWidget *, const QwtPlotItem *> &
244
QwtLegend::PrivateData::LegendMap::widgetMap() const
249
inline QMap<QWidget *, const QwtPlotItem *> &
250
QwtLegend::PrivateData::LegendMap::widgetMap()
256
\param parent Parent widget
258
QwtLegend::QwtLegend(QWidget *parent):
261
setFrameStyle(NoFrame);
263
d_data = new QwtLegend::PrivateData;
264
d_data->itemMode = QwtLegend::ReadOnlyItem;
265
d_data->displayPolicy = QwtLegend::AutoIdentifier;
266
d_data->identifierMode = QwtLegendItem::ShowLine |
267
QwtLegendItem::ShowSymbol | QwtLegendItem::ShowText;
269
d_data->view = new QwtLegend::PrivateData::LegendView(this);
270
d_data->view->setFrameStyle(NoFrame);
272
QwtDynGridLayout *layout = new QwtDynGridLayout(
273
d_data->view->contentsWidget);
274
#if QT_VERSION < 0x040000
275
layout->setAutoAdd(true);
277
layout->setAlignment(Qt::AlignHCenter | Qt::AlignTop);
279
d_data->view->contentsWidget->installEventFilter(this);
283
QwtLegend::~QwtLegend()
289
Set the legend display policy to:
291
\param policy Legend display policy
292
\param mode Identifier mode (or'd ShowLine, ShowSymbol, ShowText)
294
\sa displayPolicy, LegendDisplayPolicy
296
void QwtLegend::setDisplayPolicy(LegendDisplayPolicy policy, int mode)
298
d_data->displayPolicy = policy;
300
d_data->identifierMode = mode;
302
QMap<QWidget *, const QwtPlotItem *> &map =
303
d_data->map.widgetMap();
305
QMap<QWidget *, const QwtPlotItem *>::iterator it;
306
for ( it = map.begin(); it != map.end(); ++it )
308
#if QT_VERSION < 0x040000
309
QwtPlotItem *item = (QwtPlotItem *)it.data();
311
QwtPlotItem *item = (QwtPlotItem *)it.value();
314
item->updateLegend(this);
319
\return the legend display policy.
320
Default is LegendDisplayPolicy::Auto.
321
\sa setDisplayPolicy, LegendDisplayPolicy
324
QwtLegend::LegendDisplayPolicy QwtLegend::displayPolicy() const
326
return d_data->displayPolicy;
329
void QwtLegend::setItemMode(LegendItemMode mode)
331
d_data->itemMode = mode;
334
QwtLegend::LegendItemMode QwtLegend::itemMode() const
336
return d_data->itemMode;
340
\return the IdentifierMode to be used in combination with
341
LegendDisplayPolicy::Fixed.
343
Default is ShowLine | ShowSymbol | ShowText.
346
int QwtLegend::identifierMode() const
348
return d_data->identifierMode;
352
The contents widget is the only child of the viewport() and
353
the parent widget of all legend items.
355
QWidget *QwtLegend::contentsWidget()
357
return d_data->view->contentsWidget;
360
QScrollBar *QwtLegend::horizontalScrollBar() const
362
return d_data->view->horizontalScrollBar();
365
QScrollBar *QwtLegend::verticalScrollBar() const
367
return d_data->view->horizontalScrollBar();
371
The contents widget is the only child of the viewport() and
372
the parent widget of all legend items.
375
const QWidget *QwtLegend::contentsWidget() const
377
return d_data->view->contentsWidget;
381
Insert a new item for a plot item
382
\param plotItem Plot item
383
\param legendItem New legend item
384
\note The parent of item will be changed to QwtLegend::contentsWidget()
386
void QwtLegend::insert(const QwtPlotItem *plotItem, QWidget *legendItem)
388
if ( legendItem == NULL || plotItem == NULL )
391
QWidget *contentsWidget = d_data->view->contentsWidget;
393
if ( legendItem->parent() != contentsWidget )
395
#if QT_VERSION >= 0x040000
396
legendItem->setParent(contentsWidget);
398
legendItem->reparent(contentsWidget, QPoint(0, 0));
404
d_data->map.insert(plotItem, legendItem);
408
if ( contentsWidget->layout() )
410
#if QT_VERSION >= 0x040000
411
contentsWidget->layout()->addWidget(legendItem);
414
// set tab focus chain
418
#if QT_VERSION < 0x040000
419
QLayoutIterator layoutIterator =
420
contentsWidget->layout()->iterator();
421
for ( QLayoutItem *item = layoutIterator.current();
422
item != 0; item = ++layoutIterator)
425
for (int i = 0; i < contentsWidget->layout()->count(); i++)
427
QLayoutItem *item = contentsWidget->layout()->itemAt(i);
429
if ( w && item->widget() )
431
QWidget::setTabOrder(w, item->widget());
436
if ( parentWidget() && parentWidget()->layout() == NULL )
439
updateGeometry() doesn't post LayoutRequest in certain
440
situations, like when we are hidden. But we want the
441
parent widget notified, so it can show/hide the legend
442
depending on its items.
444
#if QT_VERSION < 0x040000
445
QApplication::postEvent(parentWidget(),
446
new QEvent(QEvent::LayoutHint));
448
QApplication::postEvent(parentWidget(),
449
new QEvent(QEvent::LayoutRequest));
455
Find the widget that represents a plot item
457
\param plotItem Plot item
458
\return Widget on the legend, or NULL
460
QWidget *QwtLegend::find(const QwtPlotItem *plotItem) const
462
return d_data->map.find(plotItem);
466
Find the widget that represents a plot item
468
\param plotItem Plot item
469
\return Widget on the legend, or NULL
471
QwtPlotItem *QwtLegend::find(const QWidget *legendItem) const
473
return d_data->map.find(legendItem);
477
Find the corresponding item for a plotItem and remove it
480
\param plotItem Plot item
482
void QwtLegend::remove(const QwtPlotItem *plotItem)
484
QWidget *legendItem = d_data->map.find(plotItem);
485
d_data->map.remove(legendItem);
489
//! Remove all items.
490
void QwtLegend::clear()
492
#if QT_VERSION < 0x040000
493
bool doUpdate = isUpdatesEnabled();
495
bool doUpdate = updatesEnabled();
497
setUpdatesEnabled(false);
501
setUpdatesEnabled(doUpdate);
505
//! Return a size hint.
506
QSize QwtLegend::sizeHint() const
508
QSize hint = d_data->view->contentsWidget->sizeHint();
509
hint += QSize(2 * frameWidth(), 2 * frameWidth());
515
\return The preferred height, for the width w.
518
int QwtLegend::heightForWidth(int width) const
520
width -= 2 * frameWidth();
522
int h = d_data->view->contentsWidget->heightForWidth(width);
523
#if QT_VERSION < 0x040000
525
// Asking the layout is the default implementation in Qt4
529
QLayout *l = d_data->view->contentsWidget->layout();
530
if ( l && l->hasHeightForWidth() )
531
h = l->heightForWidth(width);
535
h += 2 * frameWidth();
541
Adjust contents widget and item layout to the size of the viewport().
543
void QwtLegend::layoutContents()
545
const QSize visibleSize = d_data->view->viewport()->size();
547
const QLayout *l = d_data->view->contentsWidget->layout();
548
if ( l && l->inherits("QwtDynGridLayout") )
550
const QwtDynGridLayout *tl = (const QwtDynGridLayout *)l;
552
const int minW = int(tl->maxItemWidth()) + 2 * tl->margin();
554
int w = qwtMax(visibleSize.width(), minW);
555
int h = qwtMax(tl->heightForWidth(w), visibleSize.height());
557
const int vpWidth = d_data->view->viewportSize(w, h).width();
560
w = qwtMax(vpWidth, minW);
561
h = qwtMax(tl->heightForWidth(w), visibleSize.height());
564
d_data->view->contentsWidget->resize(w, h);
565
#if QT_VERSION < 0x040000
566
d_data->view->resizeContents(w, h);
572
Filter layout related events of QwtLegend::contentsWidget().
574
\param o Object to be filtered
578
bool QwtLegend::eventFilter(QObject *o, QEvent *e)
580
if ( o == d_data->view->contentsWidget )
584
case QEvent::ChildRemoved:
586
const QChildEvent *ce = (const QChildEvent *)e;
587
if ( ce->child()->isWidgetType() )
588
d_data->map.remove((QWidget *)ce->child());
591
#if QT_VERSION < 0x040000
592
case QEvent::LayoutHint:
594
case QEvent::LayoutRequest:
600
#if QT_VERSION < 0x040000
612
return QFrame::eventFilter(o, e);
616
//! Return true, if there are no legend items.
617
bool QwtLegend::isEmpty() const
619
return d_data->map.count() == 0;
622
//! Return the number of legend items.
623
uint QwtLegend::itemCount() const
625
return d_data->map.count();
628
#if QT_VERSION < 0x040000
629
QValueList<QWidget *> QwtLegend::legendItems() const
631
QList<QWidget *> QwtLegend::legendItems() const
634
const QMap<QWidget *, const QwtPlotItem *> &map =
635
d_data->map.widgetMap();
637
#if QT_VERSION < 0x040000
638
QValueList<QWidget *> list;
640
QList<QWidget *> list;
643
QMap<QWidget *, const QwtPlotItem *>::const_iterator it;
644
for ( it = map.begin(); it != map.end(); ++it )
654
void QwtLegend::resizeEvent(QResizeEvent *e)
656
QFrame::resizeEvent(e);
657
d_data->view->setGeometry(contentsRect());