00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <qapplication.h>
00013 #include <qmap.h>
00014 #if QT_VERSION >= 0x040000
00015 #include <qscrollbar.h>
00016 #endif
00017 #include "qwt_math.h"
00018 #include "qwt_dyngrid_layout.h"
00019 #include "qwt_plot_item.h"
00020 #include "qwt_legend_item.h"
00021 #include "qwt_legend.h"
00022
00023 class QwtLegend::PrivateData
00024 {
00025 public:
00026 class LegendMap
00027 {
00028 public:
00029 void insert(const QwtPlotItem *, QWidget *);
00030
00031 void remove(const QwtPlotItem *);
00032 void remove(QWidget *);
00033
00034 void clear();
00035
00036 uint count() const;
00037
00038 inline const QWidget *find(const QwtPlotItem *) const;
00039 inline QWidget *find(const QwtPlotItem *);
00040
00041 inline const QwtPlotItem *find(const QWidget *) const;
00042 inline QwtPlotItem *find(const QWidget *);
00043
00044 const QMap<QWidget *, const QwtPlotItem *> &widgetMap() const;
00045 QMap<QWidget *, const QwtPlotItem *> &widgetMap();
00046
00047 private:
00048 QMap<QWidget *, const QwtPlotItem *> d_widgetMap;
00049 QMap<const QwtPlotItem *, QWidget *> d_itemMap;
00050 };
00051
00052 QwtLegend::LegendItemMode itemMode;
00053 QwtLegend::LegendDisplayPolicy displayPolicy;
00054 int identifierMode;
00055
00056 LegendMap map;
00057
00058 class LegendView;
00059 LegendView *view;
00060 };
00061
00062 #if QT_VERSION < 0x040000
00063 #include <qscrollview.h>
00064
00065 class QwtLegend::PrivateData::LegendView: public QScrollView
00066 {
00067 public:
00068 LegendView(QWidget *parent):
00069 QScrollView(parent)
00070 {
00071 setResizePolicy(Manual);
00072
00073 viewport()->setBackgroundMode(Qt::NoBackground);
00074
00075 contentsWidget = new QWidget(viewport());
00076
00077 addChild(contentsWidget);
00078 }
00079
00080 void viewportResizeEvent(QResizeEvent *e)
00081 {
00082 QScrollView::viewportResizeEvent(e);
00083
00084
00085
00086
00087
00088 QApplication::postEvent(contentsWidget,
00089 new QEvent(QEvent::LayoutHint));
00090 }
00091
00092 QWidget *contentsWidget;
00093 };
00094
00095 #else // QT_VERSION >= 0x040000
00096
00097 #include <qscrollarea.h>
00098
00099 class QwtLegend::PrivateData::LegendView: public QScrollArea
00100 {
00101 public:
00102 LegendView(QWidget *parent):
00103 QScrollArea(parent)
00104 {
00105 contentsWidget = new QWidget(this);
00106
00107 setWidget(contentsWidget);
00108 setWidgetResizable(false);
00109 }
00110
00111 virtual bool viewportEvent(QEvent *e)
00112 {
00113 bool ok = QScrollArea::viewportEvent(e);
00114
00115 if ( e->type() == QEvent::Resize )
00116 {
00117 QApplication::postEvent(contentsWidget,
00118 new QEvent(QEvent::LayoutRequest));
00119 }
00120 return ok;
00121 }
00122
00123 QSize viewportSize(int w, int h) const
00124 {
00125 const int sbHeight = horizontalScrollBar()->sizeHint().height();
00126 const int sbWidth = verticalScrollBar()->sizeHint().width();
00127
00128 const int cw = contentsRect().width();
00129 const int ch = contentsRect().height();
00130
00131 int vw = cw;
00132 int vh = ch;
00133
00134 if ( w > vw )
00135 vh -= sbHeight;
00136
00137 if ( h > vh )
00138 {
00139 vw -= sbWidth;
00140 if ( w > vw && vh == ch )
00141 vh -= sbHeight;
00142 }
00143 return QSize(vw, vh);
00144 }
00145
00146 QWidget *contentsWidget;
00147 };
00148
00149 #endif
00150
00151
00152 void QwtLegend::PrivateData::LegendMap::insert(
00153 const QwtPlotItem *item, QWidget *widget)
00154 {
00155 d_itemMap.insert(item, widget);
00156 d_widgetMap.insert(widget, item);
00157 }
00158
00159 void QwtLegend::PrivateData::LegendMap::remove(const QwtPlotItem *item)
00160 {
00161 QWidget *widget = d_itemMap[item];
00162 d_itemMap.remove(item);
00163 d_widgetMap.remove(widget);
00164 }
00165
00166 void QwtLegend::PrivateData::LegendMap::remove(QWidget *widget)
00167 {
00168 const QwtPlotItem *item = d_widgetMap[widget];
00169 d_itemMap.remove(item);
00170 d_widgetMap.remove(widget);
00171 }
00172
00173 void QwtLegend::PrivateData::LegendMap::clear()
00174 {
00175 QMap<QWidget *, const QwtPlotItem *>::const_iterator it;
00176 for ( it = d_widgetMap.begin(); it != d_widgetMap.end(); ++it )
00177 delete it.key();
00178
00179 d_itemMap.clear();
00180 d_widgetMap.clear();
00181 }
00182
00183 uint QwtLegend::PrivateData::LegendMap::count() const
00184 {
00185 return d_itemMap.count();
00186 }
00187
00188 inline const QWidget *QwtLegend::PrivateData::LegendMap::find(const QwtPlotItem *item) const
00189 {
00190 if ( !d_itemMap.contains((QwtPlotItem *)item) )
00191 return NULL;
00192
00193 return d_itemMap[(QwtPlotItem *)item];
00194 }
00195
00196 inline QWidget *QwtLegend::PrivateData::LegendMap::find(const QwtPlotItem *item)
00197 {
00198 if ( !d_itemMap.contains((QwtPlotItem *)item) )
00199 return NULL;
00200
00201 return d_itemMap[(QwtPlotItem *)item];
00202 }
00203
00204 inline const QwtPlotItem *QwtLegend::PrivateData::LegendMap::find(
00205 const QWidget *widget) const
00206 {
00207 if ( !d_widgetMap.contains((QWidget *)widget) )
00208 return NULL;
00209
00210 return d_widgetMap[(QWidget *)widget];
00211 }
00212
00213 inline QwtPlotItem *QwtLegend::PrivateData::LegendMap::find(
00214 const QWidget *widget)
00215 {
00216 if ( !d_widgetMap.contains((QWidget *)widget) )
00217 return NULL;
00218
00219 return (QwtPlotItem *)d_widgetMap[(QWidget *)widget];
00220 }
00221
00222 inline const QMap<QWidget *, const QwtPlotItem *> &
00223 QwtLegend::PrivateData::LegendMap::widgetMap() const
00224 {
00225 return d_widgetMap;
00226 }
00227
00228 inline QMap<QWidget *, const QwtPlotItem *> &
00229 QwtLegend::PrivateData::LegendMap::widgetMap()
00230 {
00231 return d_widgetMap;
00232 }
00233
00237 QwtLegend::QwtLegend(QWidget *parent):
00238 QFrame(parent)
00239 {
00240 setFrameStyle(NoFrame);
00241
00242 d_data = new QwtLegend::PrivateData;
00243 d_data->itemMode = QwtLegend::ReadOnlyItem;
00244 d_data->displayPolicy = QwtLegend::Auto;
00245 d_data->identifierMode = QwtLegendItem::ShowLine |
00246 QwtLegendItem::ShowSymbol | QwtLegendItem::ShowText;
00247
00248 d_data->view = new QwtLegend::PrivateData::LegendView(this);
00249 d_data->view->setFrameStyle(NoFrame);
00250
00251 QwtDynGridLayout *layout = new QwtDynGridLayout(
00252 d_data->view->contentsWidget);
00253 #if QT_VERSION < 0x040000
00254 layout->setAutoAdd(true);
00255 #endif
00256 layout->setAlignment(Qt::AlignHCenter | Qt::AlignTop);
00257
00258 d_data->view->contentsWidget->installEventFilter(this);
00259 }
00260
00261 QwtLegend::~QwtLegend()
00262 {
00263 delete d_data;
00264 }
00265
00274 void QwtLegend::setDisplayPolicy(LegendDisplayPolicy policy, int mode)
00275 {
00276 d_data->displayPolicy = policy;
00277 if (-1 != mode)
00278 d_data->identifierMode = mode;
00279
00280 QMap<QWidget *, const QwtPlotItem *> &map =
00281 d_data->map.widgetMap();
00282
00283 QMap<QWidget *, const QwtPlotItem *>::iterator it;
00284 for ( it = map.begin(); it != map.end(); ++it )
00285 {
00286 #if QT_VERSION < 0x040000
00287 QwtPlotItem *item = (QwtPlotItem *)it.data();
00288 #else
00289 QwtPlotItem *item = (QwtPlotItem *)it.value();
00290 #endif
00291 if ( item )
00292 item->updateLegend(this);
00293 }
00294 }
00295
00302 QwtLegend::LegendDisplayPolicy QwtLegend::displayPolicy() const
00303 {
00304 return d_data->displayPolicy;
00305 }
00306
00307 void QwtLegend::setItemMode(LegendItemMode mode)
00308 {
00309 d_data->itemMode = mode;
00310 }
00311
00312 QwtLegend::LegendItemMode QwtLegend::itemMode() const
00313 {
00314 return d_data->itemMode;
00315 }
00316
00324 int QwtLegend::identifierMode() const
00325 {
00326 return d_data->identifierMode;
00327 }
00328
00333 QWidget *QwtLegend::contentsWidget()
00334 {
00335 return d_data->view->contentsWidget;
00336 }
00337
00338 QScrollBar *QwtLegend::horizontalScrollBar() const
00339 {
00340 return d_data->view->horizontalScrollBar();
00341 }
00342
00343 QScrollBar *QwtLegend::verticalScrollBar() const
00344 {
00345 return d_data->view->horizontalScrollBar();
00346 }
00347
00353 const QWidget *QwtLegend::contentsWidget() const
00354 {
00355 return d_data->view->contentsWidget;
00356 }
00357
00364 void QwtLegend::insert(const QwtPlotItem *plotItem, QWidget *legendItem)
00365 {
00366 if ( legendItem == NULL || plotItem == NULL )
00367 return;
00368
00369 QWidget *contentsWidget = d_data->view->contentsWidget;
00370
00371 if ( legendItem->parent() != contentsWidget )
00372 {
00373 #if QT_VERSION >= 0x040000
00374 legendItem->setParent(contentsWidget);
00375 #else
00376 legendItem->reparent(contentsWidget, QPoint(0, 0));
00377 #endif
00378 }
00379
00380 legendItem->show();
00381
00382 d_data->map.insert(plotItem, legendItem);
00383
00384 layoutContents();
00385
00386 if ( contentsWidget->layout() )
00387 {
00388 #if QT_VERSION >= 0x040000
00389 contentsWidget->layout()->addWidget(legendItem);
00390 #endif
00391
00392
00393
00394 QWidget *w = NULL;
00395
00396 #if QT_VERSION < 0x040000
00397 QLayoutIterator layoutIterator =
00398 contentsWidget->layout()->iterator();
00399 for ( QLayoutItem *item = layoutIterator.current();
00400 item != 0; item = ++layoutIterator)
00401 {
00402 #else
00403 for (int i = 0; i < contentsWidget->layout()->count(); i++)
00404 {
00405 QLayoutItem *item = contentsWidget->layout()->itemAt(i);
00406 #endif
00407 if ( w && item->widget() )
00408 {
00409 QWidget::setTabOrder(w, item->widget());
00410 w = item->widget();
00411 }
00412 }
00413 }
00414 }
00415
00416 QWidget *QwtLegend::find(const QwtPlotItem *plotItem) const
00417 {
00418 return d_data->map.find(plotItem);
00419 }
00420
00421 QwtPlotItem *QwtLegend::find(const QWidget *legendItem) const
00422 {
00423 return d_data->map.find(legendItem);
00424 }
00425
00427 void QwtLegend::remove(const QwtPlotItem *plotItem)
00428 {
00429 QWidget *legendItem = d_data->map.find(plotItem);
00430 d_data->map.remove(legendItem);
00431 delete legendItem;
00432 }
00433
00435 void QwtLegend::clear()
00436 {
00437 #if QT_VERSION < 0x040000
00438 bool doUpdate = isUpdatesEnabled();
00439 #else
00440 bool doUpdate = updatesEnabled();
00441 #endif
00442 setUpdatesEnabled(false);
00443
00444 d_data->map.clear();
00445
00446 setUpdatesEnabled(doUpdate);
00447 update();
00448 }
00449
00451 QSize QwtLegend::sizeHint() const
00452 {
00453 QSize hint = d_data->view->contentsWidget->sizeHint();
00454 hint += QSize(2 * frameWidth(), 2 * frameWidth());
00455
00456 return hint;
00457 }
00458
00462 int QwtLegend::heightForWidth(int w) const
00463 {
00464 w -= 2 * frameWidth();
00465
00466 int h = d_data->view->contentsWidget->heightForWidth(w);
00467 #if QT_VERSION < 0x040000
00468
00469
00470
00471 if ( h <= 0 )
00472 {
00473 QLayout *l = d_data->view->contentsWidget->layout();
00474 if ( l && l->hasHeightForWidth() )
00475 h = l->heightForWidth(w);
00476 }
00477 #endif
00478 if ( h >= 0 )
00479 h += 2 * frameWidth();
00480
00481 return h;
00482 }
00483
00487 void QwtLegend::layoutContents()
00488 {
00489 const QSize visibleSize = d_data->view->viewport()->size();
00490
00491 const QLayout *l = d_data->view->contentsWidget->layout();
00492 if ( l && l->inherits("QwtDynGridLayout") )
00493 {
00494 const QwtDynGridLayout *tl = (const QwtDynGridLayout *)l;
00495
00496 const int minW = int(tl->maxItemWidth()) + 2 * tl->margin();
00497
00498 int w = qwtMax(visibleSize.width(), minW);
00499 int h = qwtMax(tl->heightForWidth(w), visibleSize.height());
00500
00501 const int vpWidth = d_data->view->viewportSize(w, h).width();
00502 if ( w > vpWidth )
00503 {
00504 w = qwtMax(vpWidth, minW);
00505 h = qwtMax(tl->heightForWidth(w), visibleSize.height());
00506 }
00507
00508 d_data->view->contentsWidget->resize(w, h);
00509 #if QT_VERSION < 0x040000
00510 d_data->view->resizeContents(w, h);
00511 #endif
00512 }
00513 }
00514
00515
00516
00517
00518
00519 bool QwtLegend::eventFilter(QObject *o, QEvent *e)
00520 {
00521 if ( o == d_data->view->contentsWidget )
00522 {
00523 switch(e->type())
00524 {
00525 case QEvent::ChildRemoved:
00526 {
00527 const QChildEvent *ce = (const QChildEvent *)e;
00528 if ( ce->child()->isWidgetType() )
00529 d_data->map.remove((QWidget *)ce->child());
00530 break;
00531 }
00532 #if QT_VERSION < 0x040000
00533 case QEvent::LayoutHint:
00534 #else
00535 case QEvent::LayoutRequest:
00536 #endif
00537 {
00538 layoutContents();
00539 break;
00540 }
00541 #if QT_VERSION < 0x040000
00542 case QEvent::Resize:
00543 {
00544 updateGeometry();
00545 break;
00546 }
00547 #endif
00548 default:
00549 break;
00550 }
00551 }
00552
00553 return QFrame::eventFilter(o, e);
00554 }
00555
00556
00558 bool QwtLegend::isEmpty() const
00559 {
00560 return d_data->map.count() == 0;
00561 }
00562
00564 uint QwtLegend::itemCount() const
00565 {
00566 return d_data->map.count();
00567 }
00568
00569 #if QT_VERSION < 0x040000
00570 QValueList<QWidget *> QwtLegend::legendItems() const
00571 #else
00572 QList<QWidget *> QwtLegend::legendItems() const
00573 #endif
00574 {
00575 const QMap<QWidget *, const QwtPlotItem *> &map =
00576 d_data->map.widgetMap();
00577
00578 #if QT_VERSION < 0x040000
00579 QValueList<QWidget *> list;
00580 #else
00581 QList<QWidget *> list;
00582 #endif
00583
00584 QMap<QWidget *, const QwtPlotItem *>::const_iterator it;
00585 for ( it = map.begin(); it != map.end(); ++it )
00586 list += it.key();
00587
00588 return list;
00589 }
00590
00591 void QwtLegend::resizeEvent(QResizeEvent *e)
00592 {
00593 QFrame::resizeEvent(e);
00594 d_data->view->setGeometry(contentsRect());
00595 }