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 setFocusPolicy(Qt::NoFocus);
00110 }
00111
00112 virtual bool viewportEvent(QEvent *e)
00113 {
00114 bool ok = QScrollArea::viewportEvent(e);
00115
00116 if ( e->type() == QEvent::Resize )
00117 {
00118 QApplication::sendEvent(contentsWidget,
00119 new QEvent(QEvent::LayoutRequest));
00120 }
00121 return ok;
00122 }
00123
00124 QSize viewportSize(int w, int h) const
00125 {
00126 const int sbHeight = horizontalScrollBar()->sizeHint().height();
00127 const int sbWidth = verticalScrollBar()->sizeHint().width();
00128
00129 const int cw = contentsRect().width();
00130 const int ch = contentsRect().height();
00131
00132 int vw = cw;
00133 int vh = ch;
00134
00135 if ( w > vw )
00136 vh -= sbHeight;
00137
00138 if ( h > vh )
00139 {
00140 vw -= sbWidth;
00141 if ( w > vw && vh == ch )
00142 vh -= sbHeight;
00143 }
00144 return QSize(vw, vh);
00145 }
00146
00147 QWidget *contentsWidget;
00148 };
00149
00150 #endif
00151
00152
00153 void QwtLegend::PrivateData::LegendMap::insert(
00154 const QwtPlotItem *item, QWidget *widget)
00155 {
00156 d_itemMap.insert(item, widget);
00157 d_widgetMap.insert(widget, item);
00158 }
00159
00160 void QwtLegend::PrivateData::LegendMap::remove(const QwtPlotItem *item)
00161 {
00162 QWidget *widget = d_itemMap[item];
00163 d_itemMap.remove(item);
00164 d_widgetMap.remove(widget);
00165 }
00166
00167 void QwtLegend::PrivateData::LegendMap::remove(QWidget *widget)
00168 {
00169 const QwtPlotItem *item = d_widgetMap[widget];
00170 d_itemMap.remove(item);
00171 d_widgetMap.remove(widget);
00172 }
00173
00174 void QwtLegend::PrivateData::LegendMap::clear()
00175 {
00176
00177
00178
00179
00180
00181
00182
00183 #if QT_VERSION < 0x040000
00184 QValueList<QWidget *> widgets;
00185
00186 QMap<const QwtPlotItem *, QWidget *>::const_iterator it;
00187 for ( it = d_itemMap.begin(); it != d_itemMap.end(); ++it )
00188 widgets.append(it.data());
00189 #else
00190 QList<QWidget *> widgets;
00191
00192 QMap<const QwtPlotItem *, QWidget *>::const_iterator it;
00193 for ( it = d_itemMap.begin(); it != d_itemMap.end(); ++it )
00194 widgets.append(it.value());
00195 #endif
00196
00197 d_itemMap.clear();
00198 d_widgetMap.clear();
00199
00200 for ( int i = 0; i < (int)widgets.size(); i++ )
00201 delete widgets[i];
00202 }
00203
00204 uint QwtLegend::PrivateData::LegendMap::count() const
00205 {
00206 return d_itemMap.count();
00207 }
00208
00209 inline const QWidget *QwtLegend::PrivateData::LegendMap::find(const QwtPlotItem *item) const
00210 {
00211 if ( !d_itemMap.contains((QwtPlotItem *)item) )
00212 return NULL;
00213
00214 return d_itemMap[(QwtPlotItem *)item];
00215 }
00216
00217 inline QWidget *QwtLegend::PrivateData::LegendMap::find(const QwtPlotItem *item)
00218 {
00219 if ( !d_itemMap.contains((QwtPlotItem *)item) )
00220 return NULL;
00221
00222 return d_itemMap[(QwtPlotItem *)item];
00223 }
00224
00225 inline const QwtPlotItem *QwtLegend::PrivateData::LegendMap::find(
00226 const QWidget *widget) const
00227 {
00228 if ( !d_widgetMap.contains((QWidget *)widget) )
00229 return NULL;
00230
00231 return d_widgetMap[(QWidget *)widget];
00232 }
00233
00234 inline QwtPlotItem *QwtLegend::PrivateData::LegendMap::find(
00235 const QWidget *widget)
00236 {
00237 if ( !d_widgetMap.contains((QWidget *)widget) )
00238 return NULL;
00239
00240 return (QwtPlotItem *)d_widgetMap[(QWidget *)widget];
00241 }
00242
00243 inline const QMap<QWidget *, const QwtPlotItem *> &
00244 QwtLegend::PrivateData::LegendMap::widgetMap() const
00245 {
00246 return d_widgetMap;
00247 }
00248
00249 inline QMap<QWidget *, const QwtPlotItem *> &
00250 QwtLegend::PrivateData::LegendMap::widgetMap()
00251 {
00252 return d_widgetMap;
00253 }
00254
00258 QwtLegend::QwtLegend(QWidget *parent):
00259 QFrame(parent)
00260 {
00261 setFrameStyle(NoFrame);
00262
00263 d_data = new QwtLegend::PrivateData;
00264 d_data->itemMode = QwtLegend::ReadOnlyItem;
00265 d_data->displayPolicy = QwtLegend::AutoIdentifier;
00266 d_data->identifierMode = QwtLegendItem::ShowLine |
00267 QwtLegendItem::ShowSymbol | QwtLegendItem::ShowText;
00268
00269 d_data->view = new QwtLegend::PrivateData::LegendView(this);
00270 d_data->view->setFrameStyle(NoFrame);
00271
00272 QwtDynGridLayout *layout = new QwtDynGridLayout(
00273 d_data->view->contentsWidget);
00274 #if QT_VERSION < 0x040000
00275 layout->setAutoAdd(true);
00276 #endif
00277 layout->setAlignment(Qt::AlignHCenter | Qt::AlignTop);
00278
00279 d_data->view->contentsWidget->installEventFilter(this);
00280 }
00281
00283 QwtLegend::~QwtLegend()
00284 {
00285 delete d_data;
00286 }
00287
00296 void QwtLegend::setDisplayPolicy(LegendDisplayPolicy policy, int mode)
00297 {
00298 d_data->displayPolicy = policy;
00299 if (-1 != mode)
00300 d_data->identifierMode = mode;
00301
00302 QMap<QWidget *, const QwtPlotItem *> &map =
00303 d_data->map.widgetMap();
00304
00305 QMap<QWidget *, const QwtPlotItem *>::iterator it;
00306 for ( it = map.begin(); it != map.end(); ++it )
00307 {
00308 #if QT_VERSION < 0x040000
00309 QwtPlotItem *item = (QwtPlotItem *)it.data();
00310 #else
00311 QwtPlotItem *item = (QwtPlotItem *)it.value();
00312 #endif
00313 if ( item )
00314 item->updateLegend(this);
00315 }
00316 }
00317
00324 QwtLegend::LegendDisplayPolicy QwtLegend::displayPolicy() const
00325 {
00326 return d_data->displayPolicy;
00327 }
00328
00329 void QwtLegend::setItemMode(LegendItemMode mode)
00330 {
00331 d_data->itemMode = mode;
00332 }
00333
00334 QwtLegend::LegendItemMode QwtLegend::itemMode() const
00335 {
00336 return d_data->itemMode;
00337 }
00338
00346 int QwtLegend::identifierMode() const
00347 {
00348 return d_data->identifierMode;
00349 }
00350
00355 QWidget *QwtLegend::contentsWidget()
00356 {
00357 return d_data->view->contentsWidget;
00358 }
00359
00360 QScrollBar *QwtLegend::horizontalScrollBar() const
00361 {
00362 return d_data->view->horizontalScrollBar();
00363 }
00364
00365 QScrollBar *QwtLegend::verticalScrollBar() const
00366 {
00367 return d_data->view->horizontalScrollBar();
00368 }
00369
00375 const QWidget *QwtLegend::contentsWidget() const
00376 {
00377 return d_data->view->contentsWidget;
00378 }
00379
00386 void QwtLegend::insert(const QwtPlotItem *plotItem, QWidget *legendItem)
00387 {
00388 if ( legendItem == NULL || plotItem == NULL )
00389 return;
00390
00391 QWidget *contentsWidget = d_data->view->contentsWidget;
00392
00393 if ( legendItem->parent() != contentsWidget )
00394 {
00395 #if QT_VERSION >= 0x040000
00396 legendItem->setParent(contentsWidget);
00397 #else
00398 legendItem->reparent(contentsWidget, QPoint(0, 0));
00399 #endif
00400 }
00401
00402 legendItem->show();
00403
00404 d_data->map.insert(plotItem, legendItem);
00405
00406 layoutContents();
00407
00408 if ( contentsWidget->layout() )
00409 {
00410 #if QT_VERSION >= 0x040000
00411 contentsWidget->layout()->addWidget(legendItem);
00412 #endif
00413
00414
00415
00416 QWidget *w = NULL;
00417
00418 #if QT_VERSION < 0x040000
00419 QLayoutIterator layoutIterator =
00420 contentsWidget->layout()->iterator();
00421 for ( QLayoutItem *item = layoutIterator.current();
00422 item != 0; item = ++layoutIterator)
00423 {
00424 #else
00425 for (int i = 0; i < contentsWidget->layout()->count(); i++)
00426 {
00427 QLayoutItem *item = contentsWidget->layout()->itemAt(i);
00428 #endif
00429 if ( w && item->widget() )
00430 {
00431 QWidget::setTabOrder(w, item->widget());
00432 w = item->widget();
00433 }
00434 }
00435 }
00436 if ( parentWidget() && parentWidget()->layout() == NULL )
00437 {
00438
00439
00440
00441
00442
00443
00444 #if QT_VERSION < 0x040000
00445 QApplication::postEvent(parentWidget(),
00446 new QEvent(QEvent::LayoutHint));
00447 #else
00448 QApplication::postEvent(parentWidget(),
00449 new QEvent(QEvent::LayoutRequest));
00450 #endif
00451 }
00452 }
00453
00460 QWidget *QwtLegend::find(const QwtPlotItem *plotItem) const
00461 {
00462 return d_data->map.find(plotItem);
00463 }
00464
00471 QwtPlotItem *QwtLegend::find(const QWidget *legendItem) const
00472 {
00473 return d_data->map.find(legendItem);
00474 }
00475
00482 void QwtLegend::remove(const QwtPlotItem *plotItem)
00483 {
00484 QWidget *legendItem = d_data->map.find(plotItem);
00485 d_data->map.remove(legendItem);
00486 delete legendItem;
00487 }
00488
00490 void QwtLegend::clear()
00491 {
00492 #if QT_VERSION < 0x040000
00493 bool doUpdate = isUpdatesEnabled();
00494 #else
00495 bool doUpdate = updatesEnabled();
00496 #endif
00497 setUpdatesEnabled(false);
00498
00499 d_data->map.clear();
00500
00501 setUpdatesEnabled(doUpdate);
00502 update();
00503 }
00504
00506 QSize QwtLegend::sizeHint() const
00507 {
00508 QSize hint = d_data->view->contentsWidget->sizeHint();
00509 hint += QSize(2 * frameWidth(), 2 * frameWidth());
00510
00511 return hint;
00512 }
00513
00518 int QwtLegend::heightForWidth(int width) const
00519 {
00520 width -= 2 * frameWidth();
00521
00522 int h = d_data->view->contentsWidget->heightForWidth(width);
00523 #if QT_VERSION < 0x040000
00524
00525
00526
00527 if ( h <= 0 )
00528 {
00529 QLayout *l = d_data->view->contentsWidget->layout();
00530 if ( l && l->hasHeightForWidth() )
00531 h = l->heightForWidth(width);
00532 }
00533 #endif
00534 if ( h >= 0 )
00535 h += 2 * frameWidth();
00536
00537 return h;
00538 }
00539
00543 void QwtLegend::layoutContents()
00544 {
00545 const QSize visibleSize = d_data->view->viewport()->size();
00546
00547 const QLayout *l = d_data->view->contentsWidget->layout();
00548 if ( l && l->inherits("QwtDynGridLayout") )
00549 {
00550 const QwtDynGridLayout *tl = (const QwtDynGridLayout *)l;
00551
00552 const int minW = int(tl->maxItemWidth()) + 2 * tl->margin();
00553
00554 int w = qwtMax(visibleSize.width(), minW);
00555 int h = qwtMax(tl->heightForWidth(w), visibleSize.height());
00556
00557 const int vpWidth = d_data->view->viewportSize(w, h).width();
00558 if ( w > vpWidth )
00559 {
00560 w = qwtMax(vpWidth, minW);
00561 h = qwtMax(tl->heightForWidth(w), visibleSize.height());
00562 }
00563
00564 d_data->view->contentsWidget->resize(w, h);
00565 #if QT_VERSION < 0x040000
00566 d_data->view->resizeContents(w, h);
00567 #endif
00568 }
00569 }
00570
00571
00572
00573
00574
00575
00576
00577
00578 bool QwtLegend::eventFilter(QObject *o, QEvent *e)
00579 {
00580 if ( o == d_data->view->contentsWidget )
00581 {
00582 switch(e->type())
00583 {
00584 case QEvent::ChildRemoved:
00585 {
00586 const QChildEvent *ce = (const QChildEvent *)e;
00587 if ( ce->child()->isWidgetType() )
00588 d_data->map.remove((QWidget *)ce->child());
00589 break;
00590 }
00591 #if QT_VERSION < 0x040000
00592 case QEvent::LayoutHint:
00593 #else
00594 case QEvent::LayoutRequest:
00595 #endif
00596 {
00597 layoutContents();
00598 break;
00599 }
00600 #if QT_VERSION < 0x040000
00601 case QEvent::Resize:
00602 {
00603 updateGeometry();
00604 break;
00605 }
00606 #endif
00607 default:
00608 break;
00609 }
00610 }
00611
00612 return QFrame::eventFilter(o, e);
00613 }
00614
00615
00617 bool QwtLegend::isEmpty() const
00618 {
00619 return d_data->map.count() == 0;
00620 }
00621
00623 uint QwtLegend::itemCount() const
00624 {
00625 return d_data->map.count();
00626 }
00627
00628 #if QT_VERSION < 0x040000
00629 QValueList<QWidget *> QwtLegend::legendItems() const
00630 #else
00631 QList<QWidget *> QwtLegend::legendItems() const
00632 #endif
00633 {
00634 const QMap<QWidget *, const QwtPlotItem *> &map =
00635 d_data->map.widgetMap();
00636
00637 #if QT_VERSION < 0x040000
00638 QValueList<QWidget *> list;
00639 #else
00640 QList<QWidget *> list;
00641 #endif
00642
00643 QMap<QWidget *, const QwtPlotItem *>::const_iterator it;
00644 for ( it = map.begin(); it != map.end(); ++it )
00645 list += it.key();
00646
00647 return list;
00648 }
00649
00654 void QwtLegend::resizeEvent(QResizeEvent *e)
00655 {
00656 QFrame::resizeEvent(e);
00657 d_data->view->setGeometry(contentsRect());
00658 }