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
00238 QwtLegend::QwtLegend(QWidget *parent):
00239 QFrame(parent)
00240 {
00241 setFrameStyle(NoFrame);
00242
00243 d_data = new QwtLegend::PrivateData;
00244 d_data->itemMode = QwtLegend::ReadOnlyItem;
00245 d_data->displayPolicy = QwtLegend::Auto;
00246 d_data->identifierMode = QwtLegendItem::ShowLine |
00247 QwtLegendItem::ShowSymbol | QwtLegendItem::ShowText;
00248
00249 d_data->view = new QwtLegend::PrivateData::LegendView(this);
00250 d_data->view->setFrameStyle(NoFrame);
00251
00252 QwtDynGridLayout *layout = new QwtDynGridLayout(
00253 d_data->view->contentsWidget);
00254 #if QT_VERSION < 0x040000
00255 layout->setAutoAdd(true);
00256 #endif
00257 layout->setAlignment(Qt::AlignHCenter | Qt::AlignTop);
00258
00259 d_data->view->contentsWidget->installEventFilter(this);
00260 }
00261
00262 QwtLegend::~QwtLegend()
00263 {
00264 delete d_data;
00265 }
00266
00275 void QwtLegend::setDisplayPolicy(LegendDisplayPolicy policy, int mode)
00276 {
00277 d_data->displayPolicy = policy;
00278 if (-1 != mode)
00279 d_data->identifierMode = mode;
00280
00281 QMap<QWidget *, const QwtPlotItem *> &map =
00282 d_data->map.widgetMap();
00283
00284 QMap<QWidget *, const QwtPlotItem *>::iterator it;
00285 for ( it = map.begin(); it != map.end(); ++it )
00286 {
00287 #if QT_VERSION < 0x040000
00288 QwtPlotItem *item = (QwtPlotItem *)it.data();
00289 #else
00290 QwtPlotItem *item = (QwtPlotItem *)it.value();
00291 #endif
00292 if ( item )
00293 item->updateLegend(this);
00294 }
00295 }
00296
00303 QwtLegend::LegendDisplayPolicy QwtLegend::displayPolicy() const
00304 {
00305 return d_data->displayPolicy;
00306 }
00307
00308 void QwtLegend::setItemMode(LegendItemMode mode)
00309 {
00310 d_data->itemMode = mode;
00311 }
00312
00313 QwtLegend::LegendItemMode QwtLegend::itemMode() const
00314 {
00315 return d_data->itemMode;
00316 }
00317
00325 int QwtLegend::identifierMode() const
00326 {
00327 return d_data->identifierMode;
00328 }
00329
00334 QWidget *QwtLegend::contentsWidget()
00335 {
00336 return d_data->view->contentsWidget;
00337 }
00338
00339 QScrollBar *QwtLegend::horizontalScrollBar() const
00340 {
00341 return d_data->view->horizontalScrollBar();
00342 }
00343
00344 QScrollBar *QwtLegend::verticalScrollBar() const
00345 {
00346 return d_data->view->horizontalScrollBar();
00347 }
00348
00354 const QWidget *QwtLegend::contentsWidget() const
00355 {
00356 return d_data->view->contentsWidget;
00357 }
00358
00366 void QwtLegend::insert(const QwtPlotItem *plotItem, QWidget *legendItem)
00367 {
00368 if ( legendItem == NULL || plotItem == NULL )
00369 return;
00370
00371 QWidget *contentsWidget = d_data->view->contentsWidget;
00372
00373 if ( legendItem->parent() != contentsWidget )
00374 {
00375 #if QT_VERSION >= 0x040000
00376 legendItem->setParent(contentsWidget);
00377 #else
00378 legendItem->reparent(contentsWidget, QPoint(0, 0));
00379 #endif
00380 }
00381
00382 legendItem->show();
00383
00384 d_data->map.insert(plotItem, legendItem);
00385
00386 layoutContents();
00387
00388 if ( contentsWidget->layout() )
00389 {
00390 #if QT_VERSION >= 0x040000
00391 contentsWidget->layout()->addWidget(legendItem);
00392 #endif
00393
00394
00395
00396 QWidget *w = NULL;
00397
00398 #if QT_VERSION < 0x040000
00399 QLayoutIterator layoutIterator =
00400 contentsWidget->layout()->iterator();
00401 for ( QLayoutItem *item = layoutIterator.current();
00402 item != 0; item = ++layoutIterator)
00403 {
00404 #else
00405 for (int i = 0; i < contentsWidget->layout()->count(); i++)
00406 {
00407 QLayoutItem *item = contentsWidget->layout()->itemAt(i);
00408 #endif
00409 if ( w && item->widget() )
00410 {
00411 QWidget::setTabOrder(w, item->widget());
00412 w = item->widget();
00413 }
00414 }
00415 }
00416 }
00417
00418 QWidget *QwtLegend::find(const QwtPlotItem *plotItem) const
00419 {
00420 return d_data->map.find(plotItem);
00421 }
00422
00423 QwtPlotItem *QwtLegend::find(const QWidget *legendItem) const
00424 {
00425 return d_data->map.find(legendItem);
00426 }
00427
00429 void QwtLegend::remove(const QwtPlotItem *plotItem)
00430 {
00431 QWidget *legendItem = d_data->map.find(plotItem);
00432 d_data->map.remove(legendItem);
00433 delete legendItem;
00434 }
00435
00437 void QwtLegend::clear()
00438 {
00439 #if QT_VERSION < 0x040000
00440 bool doUpdate = isUpdatesEnabled();
00441 #else
00442 bool doUpdate = updatesEnabled();
00443 #endif
00444 setUpdatesEnabled(false);
00445
00446 d_data->map.clear();
00447
00448 setUpdatesEnabled(doUpdate);
00449 update();
00450 }
00451
00453 QSize QwtLegend::sizeHint() const
00454 {
00455 QSize hint = d_data->view->contentsWidget->sizeHint();
00456 hint += QSize(2 * frameWidth(), 2 * frameWidth());
00457
00458 return hint;
00459 }
00460
00464 int QwtLegend::heightForWidth(int w) const
00465 {
00466 w -= 2 * frameWidth();
00467
00468 int h = d_data->view->contentsWidget->heightForWidth(w);
00469 #if QT_VERSION < 0x040000
00470
00471
00472
00473 if ( h <= 0 )
00474 {
00475 QLayout *l = d_data->view->contentsWidget->layout();
00476 if ( l && l->hasHeightForWidth() )
00477 h = l->heightForWidth(w);
00478 }
00479 #endif
00480 if ( h >= 0 )
00481 h += 2 * frameWidth();
00482
00483 return h;
00484 }
00485
00489 void QwtLegend::layoutContents()
00490 {
00491 const QSize visibleSize = d_data->view->viewport()->size();
00492
00493 const QLayout *l = d_data->view->contentsWidget->layout();
00494 if ( l && l->inherits("QwtDynGridLayout") )
00495 {
00496 const QwtDynGridLayout *tl = (const QwtDynGridLayout *)l;
00497
00498 const int minW = int(tl->maxItemWidth()) + 2 * tl->margin();
00499
00500 int w = qwtMax(visibleSize.width(), minW);
00501 int h = qwtMax(tl->heightForWidth(w), visibleSize.height());
00502
00503 const int vpWidth = d_data->view->viewportSize(w, h).width();
00504 if ( w > vpWidth )
00505 {
00506 w = qwtMax(vpWidth, minW);
00507 h = qwtMax(tl->heightForWidth(w), visibleSize.height());
00508 }
00509
00510 d_data->view->contentsWidget->resize(w, h);
00511 #if QT_VERSION < 0x040000
00512 d_data->view->resizeContents(w, h);
00513 #endif
00514 }
00515 }
00516
00517
00518
00519
00520
00521 bool QwtLegend::eventFilter(QObject *o, QEvent *e)
00522 {
00523 if ( o == d_data->view->contentsWidget )
00524 {
00525 switch(e->type())
00526 {
00527 case QEvent::ChildRemoved:
00528 {
00529 const QChildEvent *ce = (const QChildEvent *)e;
00530 if ( ce->child()->isWidgetType() )
00531 d_data->map.remove((QWidget *)ce->child());
00532 break;
00533 }
00534 #if QT_VERSION < 0x040000
00535 case QEvent::LayoutHint:
00536 #else
00537 case QEvent::LayoutRequest:
00538 #endif
00539 {
00540 layoutContents();
00541 break;
00542 }
00543 default:
00544 break;
00545 }
00546 }
00547
00548 return QFrame::eventFilter(o, e);
00549 }
00550
00551
00553 bool QwtLegend::isEmpty() const
00554 {
00555 return d_data->map.count() == 0;
00556 }
00557
00559 uint QwtLegend::itemCount() const
00560 {
00561 return d_data->map.count();
00562 }
00563
00564 #if QT_VERSION < 0x040000
00565 QValueList<QWidget *> QwtLegend::legendItems() const
00566 #else
00567 QList<QWidget *> QwtLegend::legendItems() const
00568 #endif
00569 {
00570 const QMap<QWidget *, const QwtPlotItem *> &map =
00571 d_data->map.widgetMap();
00572
00573 #if QT_VERSION < 0x040000
00574 QValueList<QWidget *> list;
00575 #else
00576 QList<QWidget *> list;
00577 #endif
00578
00579 QMap<QWidget *, const QwtPlotItem *>::const_iterator it;
00580 for ( it = map.begin(); it != map.end(); ++it )
00581 list += it.key();
00582
00583 return list;
00584 }
00585
00586 void QwtLegend::resizeEvent(QResizeEvent *e)
00587 {
00588 QFrame::resizeEvent(e);
00589 d_data->view->setGeometry(contentsRect());
00590 }