From b5ca997b2d2a64f955b78208d0362cba0278f8d3 Mon Sep 17 00:00:00 2001 From: Samuel Fadel Date: Thu, 11 Feb 2016 12:03:59 -0200 Subject: Modified the way the history interacts with other components. * Main class is now responsible for updating map components whenever the current map changes (even rewinding): this simplifies other objects because they don't have to know anything about how the data is being displayed later (no CP/RP juggling everywhere) * Added undo/reset actions to main view, including menu items * ProjectionHistory now has specific signals for each change happening to the history --- main.cpp | 40 +++++++++++++++++++++++----------------- main.h | 30 +++++++++++++++++++++++++----- main_view.qml | 29 +++++++++++++++++++++++++---- manipulationhandler.cpp | 10 ---------- manipulationhandler.h | 6 +----- projectionhistory.cpp | 8 ++++---- projectionhistory.h | 6 ++++-- 7 files changed, 82 insertions(+), 47 deletions(-) diff --git a/main.cpp b/main.cpp index f34f7be..cf752a0 100644 --- a/main.cpp +++ b/main.cpp @@ -172,21 +172,27 @@ int main(int argc, char **argv) ManipulationHandler manipulationHandler(X, cpIndices, m->projectionHistory); QObject::connect(m->cpPlot, &Scatterplot::xyInteractivelyChanged, &manipulationHandler, &ManipulationHandler::setCP); - QObject::connect(&manipulationHandler, &ManipulationHandler::cpChanged, - m->cpPlot, &Scatterplot::setXY); - QObject::connect(&manipulationHandler, &ManipulationHandler::rpChanged, - m->rpPlot, &Scatterplot::setXY); - QObject::connect(&manipulationHandler, &ManipulationHandler::rpChanged, - m->splat, &VoronoiSplat::setSites); - - // Update history whenever a new projection is computed + + // Update history whenever a new projection is computed... QObject::connect(&manipulationHandler, &ManipulationHandler::mapChanged, m->projectionHistory, &ProjectionHistory::addMap); + // ... and update visual components whenever the history changes + QObject::connect(m->projectionHistory, &ProjectionHistory::mapAdded, + m, &Main::updateMap); + QObject::connect(m->projectionHistory, &ProjectionHistory::undoPerformed, + m, &Main::updateMap); + QObject::connect(m->projectionHistory, &ProjectionHistory::resetPerformed, + m, &Main::updateMap); + // Keep both scatterplots and the splat scaled equally and relative to the // full plot MapScaleHandler mapScaleHandler; - QObject::connect(&manipulationHandler, &ManipulationHandler::mapChanged, + QObject::connect(m->projectionHistory, &ProjectionHistory::mapAdded, + &mapScaleHandler, &MapScaleHandler::scaleToMap); + QObject::connect(m->projectionHistory, &ProjectionHistory::undoPerformed, + &mapScaleHandler, &MapScaleHandler::scaleToMap); + QObject::connect(m->projectionHistory, &ProjectionHistory::resetPerformed, &mapScaleHandler, &MapScaleHandler::scaleToMap); QObject::connect(&mapScaleHandler, &MapScaleHandler::scaleChanged, m->cpPlot, &Scatterplot::setScale); @@ -239,7 +245,11 @@ int main(int argc, char **argv) // Recompute values whenever projection changes ProjectionObserver projectionObserver(X, cpIndices, m->projectionHistory); m->projectionObserver = &projectionObserver; - QObject::connect(&manipulationHandler, &ManipulationHandler::mapChanged, + QObject::connect(m->projectionHistory, &ProjectionHistory::mapAdded, + m->projectionObserver, &ProjectionObserver::setMap); + QObject::connect(m->projectionHistory, &ProjectionHistory::undoPerformed, + m->projectionObserver, &ProjectionObserver::setMap); + QObject::connect(m->projectionHistory, &ProjectionHistory::resetPerformed, m->projectionObserver, &ProjectionObserver::setMap); QObject::connect(m->projectionObserver, &ProjectionObserver::cpValuesChanged, m->cpPlot, &Scatterplot::setColorData); @@ -256,15 +266,11 @@ int main(int argc, char **argv) QObject::connect(&rpSelectionHandler, &SelectionHandler::selectionChanged, &projectionObserver, &ProjectionObserver::setRPSelection); - // Connect visual components (but not barcharts) to rewinding mechanism + // Connect projection components to rewinding mechanism QObject::connect(plotTC, &TransitionControl::tChanged, &manipulationHandler, &ManipulationHandler::setRewind); - QObject::connect(&manipulationHandler, &ManipulationHandler::cpRewound, - m->cpPlot, &Scatterplot::setXY); - QObject::connect(&manipulationHandler, &ManipulationHandler::rpRewound, - m->rpPlot, &Scatterplot::setXY); - QObject::connect(&manipulationHandler, &ManipulationHandler::rpRewound, - m->splat, &VoronoiSplat::setSites); + QObject::connect(&manipulationHandler, &ManipulationHandler::mapRewound, + m, &Main::updateMap); QObject::connect(plotTC, &TransitionControl::tChanged, m->projectionObserver, &ProjectionObserver::setRewind); diff --git a/main.h b/main.h index 7d94770..904b458 100644 --- a/main.h +++ b/main.h @@ -4,12 +4,13 @@ #include #include -#include "barchart.h" -#include "colormap.h" #include "colorscale.h" #include "continuouscolorscale.h" #include "projectionobserver.h" #include "projectionhistory.h" +#include "numericrange.h" +#include "barchart.h" +#include "colormap.h" #include "scatterplot.h" #include "voronoisplat.h" @@ -134,10 +135,18 @@ public: // Shared object that controls manipulation history ProjectionHistory *projectionHistory; Q_INVOKABLE void undoManipulation() { projectionHistory->undo(); } - Q_INVOKABLE void resetManipulation() { projectionHistory->undoAll(); } + Q_INVOKABLE void resetManipulation() { projectionHistory->reset(); } public slots: - void setCPIndices(const arma::uvec &indices) { m_cpIndices = indices; } + void setCPIndices(const arma::uvec &indices) { + m_cpIndices = indices; + + m_rpIndices.set_size(m_dataset.n_rows - m_cpIndices.n_elem); + NumericRange allIndices(0, m_dataset.n_rows); + std::set_symmetric_difference(allIndices.cbegin(), allIndices.cend(), + m_cpIndices.cbegin(), m_cpIndices.cend(), m_rpIndices.begin()); + } + void setCP(const arma::mat &cp) { if (cp.n_cols != 2 || cp.n_rows != m_cpIndices.n_elem) { @@ -147,6 +156,14 @@ public slots: m_cp = cp; } + void updateMap(const arma::mat &Y) { + cpPlot->setXY(Y.rows(m_cpIndices)); + + const arma::mat ®ularPoints = Y.rows(m_rpIndices); + rpPlot->setXY(regularPoints); + splat->setSites(regularPoints); + } + private: Main(QObject *parent = 0) : QObject(parent) @@ -163,8 +180,11 @@ private: , cpPlot(0) , rpPlot(0) , splat(0) + , projectionObserver(0) + , projectionHistory(0) { } + ~Main() {} ColorScale &getColorScale(ColorScaleType colorScaleType) { @@ -183,7 +203,7 @@ private: } arma::mat m_dataset, m_cp; - arma::uvec m_cpIndices; + arma::uvec m_cpIndices, m_rpIndices; std::string m_indicesSavePath, m_cpSavePath; }; diff --git a/main_view.qml b/main_view.qml index cfbea4f..b0cee3c 100644 --- a/main_view.qml +++ b/main_view.qml @@ -27,6 +27,12 @@ ApplicationWindow { MenuItem { action: quitAction } } + Menu { + title: "Edit" + MenuItem { action: undoManipulationAction } + MenuItem { action: resetManipulationAction } + } + Menu { title: "Select" MenuItem { action: selectRPsAction } @@ -79,6 +85,7 @@ ApplicationWindow { y: parent.y z: 1 anchors.fill: parent + glyphSize: 3.0 } Scatterplot { @@ -258,10 +265,10 @@ ApplicationWindow { id: cpGlyphSizeSpinBox maximumValue: 100 minimumValue: 6 - value: cpPlot.glyphSize() decimals: 1 stepSize: 1 - onValueChanged: cpPlot.setGlyphSize(this.value) + value: cpPlot.glyphSize + onValueChanged: cpPlot.glyphSize = this.value } Label { text: "Opacity:" } @@ -364,10 +371,10 @@ ApplicationWindow { id: rpGlyphSizeSpinBox maximumValue: 100 minimumValue: 2 - value: rpPlot.glyphSize() decimals: 1 stepSize: 1 - onValueChanged: rpPlot.setGlyphSize(this.value) + value: rpPlot.glyphSize + onValueChanged: rpPlot.glyphSize = this.value } Label { text: "Opacity:" } @@ -459,6 +466,20 @@ ApplicationWindow { onTriggered: Qt.quit() } + Action { + id: undoManipulationAction + text: "&Undo manipulation" + shortcut: "Ctrl+Z" + onTriggered: Main.undoManipulation() + } + + Action { + id: resetManipulationAction + text: "&Reset manipulation" + shortcut: "Ctrl+R" + onTriggered: Main.resetManipulation() + } + Action { id: selectRPsAction text: "&Regular points" diff --git a/manipulationhandler.cpp b/manipulationhandler.cpp index f764eaf..f561ad7 100644 --- a/manipulationhandler.cpp +++ b/manipulationhandler.cpp @@ -3,22 +3,16 @@ #include #include "mp.h" -#include "numericrange.h" ManipulationHandler::ManipulationHandler(const arma::mat &X, const arma::uvec &cpIndices, ProjectionHistory *history) : m_X(X) , m_cpIndices(cpIndices) - , m_rpIndices(X.n_rows - cpIndices.n_elem) , m_history(history) , m_technique(TECHNIQUE_LAMP) { Q_ASSERT(history); - - NumericRange allIndices(0, m_X.n_rows); - std::set_symmetric_difference(allIndices.cbegin(), allIndices.cend(), - m_cpIndices.cbegin(), m_cpIndices.cend(), m_rpIndices.begin()); } void ManipulationHandler::setCP(const arma::mat &Ys) @@ -39,8 +33,6 @@ void ManipulationHandler::setCP(const arma::mat &Ys) break; } - emit cpChanged(Y.rows(m_cpIndices)); - emit rpChanged(Y.rows(m_rpIndices)); emit mapChanged(Y); } @@ -51,7 +43,5 @@ void ManipulationHandler::setRewind(double t) } arma::mat Y = m_history->Y() * t + m_history->prev() * (1.0 - t); - emit cpRewound(Y.rows(m_cpIndices)); - emit rpRewound(Y.rows(m_rpIndices)); emit mapRewound(Y); } diff --git a/manipulationhandler.h b/manipulationhandler.h index 8bb8a98..b1aed61 100644 --- a/manipulationhandler.h +++ b/manipulationhandler.h @@ -26,11 +26,7 @@ public: void setTechnique(Technique technique) { m_technique = technique; } signals: - void cpChanged(const arma::mat &cpY) const; - void rpChanged(const arma::mat &rpY) const; void mapChanged(const arma::mat &Y) const; - void cpRewound(const arma::mat &cpY) const; - void rpRewound(const arma::mat &rpY) const; void mapRewound(const arma::mat &Y) const; public slots: @@ -39,7 +35,7 @@ public slots: private: arma::mat m_X; - arma::uvec m_cpIndices, m_rpIndices; + arma::uvec m_cpIndices; ProjectionHistory *m_history; Technique m_technique; }; diff --git a/projectionhistory.cpp b/projectionhistory.cpp index 24bf34e..bd55431 100644 --- a/projectionhistory.cpp +++ b/projectionhistory.cpp @@ -13,17 +13,17 @@ void ProjectionHistory::undo() m_hasPrev = false; m_Y = m_prevY; - emit historyChanged(m_Y); + emit undoPerformed(m_Y); } } -void ProjectionHistory::undoAll() +void ProjectionHistory::reset() { if (m_hasFirst) { m_hasPrev = false; m_Y = m_firstY; - emit historyChanged(m_Y); + emit resetPerformed(m_Y); } } @@ -41,5 +41,5 @@ void ProjectionHistory::addMap(const arma::mat &Y) m_firstY = m_Y; } - emit historyChanged(m_Y); + emit mapAdded(m_Y); } diff --git a/projectionhistory.h b/projectionhistory.h index 28a9b4b..9fe9ffc 100644 --- a/projectionhistory.h +++ b/projectionhistory.h @@ -20,10 +20,12 @@ public: bool hasPrev() const { return m_hasPrev; } void undo(); - void undoAll(); + void reset(); signals: - void historyChanged(const arma::mat ¤tY) const; + void undoPerformed(const arma::mat &prevY) const; + void resetPerformed(const arma::mat &firstY) const; + void mapAdded(const arma::mat &newY) const; public slots: void addMap(const arma::mat &Y); -- cgit v1.2.3