From 75c5affd4d7919a969ab65a4a28b6306686e5f9c Mon Sep 17 00:00:00 2001 From: Samuel Fadel Date: Tue, 29 Sep 2015 16:01:00 -0300 Subject: HistoryGraph now notifies when the active item changes. Scatterplot now differentiates between interactive and programatic changes in x/y data. --- historygraph.cpp | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- historygraph.h | 8 +++++++- main.cpp | 5 +++-- scatterplot.cpp | 2 +- scatterplot.h | 1 + 5 files changed, 71 insertions(+), 6 deletions(-) diff --git a/historygraph.cpp b/historygraph.cpp index 997d079..0aeec20 100644 --- a/historygraph.cpp +++ b/historygraph.cpp @@ -10,9 +10,11 @@ static const float ASPECT = 4.f / 3.f; static const float MARGIN = 0.1f; -static const float GLYPH_SIZE = 4.0f; static const float PADDING = 0.05f; +static const float GLYPH_SIZE = 4.0f; +static const float GLYPH_OPACITY = 0.6f; + class HistoryGraph::HistoryItemNode { public: @@ -21,9 +23,14 @@ public: void append(HistoryItemNode *node); const QList &children() const { return m_next; } + const arma::mat &item() const; int depth() const { return m_depth; } int breadth() const { return m_breadth; } + const QRectF &rect() const { return m_rect; } + + void setRect(const QRectF &rect) { m_rect = rect; } + void updateDepth(); void updateBreadth(); @@ -34,6 +41,7 @@ private: HistoryItemNode *m_prev; QList m_next; int m_depth, m_breadth; + QRectF m_rect; }; HistoryGraph::HistoryItemNode::HistoryItemNode(const arma::mat &item) @@ -122,6 +130,7 @@ HistoryGraph::HistoryGraph(QQuickItem *parent) { setClip(true); setFlag(QQuickItem::ItemHasContents); + setAcceptedMouseButtons(Qt::LeftButton); } HistoryGraph::~HistoryGraph() @@ -169,7 +178,7 @@ void HistoryGraph::addScatterplot(QSGNode *node, const HistoryGraph::HistoryItem // Place the glyph geometry node under an opacity node QSGOpacityNode *glyphOpacityNode = new QSGOpacityNode; - //glyphOpacityNode->appendChildNode(glyphOutlineNode); + glyphOpacityNode->setOpacity(GLYPH_OPACITY); glyphOpacityNode->appendChildNode(glyphNode); node->appendChildNode(glyphOpacityNode); } @@ -197,6 +206,7 @@ QSGNode *HistoryGraph::createNodeTree() QSGOpacityNode *opacityNode = new QSGOpacityNode; opacityNode->setOpacity(histNode == m_currentNode ? 1.0f : 0.4f); + histNode->setRect(QRectF(x, margin, w, h)); QSGGeometryNode *histItemGeomNode = new QSGGeometryNode; QSGGeometry *histItemGeom = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 4); updateRectGeometry(histItemGeom, x, margin, w, h); @@ -266,3 +276,50 @@ QSGNode *HistoryGraph::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) return root; } + +HistoryGraph::HistoryItemNode *HistoryGraph::nodeAt(const QPointF &pos) const +{ + return nodeAt(pos, m_firstNode); +} + +HistoryGraph::HistoryItemNode *HistoryGraph::nodeAt(const QPointF &pos, HistoryGraph::HistoryItemNode *node) const +{ + if (!node) { + return 0; + } + + const QRectF &rect = node->rect(); + + if (pos.x() < rect.x()) { + return 0; + } + + if (rect.contains(pos)) { + return node; + } + + QList children = node->children(); + for (auto it = children.begin(); it != children.end(); it++) { + HistoryGraph::HistoryItemNode *tmp = nodeAt(pos, *it); + if (tmp) { + return tmp; + } + } + + return 0; +} + +void HistoryGraph::mousePressEvent(QMouseEvent *event) +{ + HistoryGraph::HistoryItemNode *node = nodeAt(event->localPos()); + if (!node || node == m_currentNode) { + event->ignore(); + return; + } + + m_currentNode = node; + m_needsUpdate = true; + update(); + + emit currentItemChanged(m_currentNode->item()); +} diff --git a/historygraph.h b/historygraph.h index 564845c..60cce94 100644 --- a/historygraph.h +++ b/historygraph.h @@ -11,20 +11,26 @@ public: HistoryGraph(QQuickItem *parent = 0); ~HistoryGraph(); +signals: + void currentItemChanged(const arma::mat &item); + public slots: void addHistoryItem(const arma::mat &item); protected: QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *); + void mousePressEvent(QMouseEvent *event); private: class HistoryItemNode; + HistoryItemNode *nodeAt(const QPointF &pos) const; + HistoryItemNode *nodeAt(const QPointF &pos, HistoryItemNode *node) const; + QSGNode *createNodeTree(); void updateNodeTree(QSGNode *root); void addScatterplot(QSGNode *node, const HistoryItemNode *historyItemNode, float x, float y, float w, float h); - HistoryItemNode *m_firstNode, *m_currentNode; bool m_needsUpdate; }; diff --git a/main.cpp b/main.cpp index e8a826e..7027be8 100644 --- a/main.cpp +++ b/main.cpp @@ -72,8 +72,10 @@ int main(int argc, char **argv) &interactionHandler, SLOT(setSubsample(const arma::mat &))); QObject::connect(&interactionHandler, SIGNAL(subsampleChanged(const arma::mat &)), plot, SLOT(setXY(const arma::mat &))); - QObject::connect(subsamplePlot, SIGNAL(xyChanged(const arma::mat &)), + QObject::connect(subsamplePlot, SIGNAL(xyInteractivelyChanged(const arma::mat &)), history, SLOT(addHistoryItem(const arma::mat &))); + QObject::connect(history, SIGNAL(currentItemChanged(const arma::mat &)), + subsamplePlot, SLOT(setXY(const arma::mat &))); SelectionHandler selectionHandler(sampleIndices); QObject::connect(subsamplePlot, SIGNAL(selectionChanged(const QSet &)), @@ -107,7 +109,6 @@ int main(int argc, char **argv) plot->setColorScale(&colorScale); plot->setColorData(labels); - //interactionHandler.setSubsample(Ys); subsamplePlot->setXY(Ys); subsamplePlot->setColorData(labels(sampleIndices)); diff --git a/scatterplot.cpp b/scatterplot.cpp index 81a55b9..e22eafd 100644 --- a/scatterplot.cpp +++ b/scatterplot.cpp @@ -359,5 +359,5 @@ void Scatterplot::applyManipulation() m_xy.row(*it) = row; } - emit xyChanged(m_xy); + emit xyInteractivelyChanged(m_xy); } diff --git a/scatterplot.h b/scatterplot.h index 43bfc57..2dc031a 100644 --- a/scatterplot.h +++ b/scatterplot.h @@ -20,6 +20,7 @@ public: signals: void xyChanged(const arma::mat &XY) const; + void xyInteractivelyChanged(const arma::mat &XY) const; void colorDataChanged(const arma::vec &colorData) const; void selectionChanged(const QSet &selection) const; -- cgit v1.2.3