Changeset 204


Ignore:
Timestamp:
05/03/10 17:37:03 (15 years ago)
Author:
ogrimm
Message:
Improved zooming of plots
Location:
Evidence/Edd
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • Evidence/Edd/Edd.cc

    r174 r204  
    99a DIM status service
    1010
    11 February 2010, Oliver Grimm
     11April 2010, Oliver Grimm
    1212
    1313============================================================ */
     
    195195  setAttribute(Qt::WA_DeleteOnClose);
    196196  setAutoReplot(false);
    197   setCanvasBackground(QColor(Qt::yellow));
    198   setAxisScaleDraw(QwtPlot::xBottom, new TimeScale());
     197  setCanvasBackground(EddPlotBackgroundColor);
     198  setAxisScaleDraw(QwtPlot::xBottom, new EddTimeScale);
     199  setMargin(15);
     200
     201  // Update additional information (e.g. time range) on widget when axis change
     202  connect(axisWidget(QwtPlot::xBottom), SIGNAL(scaleDivChanged()), SLOT(update()));
     203
     204  Picker = new QwtPicker(QwtPicker::CornerToCorner|QwtPicker::RectSelection, QwtPicker::RectRubberBand, QwtPicker::AlwaysOff, this);
     205  connect(Picker, SIGNAL(selected(const QwtPolygon &)), SLOT(MouseSelection(const QwtPolygon &)));
    199206
    200207  Zoomer = new QwtPlotZoomer(QwtPlot::xBottom,QwtPlot::yLeft,canvas());
    201208  connect(Zoomer, SIGNAL(zoomed(const QwtDoubleRect &)), this, SLOT(HandleZoom(const QwtDoubleRect &)));
     209
     210  Magnifier = new QwtPlotMagnifier(canvas());
     211  Magnifier->setMouseButton(Qt::NoButton,Qt::NoButton);
     212  Magnifier->setZoomInKey(Qt::Key_M, Qt::NoModifier);
     213  Magnifier->setZoomOutKey(Qt::Key_M, Qt::ShiftModifier);
     214
    202215  Panner = new QwtPlotPanner(canvas());
    203216  Panner->setMouseButton(Qt::LeftButton, Qt::ShiftModifier);
     217
    204218  Grid = new QwtPlotGrid;
    205219  Grid->setMajPen(QPen(Qt::gray, 0, Qt::DotLine));
    206220  Grid->attach(this);
     221
    207222  Legend = new QwtLegend();
    208223  Legend->setItemMode(QwtLegend::ClickableItem);
    209   insertLegend(Legend, QwtPlot::TopLegend);
    210 
     224  insertLegend(Legend, QwtPlot::TopLegend, 0.3);
    211225  connect(this, SIGNAL(legendClicked (QwtPlotItem *)), SLOT(LegendClicked(QwtPlotItem *)));
    212226 
     
    218232  // Context menu
    219233  Menu = new QMenu(this);
     234  StripAction = Menu->addAction("Stripchart", this, SLOT(UpdatePlot()));
     235  StripAction->setCheckable(true);
     236  Menu->addSeparator();
    220237  YLogAction = Menu->addAction("y scale log", this, SLOT(UpdatePlot()));
    221238  YLogAction->setCheckable(true);
     
    232249  Menu->addSeparator();
    233250  Menu->addAction("Paste service", this, SLOT(MenuPasteService()));
     251  Menu->addAction("Plot help", this, SLOT(MenuPlotHelp()));
    234252
    235253  // DIM client
     
    245263    Handler->Unsubscribe(Items[i].Name);
    246264    delete Items[i].Signal;
    247   } 
     265  }
     266
    248267  delete Grid;
    249268  delete Mutex;
     
    363382void EddPlot::UpdatePlot() {
    364383
     384  double Lower = axisScaleDiv(QwtPlot::xBottom)->lowerBound();
     385  double Upper = axisScaleDiv(QwtPlot::xBottom)->upperBound();
     386  double MaxTime = DBL_MIN;
    365387  static QwtSymbol Symbol, Sym1;
    366388  Symbol.setStyle(QwtSymbol::Ellipse);
    367389  Symbol.setSize(4);
    368390
     391  // Select engine for linear or logarithmic scale
    369392  if (!YLogAction->isChecked()) {
    370393    setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine);
     
    376399
    377400  for (int ItemNo=0; ItemNo<Items.size(); ItemNo++) {
    378 
     401        // Determine current maximum value for strip chart plotting
     402        if (Items[ItemNo].Signal->boundingRect().right() > MaxTime) {
     403          MaxTime = Items[ItemNo].Signal->boundingRect().right();
     404        }
     405
     406        // Set symbol if requested
    379407    if (StyleAction->isChecked()) Items[ItemNo].Signal->setSymbol(Symbol);
    380408    else Items[ItemNo].Signal->setSymbol(Sym1);
    381409
     410        // Determine number of data points
    382411    int DataPoints = Items[ItemNo].x.size();   
    383412        if (DataPoints == 0) continue;
     
    399428    Items[ItemNo].Signal->setData(Items[ItemNo].x.data(), y, DataPoints);
    400429    Items[ItemNo].Signal->show();
    401     Zoomer->setZoomBase(Items[ItemNo].Signal->boundingRect());
    402 
    403     delete[] y;
    404   }
     430        delete[] y;
     431
     432        // Generate bounding box of all curves for zoomer
     433        BBox = BBox.unite(Items[ItemNo].Signal->boundingRect());
     434  }
     435
     436  // Reset zoom base to include all data
     437  Zoomer->setZoomBase(BBox);
     438
     439  // If plot is strip char, only move axis but keep range
     440  if (StripAction->isChecked()) {
     441    setCanvasBackground(EddPlotBackgroundColor.lighter(90));
     442    setAxisScale(QwtPlot::xBottom, Lower+ BBox.right() - MaxTime, Upper + BBox.right() - MaxTime);
     443  }
     444  else setCanvasBackground(EddPlotBackgroundColor);
     445
    405446  replot();
    406447}
     448
     449// Add text indicating time range to plot
     450void EddPlot::paintEvent(QPaintEvent *) {
     451
     452  QString Text;
     453  QFont Font;
     454  QPainter Painter(this);
     455 
     456  Text = QDateTime::fromTime_t((int) axisScaleDiv(QwtPlot::xBottom)->lowerBound()).toString("d-MMM-yyyy hh:mm:ss") + " to " + QDateTime::fromTime_t((int) axisScaleDiv(QwtPlot::xBottom)->upperBound()).toString("d-MMM-yyyy hh:mm:ss");
     457
     458  Font.setPointSize(6); 
     459  Painter.setFont(Font);
     460  Painter.drawText(0, height(),Text);
     461}
     462
     463// Rescale plot in case selection has been made outside the canvas
     464void EddPlot::MouseSelection(const QPolygon &P) {
     465 
     466  QwtDoubleInterval xPlot, xMouse, yPlot, yMouse;
     467
     468  // Shift selected rectangle so that upper left corner is 0/0 on canvas
     469  QRect R = P.boundingRect().translated(-plotLayout()->canvasRect().topLeft());
     470
     471  // Current axis intervals
     472  xPlot = axisScaleDiv(QwtPlot::xBottom)->interval();
     473  yPlot = axisScaleDiv(QwtPlot::yLeft)->interval();
     474 
     475  // Selected axis intervals
     476  xMouse = QwtDoubleInterval(invTransform(QwtPlot::xBottom, R.left()),
     477                invTransform(QwtPlot::xBottom, R.right()));
     478  yMouse = QwtDoubleInterval(invTransform(QwtPlot::yLeft, R.bottom()),
     479                invTransform(QwtPlot::yLeft, R.top()));
     480
     481  // Selection region outside all axis?
     482  if (R.right() < 0 && R.top() > plotLayout()->canvasRect().height()) return;
     483 
     484  // Rescale both axis if selected rectangle encompasses canvas completely
     485  if (P.boundingRect().contains(plotLayout()->canvasRect())) {
     486        yMouse.setMaxValue(yMouse.maxValue() + yPlot.width());
     487        yMouse.setMinValue(yMouse.minValue() - yPlot.width());
     488        xMouse.setMinValue(xMouse.minValue() - xPlot.width());
     489        xMouse.setMaxValue(xMouse.maxValue() + xPlot.width());
     490
     491        setAxisScale(QwtPlot::xBottom, xMouse.minValue(), xMouse.maxValue());
     492        setAxisScale(QwtPlot::yLeft, yMouse.minValue(), yMouse.maxValue());
     493  }
     494
     495  // Rescale y axis (increase range if selected rectangle larger than axis area)
     496  if (R.right() < 0) {
     497        if (R.top() < plotLayout()->canvasRect().top()) {
     498          yMouse.setMaxValue(yMouse.maxValue() + yPlot.width());
     499        }
     500        if (R.bottom() > plotLayout()->canvasRect().bottom()) {
     501          yMouse.setMinValue(yMouse.minValue() - yPlot.width());
     502        }
     503       
     504        setAxisScale(QwtPlot::yLeft, yMouse.minValue(), yMouse.maxValue());
     505  }
     506
     507  // Rescale x axis (increase range if selected rectangle larger than axis area)
     508  if (R.top() > plotLayout()->canvasRect().height()) {
     509        if (R.left() < plotLayout()->canvasRect().left()) {
     510          xMouse.setMinValue(xMouse.minValue() - xPlot.width());
     511        }
     512        if (R.right() > plotLayout()->canvasRect().right()) {
     513          xMouse.setMaxValue(xMouse.maxValue() + xPlot.width());
     514        }
     515        setAxisScale(QwtPlot::xBottom, xMouse.minValue(), xMouse.maxValue());
     516  }
     517
     518  // Draw new scales
     519  replot();
     520}
     521
    407522
    408523//
     
    537652}
    538653
     654// Help text
     655void EddPlot::MenuPlotHelp() {
     656
     657  QMessageBox::about(this, "Edd - Plot navigation",
     658    "Zoom\tMouse wheel\n"
     659        "\tKeys m and shift-m\n"
     660        "\tSelecting region with left mouse button\n"
     661        "\tMiddle button zooms out one level\n"
     662        "\tSelecting a range on an axis\n"
     663        "\tSelecting whole canvas\n\n"
     664    "Pan\tShift and left mouse button\n\n"
     665        "ESC cancels selection\n"
     666    "Cursor keys move mouse");
     667}
     668
    539669
    540670//////////////////////////////////////
     
    754884
    755885
    756 //
    757 // Main GUI (all widgets have ultimately Central as parent)
     886//--------------------------------------------------------------------
     887//*************************** Main GUI *******************************
     888//--------------------------------------------------------------------
     889//
     890// All widgets have ultimately Central as parent.
    758891//
    759892GUI::GUI() {
     
    10021135}
    10031136
    1004 
    1005 //---------------------------------------------------------------------
    1006 //************************ All functions ****************************
    1007 //-------------------------------------------------------------------
    1008 
    10091137// Quit application when clicking close button on window
    10101138void GUI::closeEvent(QCloseEvent *) {
  • Evidence/Edd/Edd.h

    r174 r204  
    88#include <qwt_plot_grid.h>
    99#include <qwt_plot_zoomer.h>
     10#include <qwt_plot_magnifier.h>
    1011#include <qwt_plot_panner.h>
    1112#include <qwt_scale_engine.h>
     
    1617#include <qwt_legend_item.h>
    1718#include <qwt_symbol.h>
     19#include <qwt_plot_marker.h>
    1820
    1921#include <limits.h>
     
    2527#define SVN_REVISION "$Revision$"
    2628
     29const QColor EddPlotBackgroundColor(Qt::yellow);
     30
    2731QWidget *OpenHistory(char *, int);
    2832
    2933// Time scale for axis
    30 class TimeScale: public QwtScaleDraw {
    31   public:
    32     TimeScale() { }
     34class EddTimeScale: public QwtScaleDraw {
     35
     36  public:
     37    EddTimeScale() {}
     38
    3339    virtual QwtText label(double v) const {
    34       QDateTime t = QDateTime::fromTime_t((int) v);
    35       return t.toString("dMMM'\n'hh:mm:ss");
     40
     41          // Adapt text format to time span
     42          QString Format;
     43          if (scaleDiv().range() < 60*60) Format = "hh' h\n'mm:ss";
     44          else if (scaleDiv().range() < 24*60*60) Format = "hh:mm";
     45          else if (scaleDiv().range() < 30*24*60*60) Format = "h' h\n'd-MMM";
     46          else Format = "d-MMM'\n'yyyy";
     47
     48          // Generate text
     49          QwtText Text = QDateTime::fromTime_t((int) v).toString(Format);
     50          QFont Font = Text.font();
     51          Font.setPointSize(7);
     52          Text.setFont(Font);
     53
     54      return Text;
    3655    }
    3756};
     
    89108    QAction *NormAction;
    90109    QAction *StyleAction;
     110    QAction *StripAction;
    91111   
    92112    QwtPlotPanner *Panner;
    93113    QwtPlotGrid *Grid;
    94114    QwtPlotZoomer *Zoomer;
    95     QwtLegend *Legend;
    96    
     115        QwtPlotMagnifier *Magnifier;
     116    QwtPicker *Picker;
     117        QwtLegend *Legend;
     118        QwtDoubleRect BBox;
     119
    97120    void dragEnterEvent(QDragEnterEvent *);
    98121    void dropEvent(QDropEvent *);
    99 
     122        void paintEvent(QPaintEvent *);
     123               
    100124  public:
    101125    EddPlot(QString = QString(), int = 0, QWidget * = NULL);
     
    108132
    109133    void HandleZoom(const QwtDoubleRect &);
    110     void contextMenuEvent(QContextMenuEvent *);
     134        void MouseSelection(const QwtPolygon &);
     135        void contextMenuEvent(QContextMenuEvent *);
    111136        void LegendClicked(QwtPlotItem *);
    112137    void MenuZoomOut();
     
    116141    void MenuPrint();
    117142    void MenuPasteService();
     143        void MenuPlotHelp();
    118144};
    119145
Note: See TracChangeset for help on using the changeset viewer.