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