00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <qpainter.h>
00011 #if QT_VERSION < 0x040000
00012 #include <qfocusdata.h>
00013 #else
00014 #include <qpaintengine.h>
00015 #endif
00016 #include <qapplication.h>
00017 #include <qevent.h>
00018 #include "qwt_plot.h"
00019 #include "qwt_plot_dict.h"
00020 #include "qwt_plot_layout.h"
00021 #include "qwt_rect.h"
00022 #include "qwt_scale_widget.h"
00023 #include "qwt_scale_engine.h"
00024 #include "qwt_text_label.h"
00025 #include "qwt_legend.h"
00026 #include "qwt_dyngrid_layout.h"
00027 #include "qwt_plot_canvas.h"
00028 #include "qwt_paint_buffer.h"
00029
00030 class QwtPlot::PrivateData
00031 {
00032 public:
00033 QwtTextLabel *lblTitle;
00034 QwtPlotCanvas *canvas;
00035 QwtLegend *legend;
00036 QwtPlotLayout *layout;
00037
00038 bool autoReplot;
00039 };
00040
00046 QwtPlot::QwtPlot(QWidget *parent):
00047 QFrame(parent)
00048 {
00049 initPlot(QwtText());
00050 }
00051
00052
00058 QwtPlot::QwtPlot(const QwtText &title, QWidget *parent) :
00059 QFrame(parent)
00060 {
00061 initPlot(title);
00062 }
00063
00065 QwtPlot::~QwtPlot()
00066 {
00067 detachItems(QwtPlotItem::Rtti_PlotItem, autoDelete());
00068
00069 delete d_data->layout;
00070 deleteAxesData();
00071 delete d_data;
00072 }
00073
00078 void QwtPlot::initPlot(const QwtText &title)
00079 {
00080 d_data = new PrivateData;
00081
00082 #if QT_VERSION < 0x040000
00083 setWFlags(Qt::WNoAutoErase);
00084 #endif
00085
00086 d_data->layout = new QwtPlotLayout;
00087
00088 d_data->autoReplot = false;
00089
00090 d_data->lblTitle = new QwtTextLabel(title, this);
00091 d_data->lblTitle->setFont(QFont(fontInfo().family(), 14, QFont::Bold));
00092
00093 QwtText text(title);
00094 int flags = Qt::AlignCenter;
00095 #if QT_VERSION < 0x040000
00096 flags |= Qt::WordBreak | Qt::ExpandTabs;
00097 #else
00098 flags |= Qt::TextWordWrap;
00099 #endif
00100 text.setFlags(flags);
00101 d_data->lblTitle->setText(text);
00102
00103 d_data->legend = NULL;
00104
00105 initAxesData();
00106
00107 d_data->canvas = new QwtPlotCanvas(this);
00108 d_data->canvas->setFrameStyle(QFrame::Panel|QFrame::Sunken);
00109 d_data->canvas->setLineWidth(2);
00110 d_data->canvas->setMidLineWidth(0);
00111
00112 updateTabOrder();
00113
00114 setSizePolicy(QSizePolicy::MinimumExpanding,
00115 QSizePolicy::MinimumExpanding);
00116 }
00117
00121 bool QwtPlot::event(QEvent *e)
00122 {
00123 bool ok = QFrame::event(e);
00124 switch(e->type())
00125 {
00126 #if QT_VERSION < 0x040000
00127 case QEvent::LayoutHint:
00128 #else
00129 case QEvent::LayoutRequest:
00130 #endif
00131 updateLayout();
00132 break;
00133 #if QT_VERSION >= 0x040000
00134 case QEvent::PolishRequest:
00135 polish();
00136 break;
00137 #endif
00138 default:;
00139 }
00140 return ok;
00141 }
00142
00147 void QwtPlot::autoRefresh()
00148 {
00149 if (d_data->autoReplot)
00150 replot();
00151 }
00152
00167 void QwtPlot::setAutoReplot(bool tf)
00168 {
00169 d_data->autoReplot = tf;
00170 }
00171
00175 bool QwtPlot::autoReplot() const
00176 {
00177 return d_data->autoReplot;
00178 }
00179
00184 void QwtPlot::setTitle(const QString &t)
00185 {
00186 d_data->lblTitle->setText(t);
00187 }
00188
00193 void QwtPlot::setTitle(const QwtText &t)
00194 {
00195 d_data->lblTitle->setText(t);
00196 }
00197
00202 QwtText QwtPlot::title() const
00203 {
00204 return d_data->lblTitle->text();
00205 }
00206
00210 QwtPlotLayout *QwtPlot::plotLayout()
00211 {
00212 return d_data->layout;
00213 }
00214
00218 const QwtPlotLayout *QwtPlot::plotLayout() const
00219 {
00220 return d_data->layout;
00221 }
00222
00226 QwtTextLabel *QwtPlot::titleLabel()
00227 {
00228 return d_data->lblTitle;
00229 }
00230
00234 const QwtTextLabel *QwtPlot::titleLabel() const
00235 {
00236 return d_data->lblTitle;
00237 }
00238
00243 QwtLegend *QwtPlot::legend()
00244 {
00245 return d_data->legend;
00246 }
00247
00252 const QwtLegend *QwtPlot::legend() const
00253 {
00254 return d_data->legend;
00255 }
00256
00257
00261 QwtPlotCanvas *QwtPlot::canvas()
00262 {
00263 return d_data->canvas;
00264 }
00265
00269 const QwtPlotCanvas *QwtPlot::canvas() const
00270 {
00271 return d_data->canvas;
00272 }
00273
00274 void QwtPlot::polish()
00275 {
00276 replot();
00277
00278 #if QT_VERSION < 0x040000
00279 QFrame::polish();
00280 #endif
00281 }
00282
00288 QSize QwtPlot::sizeHint() const
00289 {
00290 int dw = 0;
00291 int dh = 0;
00292 for ( int axisId = 0; axisId < axisCnt; axisId++ )
00293 {
00294 if ( axisEnabled(axisId) )
00295 {
00296 const int niceDist = 40;
00297 const QwtScaleWidget *scaleWidget = axisWidget(axisId);
00298 const QwtScaleDiv &scaleDiv = scaleWidget->scaleDraw()->scaleDiv();
00299 const int majCnt = scaleDiv.ticks(QwtScaleDiv::MajorTick).count();
00300
00301 if ( axisId == yLeft || axisId == yRight )
00302 {
00303 int hDiff = (majCnt - 1) * niceDist
00304 - scaleWidget->minimumSizeHint().height();
00305 if ( hDiff > dh )
00306 dh = hDiff;
00307 }
00308 else
00309 {
00310 int wDiff = (majCnt - 1) * niceDist
00311 - scaleWidget->minimumSizeHint().width();
00312 if ( wDiff > dw )
00313 dw = wDiff;
00314 }
00315 }
00316 }
00317 return minimumSizeHint() + QSize(dw, dh);
00318 }
00319
00323 QSize QwtPlot::minimumSizeHint() const
00324 {
00325 QSize hint = d_data->layout->minimumSizeHint(this);
00326 hint += QSize(2 * frameWidth(), 2 * frameWidth());
00327
00328 return hint;
00329 }
00330
00332 void QwtPlot::resizeEvent(QResizeEvent *e)
00333 {
00334 QFrame::resizeEvent(e);
00335 updateLayout();
00336 }
00337
00348 void QwtPlot::replot()
00349 {
00350 bool doAutoReplot = autoReplot();
00351 setAutoReplot(false);
00352
00353 updateAxes();
00354
00355
00356
00357
00358
00359
00360 #if QT_VERSION >= 0x040000
00361 QApplication::sendPostedEvents(this, QEvent::LayoutRequest);
00362 #else
00363 QApplication::sendPostedEvents(this, QEvent::LayoutHint);
00364 #endif
00365
00366 QwtPlotCanvas &canvas = *d_data->canvas;
00367
00368 canvas.invalidatePaintCache();
00369
00370
00371
00372
00373
00374 const bool erase =
00375 !canvas.testPaintAttribute(QwtPlotCanvas::PaintPacked)
00376 && !canvas.testPaintAttribute(QwtPlotCanvas::PaintCached);
00377
00378 #if QT_VERSION >= 0x040000
00379 const bool noBackgroundMode = canvas.testAttribute(Qt::WA_NoBackground);
00380 if ( !erase && !noBackgroundMode )
00381 canvas.setAttribute(Qt::WA_NoBackground, true);
00382
00383 canvas.repaint(canvas.contentsRect());
00384
00385 if ( !erase && !noBackgroundMode )
00386 canvas.setAttribute(Qt::WA_NoBackground, false);
00387 #else
00388 canvas.repaint(canvas.contentsRect(), erase);
00389 #endif
00390
00391 setAutoReplot(doAutoReplot);
00392 }
00393
00398 void QwtPlot::updateLayout()
00399 {
00400 d_data->layout->activate(this, contentsRect());
00401
00402
00403
00404
00405 if (!d_data->lblTitle->text().isEmpty())
00406 {
00407 d_data->lblTitle->setGeometry(d_data->layout->titleRect());
00408 if (!d_data->lblTitle->isVisible())
00409 d_data->lblTitle->show();
00410 }
00411 else
00412 d_data->lblTitle->hide();
00413
00414 for (int axisId = 0; axisId < axisCnt; axisId++ )
00415 {
00416 if (axisEnabled(axisId) )
00417 {
00418 axisWidget(axisId)->setGeometry(d_data->layout->scaleRect(axisId));
00419
00420 if ( axisId == xBottom || axisId == xTop )
00421 {
00422 QRegion r(d_data->layout->scaleRect(axisId));
00423 if ( axisEnabled(yLeft) )
00424 r = r.subtract(QRegion(d_data->layout->scaleRect(yLeft)));
00425 if ( axisEnabled(yRight) )
00426 r = r.subtract(QRegion(d_data->layout->scaleRect(yRight)));
00427 r.translate(-d_data->layout->scaleRect(axisId).x(),
00428 -d_data->layout->scaleRect(axisId).y());
00429
00430 axisWidget(axisId)->setMask(r);
00431 }
00432 if (!axisWidget(axisId)->isVisible())
00433 axisWidget(axisId)->show();
00434 }
00435 else
00436 axisWidget(axisId)->hide();
00437 }
00438
00439 if ( d_data->legend )
00440 {
00441 if (d_data->legend->itemCount() > 0)
00442 {
00443 d_data->legend->setGeometry(d_data->layout->legendRect());
00444 d_data->legend->show();
00445 }
00446 else
00447 d_data->legend->hide();
00448 }
00449
00450 d_data->canvas->setGeometry(d_data->layout->canvasRect());
00451 }
00452
00454
00455 void QwtPlot::updateTabOrder()
00456 {
00457 #if QT_VERSION >= 0x040000
00458 using namespace Qt;
00459 #endif
00460 if ( !legend() || legend()->legendItems().count() == 0
00461 || d_data->canvas->focusPolicy() == NoFocus )
00462 {
00463 return;
00464 }
00465
00466
00467
00468
00469
00470
00471 const bool canvasFirst =
00472 d_data->layout->legendPosition() == QwtPlot::BottomLegend ||
00473 d_data->layout->legendPosition() == QwtPlot::RightLegend;
00474
00475 QWidget *previous = NULL;
00476
00477 QWidget *w;
00478 #if QT_VERSION >= 0x040000
00479 while ( nextInFocusChain() != d_data->canvas );
00480 while ( (w = nextInFocusChain()) != d_data->canvas )
00481 #else
00482 if ( focusData() == NULL )
00483 return;
00484
00485 while ( focusData()->next() != d_data->canvas );
00486 while ( (w = focusData()->next()) != d_data->canvas )
00487 #endif
00488 {
00489 bool isLegendItem = false;
00490 if ( w->focusPolicy() != NoFocus
00491 && w->parent() && w->parent() == d_data->legend->contentsWidget() )
00492 {
00493 isLegendItem = true;
00494 }
00495
00496 if ( canvasFirst )
00497 {
00498 if ( isLegendItem )
00499 break;
00500
00501 previous = w;
00502 }
00503 else
00504 {
00505 if ( isLegendItem )
00506 previous = w;
00507 else
00508 {
00509 if ( previous )
00510 break;
00511 }
00512 }
00513 }
00514
00515 if ( previous && previous != d_data->canvas)
00516 setTabOrder(previous, d_data->canvas);
00517 }
00518
00529 void QwtPlot::drawCanvas(QPainter *painter)
00530 {
00531 QwtArray<QwtScaleMap> maps(axisCnt);
00532 for ( int axisId = 0; axisId < axisCnt; axisId++ )
00533 maps[axisId] = canvasMap(axisId);
00534
00535 drawItems(painter,
00536 d_data->canvas->contentsRect(), maps, QwtPlotPrintFilter());
00537 }
00538
00547 void QwtPlot::drawItems(QPainter *painter, const QRect &rect,
00548 const QwtArray<QwtScaleMap> &map,
00549 const QwtPlotPrintFilter &pfilter) const
00550 {
00551 painter->save();
00552
00553 const QwtPlotItemList& itmList = itemList();
00554 for ( QwtPlotItemIterator it = itmList.begin();
00555 it != itmList.end(); ++it )
00556 {
00557 QwtPlotItem *item = *it;
00558 if ( item && item->isVisible() )
00559 {
00560 if ( !(pfilter.options() & QwtPlotPrintFilter::PrintGrid)
00561 && item->rtti() == QwtPlotItem::Rtti_PlotGrid )
00562 {
00563 continue;
00564 }
00565
00566 #if QT_VERSION >= 0x040000
00567 const QPaintEngine *pe = painter->device()->paintEngine();
00568 if (pe->hasFeature(QPaintEngine::Antialiasing) )
00569 {
00570 painter->setRenderHint(QPainter::Antialiasing,
00571 item->testRenderHint(QwtPlotItem::RenderAntialiased) );
00572 }
00573 #endif
00574
00575 item->draw(painter,
00576 map[item->xAxis()], map[item->yAxis()],
00577 rect);
00578 }
00579 }
00580
00581 painter->restore();
00582 }
00583
00591 QwtScaleMap QwtPlot::canvasMap(int axisId) const
00592 {
00593 QwtScaleMap map;
00594 if ( !d_data->canvas )
00595 return map;
00596
00597 map.setTransformation(axisScaleEngine(axisId)->transformation());
00598
00599 const QwtScaleDiv *sd = axisScaleDiv(axisId);
00600 map.setScaleInterval(sd->lBound(), sd->hBound());
00601
00602 if ( axisEnabled(axisId) )
00603 {
00604 const QwtScaleWidget *s = axisWidget(axisId);
00605 if ( axisId == yLeft || axisId == yRight )
00606 {
00607 int y = s->y() + s->startBorderDist() - d_data->canvas->y();
00608 int h = s->height() - s->startBorderDist() - s->endBorderDist();
00609 map.setPaintInterval(y + h - 1, y);
00610 }
00611 else
00612 {
00613 int x = s->x() + s->startBorderDist() - d_data->canvas->x();
00614 int w = s->width() - s->startBorderDist() - s->endBorderDist();
00615 map.setPaintInterval(x, x + w - 1);
00616 }
00617 }
00618 else
00619 {
00620 const int margin = plotLayout()->canvasMargin(axisId);
00621
00622 const QRect &canvasRect = d_data->canvas->contentsRect();
00623 if ( axisId == yLeft || axisId == yRight )
00624 {
00625 map.setPaintInterval(canvasRect.bottom() - margin,
00626 canvasRect.top() + margin);
00627 }
00628 else
00629 {
00630 map.setPaintInterval(canvasRect.left() + margin,
00631 canvasRect.right() - margin);
00632 }
00633 }
00634 return map;
00635 }
00636
00644 void QwtPlot::setMargin(int margin)
00645 {
00646 if ( margin < 0 )
00647 margin = 0;
00648
00649 if ( margin != d_data->layout->margin() )
00650 {
00651 d_data->layout->setMargin(margin);
00652 updateLayout();
00653 }
00654 }
00655
00660 int QwtPlot::margin() const
00661 {
00662 return d_data->layout->margin();
00663 }
00664
00673 void QwtPlot::setCanvasBackground(const QColor &c)
00674 {
00675 QPalette p = d_data->canvas->palette();
00676
00677 for ( int i = 0; i < QPalette::NColorGroups; i++ )
00678 {
00679 #if QT_VERSION < 0x040000
00680 p.setColor((QPalette::ColorGroup)i, QColorGroup::Background, c);
00681 #else
00682 p.setColor((QPalette::ColorGroup)i, QPalette::Background, c);
00683 #endif
00684 }
00685
00686 canvas()->setPalette(p);
00687 }
00688
00695 const QColor & QwtPlot::canvasBackground() const
00696 {
00697 #if QT_VERSION < 0x040000
00698 return canvas()->palette().color(
00699 QPalette::Normal, QColorGroup::Background);
00700 #else
00701 return canvas()->palette().color(
00702 QPalette::Normal, QPalette::Background);
00703 #endif
00704 }
00705
00712 void QwtPlot::setCanvasLineWidth(int w)
00713 {
00714 canvas()->setLineWidth(w);
00715 }
00716
00722 int QwtPlot::canvasLineWidth() const
00723 {
00724 return canvas()->lineWidth();
00725 }
00726
00731 bool QwtPlot::axisValid(int axisId)
00732 {
00733 return ((axisId >= QwtPlot::yLeft) && (axisId < QwtPlot::axisCnt));
00734 }
00735
00741 void QwtPlot::legendItemClicked()
00742 {
00743 if ( d_data->legend && sender()->isWidgetType() )
00744 {
00745 QwtPlotItem *plotItem = d_data->legend->find((QWidget *)sender());
00746 if ( plotItem )
00747 emit legendClicked(plotItem);
00748 }
00749 }
00750
00751 void QwtPlot::legendItemChecked(bool on)
00752 {
00753 if ( d_data->legend && sender()->isWidgetType() )
00754 {
00755 QwtPlotItem *plotItem = d_data->legend->find((QWidget *)sender());
00756 if ( plotItem )
00757 emit legendChecked(plotItem, on);
00758 }
00759 }
00760
00762 void QwtPlot::clear()
00763 {
00764 detachItems(QwtPlotItem::Rtti_PlotCurve);
00765 detachItems(QwtPlotItem::Rtti_PlotMarker);
00766 }
00767
00794 void QwtPlot::insertLegend(QwtLegend *legend,
00795 QwtPlot::LegendPosition pos, double ratio)
00796 {
00797 d_data->layout->setLegendPosition(pos, ratio);
00798
00799 if ( legend != d_data->legend )
00800 {
00801 delete d_data->legend;
00802 d_data->legend = legend;
00803
00804 if ( d_data->legend )
00805 {
00806 if ( d_data->legend->parent() != this )
00807 {
00808 #if QT_VERSION < 0x040000
00809 d_data->legend->reparent(this, QPoint(0, 0));
00810 #else
00811 d_data->legend->setParent(this);
00812 #endif
00813 }
00814
00815 const QwtPlotItemList& itmList = itemList();
00816 for ( QwtPlotItemIterator it = itmList.begin();
00817 it != itmList.end(); ++it )
00818 {
00819 (*it)->updateLegend(d_data->legend);
00820 }
00821
00822 QLayout *l = d_data->legend->contentsWidget()->layout();
00823 if ( l && l->inherits("QwtDynGridLayout") )
00824 {
00825 QwtDynGridLayout *tl = (QwtDynGridLayout *)l;
00826 if ( d_data->layout->legendPosition() == QwtPlot::TopLegend ||
00827 d_data->layout->legendPosition() == QwtPlot::BottomLegend )
00828 {
00829 tl->setMaxCols(0);
00830 }
00831 else
00832 tl->setMaxCols(1);
00833 }
00834 }
00835 updateTabOrder();
00836 }
00837
00838 updateLayout();
00839 }