00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <qlabel.h>
00011 #include <qpainter.h>
00012 #if QT_VERSION < 0x040000
00013 #include <qfocusdata.h>
00014 #else
00015 #include <qpaintengine.h>
00016 #endif
00017 #include <qapplication.h>
00018 #include <qevent.h>
00019 #include "qwt_plot.h"
00020 #include "qwt_plot_dict.h"
00021 #include "qwt_plot_layout.h"
00022 #include "qwt_rect.h"
00023 #include "qwt_scale_widget.h"
00024 #include "qwt_scale_engine.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 QLabel *lblTitle;
00034 QwtPlotCanvas *canvas;
00035 QwtLegend *legend;
00036 QwtPlotLayout *layout;
00037
00038 bool autoReplot;
00039 };
00040
00047 QwtPlot::QwtPlot(QWidget *parent):
00048 QFrame(parent)
00049 {
00050 initPlot();
00051 }
00052
00053
00060 QwtPlot::QwtPlot(const QString &title, QWidget *parent) :
00061 QFrame(parent)
00062 {
00063 initPlot(title);
00064 }
00065
00067 QwtPlot::~QwtPlot()
00068 {
00069 detachItems(QwtPlotItem::Rtti_PlotItem, autoDelete());
00070
00071 delete d_data->layout;
00072 deleteAxesData();
00073 delete d_data;
00074 }
00075
00080 void QwtPlot::initPlot(const QString &title)
00081 {
00082 d_data = new PrivateData;
00083
00084 #if QT_VERSION < 0x040000
00085 setWFlags(Qt::WNoAutoErase);
00086 #endif
00087
00088 d_data->layout = new QwtPlotLayout;
00089
00090 d_data->autoReplot = false;
00091
00092 d_data->lblTitle = new QLabel(title, this);
00093 d_data->lblTitle->setFont(QFont(fontInfo().family(), 14, QFont::Bold));
00094
00095 #if QT_VERSION < 0x040000
00096 d_data->lblTitle->setAlignment(
00097 Qt::AlignCenter | Qt::WordBreak | Qt::ExpandTabs);
00098 #else
00099
00100
00101 d_data->lblTitle->setAlignment(Qt::AlignCenter);
00102 d_data->lblTitle->setWordWrap(true);
00103 #endif
00104
00105 d_data->legend = NULL;
00106
00107 initAxesData();
00108
00109 d_data->canvas = new QwtPlotCanvas(this);
00110 d_data->canvas->setFrameStyle(QFrame::Panel|QFrame::Sunken);
00111 d_data->canvas->setLineWidth(2);
00112 d_data->canvas->setMidLineWidth(0);
00113
00114 updateTabOrder();
00115
00116 setSizePolicy(QSizePolicy::MinimumExpanding,
00117 QSizePolicy::MinimumExpanding);
00118 }
00119
00123 bool QwtPlot::event(QEvent *e)
00124 {
00125 bool ok = QFrame::event(e);
00126 switch(e->type())
00127 {
00128 #if QT_VERSION < 0x040000
00129 case QEvent::LayoutHint:
00130 #else
00131 case QEvent::LayoutRequest:
00132 #endif
00133 updateLayout();
00134 break;
00135 #if QT_VERSION >= 0x040000
00136 case QEvent::PolishRequest:
00137 polish();
00138 break;
00139 #endif
00140 default:;
00141 }
00142 return ok;
00143 }
00144
00149 void QwtPlot::autoRefresh()
00150 {
00151 if (d_data->autoReplot)
00152 replot();
00153 }
00154
00169 void QwtPlot::setAutoReplot(bool tf)
00170 {
00171 d_data->autoReplot = tf;
00172 }
00173
00177 bool QwtPlot::autoReplot() const
00178 {
00179 return d_data->autoReplot;
00180 }
00181
00186 void QwtPlot::setTitle(const QString &t)
00187 {
00188 d_data->lblTitle->setText(t);
00189 }
00190
00195 QString QwtPlot::title() const
00196 {
00197 return d_data->lblTitle->text();
00198 }
00199
00200
00205 void QwtPlot::setTitleFont(const QFont &f)
00206 {
00207 d_data->lblTitle->setFont(f);
00208 }
00209
00213 QFont QwtPlot::titleFont() const
00214 {
00215 return d_data->lblTitle->font();
00216 }
00217
00221 QwtPlotLayout *QwtPlot::plotLayout()
00222 {
00223 return d_data->layout;
00224 }
00225
00229 const QwtPlotLayout *QwtPlot::plotLayout() const
00230 {
00231 return d_data->layout;
00232 }
00233
00237 QLabel *QwtPlot::titleLabel()
00238 {
00239 return d_data->lblTitle;
00240 }
00241
00245 const QLabel *QwtPlot::titleLabel() const
00246 {
00247 return d_data->lblTitle;
00248 }
00249
00254 QwtLegend *QwtPlot::legend()
00255 {
00256 return d_data->legend;
00257 }
00258
00263 const QwtLegend *QwtPlot::legend() const
00264 {
00265 return d_data->legend;
00266 }
00267
00268
00272 QwtPlotCanvas *QwtPlot::canvas()
00273 {
00274 return d_data->canvas;
00275 }
00276
00280 const QwtPlotCanvas *QwtPlot::canvas() const
00281 {
00282 return d_data->canvas;
00283 }
00284
00285 void QwtPlot::polish()
00286 {
00287 replot();
00288
00289 #if QT_VERSION < 0x040000
00290 QFrame::polish();
00291 #endif
00292 }
00293
00299 QSize QwtPlot::sizeHint() const
00300 {
00301 int dw = 0;
00302 int dh = 0;
00303 for ( int axisId = 0; axisId < axisCnt; axisId++ )
00304 {
00305 if ( axisEnabled(axisId) )
00306 {
00307 const int niceDist = 40;
00308 const QwtScaleWidget *scaleWidget = axisWidget(axisId);
00309 const QwtScaleDiv &scaleDiv = scaleWidget->scaleDraw()->scaleDiv();
00310 const int majCnt = scaleDiv.ticks(QwtScaleDiv::MajorTick).count();
00311
00312 if ( axisId == yLeft || axisId == yRight )
00313 {
00314 int hDiff = (majCnt - 1) * niceDist
00315 - scaleWidget->minimumSizeHint().height();
00316 if ( hDiff > dh )
00317 dh = hDiff;
00318 }
00319 else
00320 {
00321 int wDiff = (majCnt - 1) * niceDist
00322 - scaleWidget->minimumSizeHint().width();
00323 if ( wDiff > dw )
00324 dw = wDiff;
00325 }
00326 }
00327 }
00328 return minimumSizeHint() + QSize(dw, dh);
00329 }
00330
00334 QSize QwtPlot::minimumSizeHint() const
00335 {
00336 QSize hint = d_data->layout->minimumSizeHint(this);
00337 hint += QSize(2 * frameWidth(), 2 * frameWidth());
00338
00339 return hint;
00340 }
00341
00343 void QwtPlot::resizeEvent(QResizeEvent *e)
00344 {
00345 QFrame::resizeEvent(e);
00346 updateLayout();
00347 }
00348
00359 void QwtPlot::replot()
00360 {
00361 bool doAutoReplot = autoReplot();
00362 setAutoReplot(false);
00363
00364 updateAxes();
00365
00366 QwtPlotCanvas &canvas = *d_data->canvas;
00367
00368 canvas.invalidateCache();
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
00786 void QwtPlot::insertLegend(QwtLegend *legend,
00787 QwtPlot::LegendPosition pos, double ratio)
00788 {
00789 d_data->layout->setLegendPosition(pos, ratio);
00790
00791 if ( legend != d_data->legend )
00792 {
00793 delete d_data->legend;
00794 d_data->legend = legend;
00795
00796 if ( d_data->legend )
00797 {
00798 if ( d_data->legend->parent() != this )
00799 {
00800 #if QT_VERSION < 0x040000
00801 d_data->legend->reparent(this, QPoint(0, 0));
00802 #else
00803 d_data->legend->setParent(this);
00804 #endif
00805 }
00806
00807 const QwtPlotItemList& itmList = itemList();
00808 for ( QwtPlotItemIterator it = itmList.begin();
00809 it != itmList.end(); ++it )
00810 {
00811 (*it)->updateLegend(d_data->legend);
00812 }
00813
00814 QLayout *l = d_data->legend->contentsWidget()->layout();
00815 if ( l && l->inherits("QwtDynGridLayout") )
00816 {
00817 QwtDynGridLayout *tl = (QwtDynGridLayout *)l;
00818 if ( d_data->layout->legendPosition() == QwtPlot::TopLegend ||
00819 d_data->layout->legendPosition() == QwtPlot::BottomLegend )
00820 {
00821 tl->setMaxCols(0);
00822 }
00823 else
00824 tl->setMaxCols(1);
00825 }
00826 }
00827 updateTabOrder();
00828 }
00829
00830 updateLayout();
00831 }