Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <qpainter.h>
00011 #if QT_VERSION < 0x040000
00012 #include <qguardedptr.h>
00013 #include <qfocusdata.h>
00014 #else
00015 #include <qpointer.h>
00016 #include <qpaintengine.h>
00017 #endif
00018 #include <qapplication.h>
00019 #include <qevent.h>
00020 #include "qwt_plot.h"
00021 #include "qwt_plot_dict.h"
00022 #include "qwt_plot_layout.h"
00023 #include "qwt_scale_widget.h"
00024 #include "qwt_scale_engine.h"
00025 #include "qwt_text_label.h"
00026 #include "qwt_legend.h"
00027 #include "qwt_dyngrid_layout.h"
00028 #include "qwt_plot_canvas.h"
00029 #include "qwt_paint_buffer.h"
00030
00031 class QwtPlot::PrivateData
00032 {
00033 public:
00034 #if QT_VERSION < 0x040000
00035 QGuardedPtr<QwtTextLabel> lblTitle;
00036 QGuardedPtr<QwtPlotCanvas> canvas;
00037 QGuardedPtr<QwtLegend> legend;
00038 #else
00039 QPointer<QwtTextLabel> lblTitle;
00040 QPointer<QwtPlotCanvas> canvas;
00041 QPointer<QwtLegend> legend;
00042 #endif
00043 QwtPlotLayout *layout;
00044
00045 bool autoReplot;
00046 };
00047
00052 QwtPlot::QwtPlot(QWidget *parent):
00053 QFrame(parent)
00054 {
00055 initPlot(QwtText());
00056 }
00057
00063 QwtPlot::QwtPlot(const QwtText &title, QWidget *parent):
00064 QFrame(parent)
00065 {
00066 initPlot(title);
00067 }
00068
00069 #if QT_VERSION < 0x040000
00070
00075 QwtPlot::QwtPlot(QWidget *parent, const char *name):
00076 QFrame(parent, name)
00077 {
00078 initPlot(QwtText());
00079 }
00080 #endif
00081
00082
00084 QwtPlot::~QwtPlot()
00085 {
00086 detachItems(QwtPlotItem::Rtti_PlotItem, autoDelete());
00087
00088 delete d_data->layout;
00089 deleteAxesData();
00090 delete d_data;
00091 }
00092
00097 void QwtPlot::initPlot(const QwtText &title)
00098 {
00099 d_data = new PrivateData;
00100
00101 #if QT_VERSION < 0x040000
00102 setWFlags(Qt::WNoAutoErase);
00103 #endif
00104
00105 d_data->layout = new QwtPlotLayout;
00106
00107 d_data->autoReplot = false;
00108
00109 d_data->lblTitle = new QwtTextLabel(title, this);
00110 d_data->lblTitle->setFont(QFont(fontInfo().family(), 14, QFont::Bold));
00111
00112 QwtText text(title);
00113 int flags = Qt::AlignCenter;
00114 #if QT_VERSION < 0x040000
00115 flags |= Qt::WordBreak | Qt::ExpandTabs;
00116 #else
00117 flags |= Qt::TextWordWrap;
00118 #endif
00119 text.setRenderFlags(flags);
00120 d_data->lblTitle->setText(text);
00121
00122 d_data->legend = NULL;
00123
00124 initAxesData();
00125
00126 d_data->canvas = new QwtPlotCanvas(this);
00127 d_data->canvas->setFrameStyle(QFrame::Panel|QFrame::Sunken);
00128 d_data->canvas->setLineWidth(2);
00129 d_data->canvas->setMidLineWidth(0);
00130
00131 updateTabOrder();
00132
00133 setSizePolicy(QSizePolicy::MinimumExpanding,
00134 QSizePolicy::MinimumExpanding);
00135 }
00136
00140 bool QwtPlot::event(QEvent *e)
00141 {
00142 bool ok = QFrame::event(e);
00143 switch(e->type())
00144 {
00145 #if QT_VERSION < 0x040000
00146 case QEvent::LayoutHint:
00147 #else
00148 case QEvent::LayoutRequest:
00149 #endif
00150 updateLayout();
00151 break;
00152 #if QT_VERSION >= 0x040000
00153 case QEvent::PolishRequest:
00154 polish();
00155 break;
00156 #endif
00157 default:;
00158 }
00159 return ok;
00160 }
00161
00163 void QwtPlot::autoRefresh()
00164 {
00165 if (d_data->autoReplot)
00166 replot();
00167 }
00168
00184 void QwtPlot::setAutoReplot(bool tf)
00185 {
00186 d_data->autoReplot = tf;
00187 }
00188
00190 bool QwtPlot::autoReplot() const
00191 {
00192 return d_data->autoReplot;
00193 }
00194
00199 void QwtPlot::setTitle(const QString &title)
00200 {
00201 if ( title != d_data->lblTitle->text().text() )
00202 {
00203 d_data->lblTitle->setText(title);
00204 updateLayout();
00205 }
00206 }
00207
00212 void QwtPlot::setTitle(const QwtText &title)
00213 {
00214 if ( title != d_data->lblTitle->text() )
00215 {
00216 d_data->lblTitle->setText(title);
00217 updateLayout();
00218 }
00219 }
00220
00222 QwtText QwtPlot::title() const
00223 {
00224 return d_data->lblTitle->text();
00225 }
00226
00228 QwtPlotLayout *QwtPlot::plotLayout()
00229 {
00230 return d_data->layout;
00231 }
00232
00234 const QwtPlotLayout *QwtPlot::plotLayout() const
00235 {
00236 return d_data->layout;
00237 }
00238
00240 QwtTextLabel *QwtPlot::titleLabel()
00241 {
00242 return d_data->lblTitle;
00243 }
00244
00248 const QwtTextLabel *QwtPlot::titleLabel() const
00249 {
00250 return d_data->lblTitle;
00251 }
00252
00257 QwtLegend *QwtPlot::legend()
00258 {
00259 return d_data->legend;
00260 }
00261
00266 const QwtLegend *QwtPlot::legend() const
00267 {
00268 return d_data->legend;
00269 }
00270
00271
00275 QwtPlotCanvas *QwtPlot::canvas()
00276 {
00277 return d_data->canvas;
00278 }
00279
00283 const QwtPlotCanvas *QwtPlot::canvas() const
00284 {
00285 return d_data->canvas;
00286 }
00287
00289 void QwtPlot::polish()
00290 {
00291 replot();
00292
00293 #if QT_VERSION < 0x040000
00294 QFrame::polish();
00295 #endif
00296 }
00297
00303 QSize QwtPlot::sizeHint() const
00304 {
00305 int dw = 0;
00306 int dh = 0;
00307 for ( int axisId = 0; axisId < axisCnt; axisId++ )
00308 {
00309 if ( axisEnabled(axisId) )
00310 {
00311 const int niceDist = 40;
00312 const QwtScaleWidget *scaleWidget = axisWidget(axisId);
00313 const QwtScaleDiv &scaleDiv = scaleWidget->scaleDraw()->scaleDiv();
00314 const int majCnt = scaleDiv.ticks(QwtScaleDiv::MajorTick).count();
00315
00316 if ( axisId == yLeft || axisId == yRight )
00317 {
00318 int hDiff = (majCnt - 1) * niceDist
00319 - scaleWidget->minimumSizeHint().height();
00320 if ( hDiff > dh )
00321 dh = hDiff;
00322 }
00323 else
00324 {
00325 int wDiff = (majCnt - 1) * niceDist
00326 - scaleWidget->minimumSizeHint().width();
00327 if ( wDiff > dw )
00328 dw = wDiff;
00329 }
00330 }
00331 }
00332 return minimumSizeHint() + QSize(dw, dh);
00333 }
00334
00338 QSize QwtPlot::minimumSizeHint() const
00339 {
00340 QSize hint = d_data->layout->minimumSizeHint(this);
00341 hint += QSize(2 * frameWidth(), 2 * frameWidth());
00342
00343 return hint;
00344 }
00345
00350 void QwtPlot::resizeEvent(QResizeEvent *e)
00351 {
00352 QFrame::resizeEvent(e);
00353 updateLayout();
00354 }
00355
00366 void QwtPlot::replot()
00367 {
00368 bool doAutoReplot = autoReplot();
00369 setAutoReplot(false);
00370
00371 updateAxes();
00372
00373
00374
00375
00376
00377
00378 #if QT_VERSION >= 0x040000
00379 QApplication::sendPostedEvents(this, QEvent::LayoutRequest);
00380 #else
00381 QApplication::sendPostedEvents(this, QEvent::LayoutHint);
00382 #endif
00383
00384 d_data->canvas->replot();
00385
00386 setAutoReplot(doAutoReplot);
00387 }
00388
00393 void QwtPlot::updateLayout()
00394 {
00395 d_data->layout->activate(this, contentsRect());
00396
00397
00398
00399
00400 if (!d_data->lblTitle->text().isEmpty())
00401 {
00402 d_data->lblTitle->setGeometry(d_data->layout->titleRect());
00403 if (!d_data->lblTitle->isVisible())
00404 d_data->lblTitle->show();
00405 }
00406 else
00407 d_data->lblTitle->hide();
00408
00409 for (int axisId = 0; axisId < axisCnt; axisId++ )
00410 {
00411 if (axisEnabled(axisId) )
00412 {
00413 axisWidget(axisId)->setGeometry(d_data->layout->scaleRect(axisId));
00414
00415 if ( axisId == xBottom || axisId == xTop )
00416 {
00417 QRegion r(d_data->layout->scaleRect(axisId));
00418 if ( axisEnabled(yLeft) )
00419 r = r.subtract(QRegion(d_data->layout->scaleRect(yLeft)));
00420 if ( axisEnabled(yRight) )
00421 r = r.subtract(QRegion(d_data->layout->scaleRect(yRight)));
00422 r.translate(-d_data->layout->scaleRect(axisId).x(),
00423 -d_data->layout->scaleRect(axisId).y());
00424
00425 axisWidget(axisId)->setMask(r);
00426 }
00427 if (!axisWidget(axisId)->isVisible())
00428 axisWidget(axisId)->show();
00429 }
00430 else
00431 axisWidget(axisId)->hide();
00432 }
00433
00434 if ( d_data->legend &&
00435 d_data->layout->legendPosition() != ExternalLegend )
00436 {
00437 if (d_data->legend->itemCount() > 0)
00438 {
00439 d_data->legend->setGeometry(d_data->layout->legendRect());
00440 d_data->legend->show();
00441 }
00442 else
00443 d_data->legend->hide();
00444 }
00445
00446 d_data->canvas->setGeometry(d_data->layout->canvasRect());
00447 }
00448
00457 void QwtPlot::updateTabOrder()
00458 {
00459 #if QT_VERSION >= 0x040000
00460 using namespace Qt;
00461 #else
00462 if ( d_data->canvas->focusPolicy() == NoFocus )
00463 return;
00464 #endif
00465 if ( d_data->legend.isNull()
00466 || d_data->layout->legendPosition() == ExternalLegend
00467 || d_data->legend->legendItems().count() == 0 )
00468 {
00469 return;
00470 }
00471
00472
00473
00474
00475
00476
00477 const bool canvasFirst =
00478 d_data->layout->legendPosition() == QwtPlot::BottomLegend ||
00479 d_data->layout->legendPosition() == QwtPlot::RightLegend;
00480
00481 QWidget *previous = NULL;
00482
00483 QWidget *w;
00484 #if QT_VERSION >= 0x040000
00485 w = d_data->canvas;
00486 while ( ( w = w->nextInFocusChain() ) != d_data->canvas )
00487 #else
00488 if ( focusData() == NULL )
00489 return;
00490
00491 while ( focusData()->next() != d_data->canvas );
00492 while ( (w = focusData()->next()) != d_data->canvas )
00493 #endif
00494 {
00495 bool isLegendItem = false;
00496 if ( w->focusPolicy() != NoFocus
00497 && w->parent() && w->parent() == d_data->legend->contentsWidget() )
00498 {
00499 isLegendItem = true;
00500 }
00501
00502 if ( canvasFirst )
00503 {
00504 if ( isLegendItem )
00505 break;
00506
00507 previous = w;
00508 }
00509 else
00510 {
00511 if ( isLegendItem )
00512 previous = w;
00513 else
00514 {
00515 if ( previous )
00516 break;
00517 }
00518 }
00519 }
00520
00521 if ( previous && previous != d_data->canvas)
00522 setTabOrder(previous, d_data->canvas);
00523 }
00524
00534 void QwtPlot::drawCanvas(QPainter *painter)
00535 {
00536 QwtScaleMap maps[axisCnt];
00537 for ( int axisId = 0; axisId < axisCnt; axisId++ )
00538 maps[axisId] = canvasMap(axisId);
00539
00540 drawItems(painter,
00541 d_data->canvas->contentsRect(), maps, QwtPlotPrintFilter());
00542 }
00543
00552 void QwtPlot::drawItems(QPainter *painter, const QRect &rect,
00553 const QwtScaleMap map[axisCnt],
00554 const QwtPlotPrintFilter &pfilter) const
00555 {
00556 const QwtPlotItemList& itmList = itemList();
00557 for ( QwtPlotItemIterator it = itmList.begin();
00558 it != itmList.end(); ++it )
00559 {
00560 QwtPlotItem *item = *it;
00561 if ( item && item->isVisible() )
00562 {
00563 if ( !(pfilter.options() & QwtPlotPrintFilter::PrintGrid)
00564 && item->rtti() == QwtPlotItem::Rtti_PlotGrid )
00565 {
00566 continue;
00567 }
00568
00569 painter->save();
00570
00571 #if QT_VERSION >= 0x040000
00572 painter->setRenderHint(QPainter::Antialiasing,
00573 item->testRenderHint(QwtPlotItem::RenderAntialiased) );
00574 #endif
00575
00576 item->draw(painter,
00577 map[item->xAxis()], map[item->yAxis()],
00578 rect);
00579
00580 painter->restore();
00581 }
00582 }
00583 }
00584
00592 QwtScaleMap QwtPlot::canvasMap(int axisId) const
00593 {
00594 QwtScaleMap map;
00595 if ( !d_data->canvas )
00596 return map;
00597
00598 map.setTransformation(axisScaleEngine(axisId)->transformation());
00599
00600 const QwtScaleDiv *sd = axisScaleDiv(axisId);
00601 map.setScaleInterval(sd->lowerBound(), sd->upperBound());
00602
00603 if ( axisEnabled(axisId) )
00604 {
00605 const QwtScaleWidget *s = axisWidget(axisId);
00606 if ( axisId == yLeft || axisId == yRight )
00607 {
00608 int y = s->y() + s->startBorderDist() - d_data->canvas->y();
00609 int h = s->height() - s->startBorderDist() - s->endBorderDist();
00610 map.setPaintInterval(y + h, y);
00611 }
00612 else
00613 {
00614 int x = s->x() + s->startBorderDist() - d_data->canvas->x();
00615 int w = s->width() - s->startBorderDist() - s->endBorderDist();
00616 map.setPaintInterval(x, x + w);
00617 }
00618 }
00619 else
00620 {
00621 const int margin = plotLayout()->canvasMargin(axisId);
00622
00623 const QRect &canvasRect = d_data->canvas->contentsRect();
00624 if ( axisId == yLeft || axisId == yRight )
00625 {
00626 map.setPaintInterval(canvasRect.bottom() - margin,
00627 canvasRect.top() + margin);
00628 }
00629 else
00630 {
00631 map.setPaintInterval(canvasRect.left() + margin,
00632 canvasRect.right() - margin);
00633 }
00634 }
00635 return map;
00636 }
00637
00645 void QwtPlot::setMargin(int margin)
00646 {
00647 if ( margin < 0 )
00648 margin = 0;
00649
00650 if ( margin != d_data->layout->margin() )
00651 {
00652 d_data->layout->setMargin(margin);
00653 updateLayout();
00654 }
00655 }
00656
00661 int QwtPlot::margin() const
00662 {
00663 return d_data->layout->margin();
00664 }
00665
00674 void QwtPlot::setCanvasBackground(const QColor &c)
00675 {
00676 QPalette p = d_data->canvas->palette();
00677
00678 for ( int i = 0; i < QPalette::NColorGroups; i++ )
00679 {
00680 #if QT_VERSION < 0x040000
00681 p.setColor((QPalette::ColorGroup)i, QColorGroup::Background, c);
00682 #else
00683 p.setColor((QPalette::ColorGroup)i, QPalette::Background, c);
00684 #endif
00685 }
00686
00687 canvas()->setPalette(p);
00688 }
00689
00696 const QColor & QwtPlot::canvasBackground() const
00697 {
00698 #if QT_VERSION < 0x040000
00699 return canvas()->palette().color(
00700 QPalette::Normal, QColorGroup::Background);
00701 #else
00702 return canvas()->palette().color(
00703 QPalette::Normal, QPalette::Background);
00704 #endif
00705 }
00706
00713 void QwtPlot::setCanvasLineWidth(int w)
00714 {
00715 canvas()->setLineWidth(w);
00716 updateLayout();
00717 }
00718
00724 int QwtPlot::canvasLineWidth() const
00725 {
00726 return canvas()->lineWidth();
00727 }
00728
00733 bool QwtPlot::axisValid(int axisId)
00734 {
00735 return ((axisId >= QwtPlot::yLeft) && (axisId < QwtPlot::axisCnt));
00736 }
00737
00742 void QwtPlot::legendItemClicked()
00743 {
00744 if ( d_data->legend && sender()->isWidgetType() )
00745 {
00746 QwtPlotItem *plotItem =
00747 (QwtPlotItem*)d_data->legend->find((QWidget *)sender());
00748 if ( plotItem )
00749 emit legendClicked(plotItem);
00750 }
00751 }
00752
00757 void QwtPlot::legendItemChecked(bool on)
00758 {
00759 if ( d_data->legend && sender()->isWidgetType() )
00760 {
00761 QwtPlotItem *plotItem =
00762 (QwtPlotItem*)d_data->legend->find((QWidget *)sender());
00763 if ( plotItem )
00764 emit legendChecked(plotItem, on);
00765 }
00766 }
00767
00772 void QwtPlot::clear()
00773 {
00774 detachItems(QwtPlotItem::Rtti_PlotCurve);
00775 detachItems(QwtPlotItem::Rtti_PlotMarker);
00776 }
00777
00805 void QwtPlot::insertLegend(QwtLegend *legend,
00806 QwtPlot::LegendPosition pos, double ratio)
00807 {
00808 d_data->layout->setLegendPosition(pos, ratio);
00809
00810 if ( legend != d_data->legend )
00811 {
00812 if ( d_data->legend && d_data->legend->parent() == this )
00813 delete d_data->legend;
00814
00815 d_data->legend = legend;
00816
00817 if ( d_data->legend )
00818 {
00819 if ( pos != ExternalLegend )
00820 {
00821 if ( d_data->legend->parent() != this )
00822 {
00823 #if QT_VERSION < 0x040000
00824 d_data->legend->reparent(this, QPoint(0, 0));
00825 #else
00826 d_data->legend->setParent(this);
00827 #endif
00828 }
00829 }
00830
00831 const QwtPlotItemList& itmList = itemList();
00832 for ( QwtPlotItemIterator it = itmList.begin();
00833 it != itmList.end(); ++it )
00834 {
00835 (*it)->updateLegend(d_data->legend);
00836 }
00837
00838 QLayout *l = d_data->legend->contentsWidget()->layout();
00839 if ( l && l->inherits("QwtDynGridLayout") )
00840 {
00841 QwtDynGridLayout *tl = (QwtDynGridLayout *)l;
00842 switch(d_data->layout->legendPosition())
00843 {
00844 case LeftLegend:
00845 case RightLegend:
00846 tl->setMaxCols(1);
00847 break;
00848 case TopLegend:
00849 case BottomLegend:
00850 tl->setMaxCols(0);
00851 break;
00852 case ExternalLegend:
00853 break;
00854 }
00855 }
00856 }
00857 updateTabOrder();
00858 }
00859
00860 updateLayout();
00861 }