From 0ecfa0e67ecb0277a8afb031ee7a9469597da5ea Mon Sep 17 00:00:00 2001 From: Mark Liversedge Date: Fri, 28 Feb 2020 14:31:50 +0000 Subject: [PATCH] Add QChart to Python Chart (3h of 5) Use legend to select which series are plotted by clicking to show hide a series. Hover just shows a hover background and does not temporarily isolate the series, this may be something to consider for later. Applies to scatter and line charts. --- src/Charts/GenericLegend.cpp | 60 +++++- src/Charts/GenericLegend.h | 13 +- src/Charts/GenericPlot.cpp | 18 ++ src/Charts/GenericPlot.h | 4 + src/Charts/GenericSelectTool.cpp | 354 +++++++++++++++++-------------- src/Charts/GenericSelectTool.h | 6 + 6 files changed, 285 insertions(+), 170 deletions(-) diff --git a/src/Charts/GenericLegend.cpp b/src/Charts/GenericLegend.cpp index 9e8fb9067..e67520cfb 100644 --- a/src/Charts/GenericLegend.cpp +++ b/src/Charts/GenericLegend.cpp @@ -31,11 +31,16 @@ GenericLegendItem::GenericLegendItem(Context *context, QWidget *parent, QString { value=0; + enabled=true; hasvalue=false; // set height and width, gets reset when configchanges configChanged(0); + // we want to track our own events - for hover and click + installEventFilter(this); + setMouseTracking(true); + // watch for changes... connect(context, SIGNAL(configChanged(qint32)), this, SLOT(configChanged(qint32))); @@ -45,8 +50,8 @@ GenericLegendItem::GenericLegendItem(Context *context, QWidget *parent, QString void GenericLegendItem::configChanged(qint32) { - static const double gl_margin = 3 * dpiXFactor; - static const double gl_spacer = 3 * dpiXFactor; + static const double gl_margin = 5 * dpiXFactor; + static const double gl_spacer = 2 * dpiXFactor; static const double gl_block = 7 * dpiXFactor; static const double gl_linewidth = 1 * dpiXFactor; @@ -62,7 +67,7 @@ GenericLegendItem::configChanged(qint32) + gl_spacer + fm.boundingRect(valuelabel).width() + gl_margin; // maximum height of widget = margin + textheight + spacer + line - double height = gl_margin + fm.boundingRect(valuelabel).height() + gl_spacer + gl_linewidth; + double height = (gl_margin*2) + fm.boundingRect(valuelabel).height() + gl_spacer + gl_linewidth; // now set geometry of widget setFixedWidth(width); @@ -70,15 +75,39 @@ GenericLegendItem::configChanged(qint32) // calculate all the rects used by the painter now since static blockrect = QRectF(gl_margin, gl_margin, gl_block, height-gl_margin); - linerect = QRectF(gl_margin+gl_block, height-gl_linewidth, width-gl_margin, gl_linewidth); + linerect = QRectF(gl_margin+gl_block, gl_spacer+height-gl_linewidth-(gl_margin*2), width-gl_block-(gl_margin*2), gl_linewidth); namerect = QRectF(gl_margin + gl_block + gl_spacer, gl_margin, fm.boundingRect(name).width(), fm.boundingRect(name).height()); valuerect =QRectF(namerect.x() + namerect.width() + gl_spacer, gl_margin, fm.boundingRect(valuelabel).width(), fm.boundingRect(valuelabel).height()); + hoverrect = QRectF(gl_block, 0, width-gl_block,height); // redraw update(); } +bool +GenericLegendItem::eventFilter(QObject *obj, QEvent *e) +{ + if (obj != this) return false; + + switch (e->type()) { + case QEvent::MouseButtonRelease: // for now just one event, but may do more later + { + if (underMouse()) { + enabled=!enabled; + if (!enabled) hasvalue=false; + emit clicked(name, enabled); + } + } + // fall through + default: + //fprintf(stderr, "event %d on %s\n", e->type(), name.toStdString().c_str()); fflush(stderr); + update(); + break; + } + return false; +} + void GenericLegendItem::paintEvent(QPaintEvent *) { @@ -90,8 +119,18 @@ GenericLegendItem::paintEvent(QPaintEvent *) painter.setPen(Qt::NoPen); painter.drawRect(0,0,geometry().width()-1, geometry().height()-1); - // block and line - painter.setBrush(QBrush(color)); + // under mouse show + if (underMouse()) { + QColor mask=GCColor::invertColor(GColor(CPLOTBACKGROUND)); + mask.setAlphaF(0.1); + painter.setBrush(mask); + painter.setPen(Qt::NoPen); + painter.drawRect(hoverrect); + } + + // block and line - gray means disabled + if (enabled) painter.setBrush(QBrush(color)); + else painter.setBrush(QBrush(Qt::gray)); painter.setPen(Qt::NoPen); //painter.drawRect(blockrect); painter.drawRect(linerect); @@ -105,7 +144,8 @@ GenericLegendItem::paintEvent(QPaintEvent *) string = Utils::removeDP(string); // set pen to series color for now - painter.setPen(GCColor::invertColor(GColor(CPLOTBACKGROUND))); // use invert - usually black or white + if (enabled) painter.setPen(GCColor::invertColor(GColor(CPLOTBACKGROUND))); // use invert - usually black or white + else painter.setPen(Qt::gray); painter.setFont(QFont()); // series @@ -136,6 +176,9 @@ GenericLegend::addSeries(QString name, QAbstractSeries *series) // lets see ya! add->show(); + + // connect signals + connect(add, SIGNAL(clicked(QString,bool)), this, SIGNAL(clicked(QString,bool))); } void @@ -153,6 +196,9 @@ GenericLegend::addX(QString name) // remember the x axis xname = name; + + // we don't connect -- there is no such series, its a meta legend item + // NOPE: connect(add, SIGNAL(clicked(QString,bool)), this, SIGNAL(clicked(QString,bool))); } void diff --git a/src/Charts/GenericLegend.h b/src/Charts/GenericLegend.h index d275cb62d..0984b2998 100644 --- a/src/Charts/GenericLegend.h +++ b/src/Charts/GenericLegend.h @@ -50,11 +50,17 @@ class GenericLegendItem : public QWidget { public: GenericLegendItem(Context *context, QWidget *parent, QString name, QColor color); + Q_SIGNALS: + void clicked(QString name, bool enabled); // someone clicked on a legend and enabled/disabled it + + protected: + bool eventFilter(QObject *, QEvent *e); + public slots: void paintEvent(QPaintEvent *event); - void setValue(double p) { hasvalue=true; value=p; update(); } // set value to display - void noValue() { hasvalue=false; update(); } // no value to display + void setValue(double p) { if (enabled) { hasvalue=true; value=p; update(); } } // set value to display + void noValue() { if (enabled) { hasvalue=false; update(); } } // no value to display void configChanged(qint32); // context changed private: @@ -63,10 +69,11 @@ class GenericLegendItem : public QWidget { QColor color; bool hasvalue; + bool enabled; double value; // geometry for painting fast / updated on config changes - QRectF blockrect, namerect, valuerect, linerect; + QRectF blockrect, namerect, valuerect, linerect, hoverrect; }; diff --git a/src/Charts/GenericPlot.cpp b/src/Charts/GenericPlot.cpp index 6a9a0f656..1cf9d5346 100644 --- a/src/Charts/GenericPlot.cpp +++ b/src/Charts/GenericPlot.cpp @@ -76,6 +76,7 @@ GenericPlot::GenericPlot(QWidget *parent, Context *context) : QWidget(parent), c connect(selector, SIGNAL(hover(QPointF,QString,QAbstractSeries*)), legend, SLOT(hover(QPointF,QString,QAbstractSeries*))); connect(selector, SIGNAL(unhover(QString)), legend, SLOT(unhover(QString))); connect(selector, SIGNAL(unhoverx()), legend, SLOT(unhoverx())); + connect(legend, SIGNAL(clicked(QString,bool)), this, SLOT(setSeriesVisible(QString,bool))); // config changed... configChanged(0); @@ -211,6 +212,23 @@ GenericPlot::configChanged(qint32) qchart->setBackgroundPen(QPen(GColor(CPLOTMARKER))); } +void +GenericPlot::setSeriesVisible(QString name, bool visible) +{ + // find the curve + QAbstractSeries *series = curves.value(name, NULL); + + // does it exist and did it change? + if (series && series->isVisible() != visible) { + + // show/hide + series->setVisible(visible); + + // tell selector we hid/show a series so it can respond. + selector->setSeriesVisible(name, visible); + } +} + bool GenericPlot::initialiseChart(QString title, int type, bool animate) { diff --git a/src/Charts/GenericPlot.h b/src/Charts/GenericPlot.h index c5daba589..44304edbc 100644 --- a/src/Charts/GenericPlot.h +++ b/src/Charts/GenericPlot.h @@ -124,6 +124,10 @@ class GenericPlot : public QWidget { static QColor seriesColor(QAbstractSeries* series); public slots: + + // do we want to see this series? + void setSeriesVisible(QString name, bool visible); + void configChanged(qint32); // set chart settings diff --git a/src/Charts/GenericSelectTool.cpp b/src/Charts/GenericSelectTool.cpp index 0db237289..34a708f6c 100644 --- a/src/Charts/GenericSelectTool.cpp +++ b/src/Charts/GenericSelectTool.cpp @@ -64,6 +64,8 @@ void GenericSelectTool::paint(QPainter*painter, const QStyleOptionGraphicsItem * // current position for each series - we only do first, coz only interested in x axis anyway foreach(QAbstractSeries *series, host->qchart->series()) { + if (series->isVisible() == false) continue; // ignore invisble curves + // convert screen position to value for series QPointF v = host->qchart->mapToValue(spos,series); double miny=0; @@ -96,7 +98,7 @@ void GenericSelectTool::paint(QPainter*painter, const QStyleOptionGraphicsItem * QColor invert = GCColor::invertColor(GColor(CPLOTBACKGROUND)); painter->setBrush(invert); painter->setPen(invert); - QRectF circle(0,0,5*dpiXFactor,5*dpiYFactor); + QRectF circle(0,0,gl_linemarker*dpiXFactor,gl_linemarker*dpiYFactor); circle.moveCenter(pos); painter->drawEllipse(circle); painter->setBrush(Qt::NoBrush); @@ -121,7 +123,7 @@ void GenericSelectTool::paint(QPainter*painter, const QStyleOptionGraphicsItem * QColor invert = GCColor::invertColor(GColor(CPLOTBACKGROUND)); painter->setBrush(invert); painter->setPen(invert); - QRectF circle(0,0,10*dpiXFactor,10*dpiYFactor); + QRectF circle(0,0,gl_scattermarker*dpiXFactor,gl_scattermarker*dpiYFactor); circle.moveCenter(hoverpoint); painter->drawEllipse(circle); painter->setBrush(Qt::NoBrush); @@ -131,6 +133,7 @@ void GenericSelectTool::paint(QPainter*painter, const QStyleOptionGraphicsItem * // current position for each series foreach(QAbstractSeries *series, host->qchart->series()) { + if (series->isVisible() == false) continue; // ignore invisble curves // convert screen position to value for series QPointF v = host->qchart->mapToValue(spos,series); @@ -483,6 +486,8 @@ GenericSelectTool::moved(QPointF pos) hoverseries = NULL; foreach(QAbstractSeries *series, host->qchart->series()) { + if (series->isVisible() == false) continue; // ignore invisble curves + Quadtree *tree= host->quadtrees.value(series,NULL); if (tree != NULL) { @@ -539,7 +544,7 @@ GenericSelectTool::moved(QPointF pos) double nearestx=-9999; foreach(QAbstractSeries *series, host->qchart->series()) { - if (ignore.contains(series)) continue; + if (series->isVisible() == false || ignore.contains(series)) continue; // get x value to search double xvalue=host->qchart->mapToValue(spos,series).x(); @@ -672,193 +677,222 @@ GenericCalculator::finalise() } } +void +GenericSelectTool::setSeriesVisible(QString name, bool visible) +{ + // a series got hidden or showm, so do whats needed. + QString selectionName = QString("%1_select").arg(name); + foreach(QAbstractSeries *x, host->qchart->series()) + if (x->name() == selectionName) + x->setVisible(visible); + + // as a special case we clear the hoverpoints. + // they will get redisplayed when the cursor moves + // but for now this is the quickes and simplest way + // to avoid artefacts + hoverpoints.clear(); + hoverpoint=QPointF(); + + // hide/show and updatescenes may overlap/get out of sync + // so we update scene to be absolutely sure the scene + // reflects the current visible settings (and others later) + rectchanged = true; + updateScene(); +} + // selector needs to update the chart for selections void GenericSelectTool::updateScene() { // is the selection active? if (rectchanged) { - if (state != GenericSelectTool::INACTIVE && state != DRAGGING) { - // selection tool is active so set curves gray - // and create curves for highlighted points etc - QList originallist=host->qchart->series(); - foreach(QAbstractSeries *x, originallist) { // because we update it below (!) + // clear incidental state that gets reset when needed + stats.clear(); - if (ignore.contains(x)) continue; + if (state != GenericSelectTool::INACTIVE && state != DRAGGING) { - // Run through all the curves, setting them gray - // selecting the points that fall into the selection - // and creating selection curves and stats for painting - // onto the plot - // - // We duplicate code by curve type (but not chart type) - // so we can e.g. put a scatter curve on a line chart - // and vice versa later. + // selection tool is active so set curves gray + // and create curves for highlighted points etc + QList originallist=host->qchart->series(); + foreach(QAbstractSeries *x, originallist) { // because we update it below (!) - switch(x->type()) { - case QAbstractSeries::SeriesTypeLine: { - QLineSeries *line = static_cast(x); + if (x->isVisible() == false || ignore.contains(x)) continue; - // ignore empty series - if (line->count() < 1) continue; + // Run through all the curves, setting them gray + // selecting the points that fall into the selection + // and creating selection curves and stats for painting + // onto the plot + // + // We duplicate code by curve type (but not chart type) + // so we can e.g. put a scatter curve on a line chart + // and vice versa later. - // this will be used to plot selected points on the plot - QLineSeries *selection =NULL; + switch(x->type()) { + case QAbstractSeries::SeriesTypeLine: { + QLineSeries *line = static_cast(x); - // the axes for the current series - QAbstractAxis *xaxis=NULL, *yaxis=NULL; - foreach (QAbstractAxis *ax, x->attachedAxes()) { - if (ax->orientation() == Qt::Vertical && yaxis==NULL) yaxis=ax; - if (ax->orientation() == Qt::Horizontal && xaxis==NULL) xaxis=ax; - } + // ignore empty series + if (line->count() < 1) continue; - if ((selection=static_cast(selections.value(x, NULL))) == NULL) { + // this will be used to plot selected points on the plot + QLineSeries *selection =NULL; - selection = new QLineSeries(); - - // all of this curve cloning should be in a new method xxx todo - selection->setUseOpenGL(line->useOpenGL()); - selection->setPen(line->pen()); - if (line->useOpenGL()) - selection->setColor(Qt::gray); // use opengl ignores changing colors - else { - selection->setColor(line->color()); - static_cast(x)->setColor(Qt::gray); + // the axes for the current series + QAbstractAxis *xaxis=NULL, *yaxis=NULL; + foreach (QAbstractAxis *ax, x->attachedAxes()) { + if (ax->orientation() == Qt::Vertical && yaxis==NULL) yaxis=ax; + if (ax->orientation() == Qt::Horizontal && xaxis==NULL) xaxis=ax; } - selections.insert(x, selection); - ignore.append(selection); - // add after done all aesthetic for opengl snafus - host->qchart->addSeries(selection); // before adding data and axis + if ((selection=static_cast(selections.value(x, NULL))) == NULL) { - // only do when creating it. - if (yaxis) selection->attachAxis(yaxis); - if (xaxis) selection->attachAxis(xaxis); - } + selection = new QLineSeries(); + selection->setName(QString("%1_select").arg(line->name())); - // lets work out what range of values we need to be - // selecting is, reverse since possible to have a backwards - // rectangle in the selection tool - double minx=0,maxx=0; - minx =this->minx(x); - maxx =this->maxx(x); - if (maxx < minx) { double t=minx; minx=maxx; maxx=t; } + // all of this curve cloning should be in a new method xxx todo + selection->setUseOpenGL(line->useOpenGL()); + selection->setPen(line->pen()); + if (line->useOpenGL()) + selection->setColor(Qt::gray); // use opengl ignores changing colors + else { + selection->setColor(line->color()); + static_cast(x)->setColor(Qt::gray); + } + selections.insert(x, selection); + ignore.append(selection); - //fprintf(stderr, "xaxis range %f-%f, yaxis range %f-%f, [%s] %d points to check\n", minx,maxx,miny,maxy,scatter->name().toStdString().c_str(), scatter->count()); + // add after done all aesthetic for opengl snafus + host->qchart->addSeries(selection); // before adding data and axis - // add points to the selection curve and calculate as you go - QList points; - GenericCalculator calc; - calc.initialise(); - calc.color = selection->color(); // should this go into constructor?! xxx todo - calc.xaxis = xaxis; - calc.yaxis = yaxis; - calc.series = line; - for(int i=0; icount(); i++) { - QPointF point = line->at(i); // avoid deep copy - if (point.x() >= minx && point.x() <= maxx) { - if (!points.contains(point)) points << point; // avoid dupes - calc.addPoint(point); + // only do when creating it. + if (yaxis) selection->attachAxis(yaxis); + if (xaxis) selection->attachAxis(xaxis); } - } - calc.finalise(); - stats.insert(line, calc); - selection->clear(); - if (points.count()) selection->append(points); + // lets work out what range of values we need to be + // selecting is, reverse since possible to have a backwards + // rectangle in the selection tool + double minx=0,maxx=0; + minx =this->minx(x); + maxx =this->maxx(x); + if (maxx < minx) { double t=minx; minx=maxx; maxx=t; } - } - break; - case QAbstractSeries::SeriesTypeScatter: { + //fprintf(stderr, "xaxis range %f-%f, yaxis range %f-%f, [%s] %d points to check\n", minx,maxx,miny,maxy,scatter->name().toStdString().c_str(), scatter->count()); - QScatterSeries *scatter = static_cast(x); - - // ignore empty series - if (scatter->count() < 1) continue; - - // this will be used to plot selected points on the plot - QScatterSeries *selection =NULL; - - // the axes for the current series - QAbstractAxis *xaxis=NULL, *yaxis=NULL; - foreach (QAbstractAxis *ax, x->attachedAxes()) { - if (ax->orientation() == Qt::Vertical && yaxis==NULL) yaxis=ax; - if (ax->orientation() == Qt::Horizontal && xaxis==NULL) xaxis=ax; - } - - if ((selection=static_cast(selections.value(x, NULL))) == NULL) { - - selection = new QScatterSeries(); - - // all of this curve cloning should be in a new method xxx todo - host->qchart->addSeries(selection); // before adding data and axis - selection->setUseOpenGL(scatter->useOpenGL()); - if (selection->useOpenGL()) - selection->setColor(Qt::gray); // use opengl ignores changing colors - else { - selection->setColor(scatter->color()); - static_cast(x)->setColor(Qt::gray); + // add points to the selection curve and calculate as you go + QList points; + GenericCalculator calc; + calc.initialise(); + calc.color = selection->color(); // should this go into constructor?! xxx todo + calc.xaxis = xaxis; + calc.yaxis = yaxis; + calc.series = line; + for(int i=0; icount(); i++) { + QPointF point = line->at(i); // avoid deep copy + if (point.x() >= minx && point.x() <= maxx) { + if (!points.contains(point)) points << point; // avoid dupes + calc.addPoint(point); + } } - selection->setMarkerSize(scatter->markerSize()); - selection->setMarkerShape(scatter->markerShape()); - selection->setPen(scatter->pen()); - selections.insert(x, selection); - ignore.append(selection); + calc.finalise(); + stats.insert(line, calc); + + selection->clear(); + if (points.count()) selection->append(points); - // only do when creating it. - if (yaxis) selection->attachAxis(yaxis); - if (xaxis) selection->attachAxis(xaxis); } - - // lets work out what range of values we need to be - // selecting is, reverse since possible to have a backwards - // rectangle in the selection tool - double miny=0,maxy=0,minx=0,maxx=0; - miny =this->miny(x); - maxy =this->maxy(x); - if (maxy < miny) { double t=miny; miny=maxy; maxy=t; } - - minx =this->minx(x); - maxx =this->maxx(x); - if (maxx < minx) { double t=minx; minx=maxx; maxx=t; } - - //fprintf(stderr, "xaxis range %f-%f, yaxis range %f-%f, [%s] %d points to check\n", minx,maxx,miny,maxy,scatter->name().toStdString().c_str(), scatter->count()); - - // add points to the selection curve and calculate as you go - QList points; - GenericCalculator calc; - calc.initialise(); - calc.color = selection->color(); // should this go into constructor?! xxx todo - calc.xaxis = xaxis; - calc.yaxis = yaxis; - calc.series = scatter; - for(int i=0; icount(); i++) { - QPointF point = scatter->at(i); // avoid deep copy - if (point.y() >= miny && point.y() <= maxy && - point.x() >= minx && point.x() <= maxx) { - if (!points.contains(point)) points << point; // avoid dupes - calc.addPoint(point); - } - } - calc.finalise(); - stats.insert(scatter, calc); - - selection->clear(); - if (points.count()) selection->append(points); - } - break; - default: break; + case QAbstractSeries::SeriesTypeScatter: { + + QScatterSeries *scatter = static_cast(x); + + // ignore empty series + if (scatter->count() < 1) continue; + + // this will be used to plot selected points on the plot + QScatterSeries *selection =NULL; + + // the axes for the current series + QAbstractAxis *xaxis=NULL, *yaxis=NULL; + foreach (QAbstractAxis *ax, x->attachedAxes()) { + if (ax->orientation() == Qt::Vertical && yaxis==NULL) yaxis=ax; + if (ax->orientation() == Qt::Horizontal && xaxis==NULL) xaxis=ax; + } + + if ((selection=static_cast(selections.value(x, NULL))) == NULL) { + + selection = new QScatterSeries(); + + // all of this curve cloning should be in a new method xxx todo + host->qchart->addSeries(selection); // before adding data and axis + selection->setUseOpenGL(scatter->useOpenGL()); + if (selection->useOpenGL()) + selection->setColor(Qt::gray); // use opengl ignores changing colors + else { + selection->setColor(scatter->color()); + static_cast(x)->setColor(Qt::gray); + } + selection->setMarkerSize(scatter->markerSize()); + selection->setMarkerShape(scatter->markerShape()); + selection->setPen(scatter->pen()); + selection->setName(QString("%1_select").arg(scatter->name())); + selections.insert(x, selection); + ignore.append(selection); + + // only do when creating it. + if (yaxis) selection->attachAxis(yaxis); + if (xaxis) selection->attachAxis(xaxis); + } + + // lets work out what range of values we need to be + // selecting is, reverse since possible to have a backwards + // rectangle in the selection tool + double miny=0,maxy=0,minx=0,maxx=0; + miny =this->miny(x); + maxy =this->maxy(x); + if (maxy < miny) { double t=miny; miny=maxy; maxy=t; } + + minx =this->minx(x); + maxx =this->maxx(x); + if (maxx < minx) { double t=minx; minx=maxx; maxx=t; } + + //fprintf(stderr, "xaxis range %f-%f, yaxis range %f-%f, [%s] %d points to check\n", minx,maxx,miny,maxy,scatter->name().toStdString().c_str(), scatter->count()); + + // add points to the selection curve and calculate as you go + QList points; + GenericCalculator calc; + calc.initialise(); + calc.color = selection->color(); // should this go into constructor?! xxx todo + calc.xaxis = xaxis; + calc.yaxis = yaxis; + calc.series = scatter; + for(int i=0; icount(); i++) { + QPointF point = scatter->at(i); // avoid deep copy + if (point.y() >= miny && point.y() <= maxy && + point.x() >= minx && point.x() <= maxx) { + if (!points.contains(point)) points << point; // avoid dupes + calc.addPoint(point); + } + } + calc.finalise(); + stats.insert(scatter, calc); + + selection->clear(); + if (points.count()) selection->append(points); + } + break; + default: + break; + } } + + rectchanged = false; + + } else { + + resetSelections(); } - - rectchanged = false; - - } else { - - resetSelections(); - } } // repaint everything @@ -873,7 +907,7 @@ GenericSelectTool::updateScene() foreach(QAbstractSeries *x, host->qchart->series()) { - if (ignore.contains(x)) continue; + if (ignore.contains(x)) continue; // we still reset selections for invisible curves switch(x->type()) { diff --git a/src/Charts/GenericSelectTool.h b/src/Charts/GenericSelectTool.h index 9cca13da6..1389cdcc8 100644 --- a/src/Charts/GenericSelectTool.h +++ b/src/Charts/GenericSelectTool.h @@ -83,6 +83,9 @@ class GenericSelectTool : public QObject, public QGraphicsItem Q_OBJECT Q_INTERFACES(QGraphicsItem) + static constexpr double gl_linemarker = 7; + static constexpr double gl_scattermarker = 10; + friend class ::GenericPlot; public: @@ -95,6 +98,9 @@ class GenericSelectTool : public QObject, public QGraphicsItem // set mode void setMode(SelectionMode mode) { this->mode=mode; } + // some series was shown or hidden... + void setSeriesVisible(QString name, bool visible); + // is invisible and tiny. we are just an observer bool sceneEventFilter(QGraphicsItem *watched, QEvent *event);