mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
statistics: show selected dives in scatter plot
As a visual feedback, show the selected dives in the scatter plot. React to application-wide selection changes. Currently, the dive list is deactivated while in statistics mode, but that may change. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
5c098eea29
commit
d85b321784
9 changed files with 68 additions and 8 deletions
|
@ -108,7 +108,7 @@ static const int scatterItemDiameter = 10;
|
||||||
static const int scatterItemBorder = 1;
|
static const int scatterItemBorder = 1;
|
||||||
|
|
||||||
ChartScatterItem::ChartScatterItem(StatsView &v, ChartZValue z) : HideableChartItem(v, z),
|
ChartScatterItem::ChartScatterItem(StatsView &v, ChartZValue z) : HideableChartItem(v, z),
|
||||||
positionDirty(false), textureDirty(false), highlighted(false)
|
positionDirty(false), textureDirty(false), highlight(Highlight::Unselected)
|
||||||
{
|
{
|
||||||
rect.setSize(QSizeF(static_cast<double>(scatterItemDiameter), static_cast<double>(scatterItemDiameter)));
|
rect.setSize(QSizeF(static_cast<double>(scatterItemDiameter), static_cast<double>(scatterItemDiameter)));
|
||||||
}
|
}
|
||||||
|
@ -138,12 +138,27 @@ static QSGTexture *createScatterTexture(StatsView &view, const QColor &color, co
|
||||||
// QApplication finished its thread leads to crashes. Therefore, these
|
// QApplication finished its thread leads to crashes. Therefore, these
|
||||||
// are now normal pointers and the texture objects are leaked.
|
// are now normal pointers and the texture objects are leaked.
|
||||||
static QSGTexture *scatterItemTexture = nullptr;
|
static QSGTexture *scatterItemTexture = nullptr;
|
||||||
|
static QSGTexture *scatterItemSelectedTexture = nullptr;
|
||||||
static QSGTexture *scatterItemHighlightedTexture = nullptr;
|
static QSGTexture *scatterItemHighlightedTexture = nullptr;
|
||||||
|
|
||||||
|
QSGTexture *ChartScatterItem::getTexture() const
|
||||||
|
{
|
||||||
|
switch (highlight) {
|
||||||
|
default:
|
||||||
|
case Highlight::Unselected:
|
||||||
|
return scatterItemTexture;
|
||||||
|
case Highlight::Selected:
|
||||||
|
return scatterItemSelectedTexture;
|
||||||
|
case Highlight::Highlighted:
|
||||||
|
return scatterItemHighlightedTexture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ChartScatterItem::render()
|
void ChartScatterItem::render()
|
||||||
{
|
{
|
||||||
if (!scatterItemTexture) {
|
if (!scatterItemTexture) {
|
||||||
scatterItemTexture = createScatterTexture(view, fillColor, borderColor);
|
scatterItemTexture = createScatterTexture(view, fillColor, borderColor);
|
||||||
|
scatterItemSelectedTexture = createScatterTexture(view, selectedColor, selectedBorderColor);
|
||||||
scatterItemHighlightedTexture = createScatterTexture(view, highlightedColor, highlightedBorderColor);
|
scatterItemHighlightedTexture = createScatterTexture(view, highlightedColor, highlightedBorderColor);
|
||||||
}
|
}
|
||||||
if (!node) {
|
if (!node) {
|
||||||
|
@ -153,7 +168,7 @@ void ChartScatterItem::render()
|
||||||
}
|
}
|
||||||
updateVisible();
|
updateVisible();
|
||||||
if (textureDirty) {
|
if (textureDirty) {
|
||||||
node->node->setTexture(highlighted ? scatterItemHighlightedTexture : scatterItemTexture);
|
node->node->setTexture(getTexture());
|
||||||
textureDirty = false;
|
textureDirty = false;
|
||||||
}
|
}
|
||||||
if (positionDirty) {
|
if (positionDirty) {
|
||||||
|
@ -181,11 +196,11 @@ bool ChartScatterItem::contains(QPointF point) const
|
||||||
return squareDist(point, rect.center()) <= (scatterItemDiameter / 2.0) * (scatterItemDiameter / 2.0);
|
return squareDist(point, rect.center()) <= (scatterItemDiameter / 2.0) * (scatterItemDiameter / 2.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChartScatterItem::setHighlight(bool highlightedIn)
|
void ChartScatterItem::setHighlight(Highlight highlightIn)
|
||||||
{
|
{
|
||||||
if (highlighted == highlightedIn)
|
if (highlight == highlightIn)
|
||||||
return;
|
return;
|
||||||
highlighted = highlightedIn;
|
highlight = highlightIn;
|
||||||
textureDirty = true;
|
textureDirty = true;
|
||||||
markDirty();
|
markDirty();
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,16 +174,23 @@ public:
|
||||||
ChartScatterItem(StatsView &v, ChartZValue z);
|
ChartScatterItem(StatsView &v, ChartZValue z);
|
||||||
~ChartScatterItem();
|
~ChartScatterItem();
|
||||||
|
|
||||||
|
// Currently, there is no highlighted and selected status.
|
||||||
|
enum class Highlight {
|
||||||
|
Unselected,
|
||||||
|
Selected,
|
||||||
|
Highlighted
|
||||||
|
};
|
||||||
void setPos(QPointF pos); // Specifies the *center* of the item.
|
void setPos(QPointF pos); // Specifies the *center* of the item.
|
||||||
void setHighlight(bool highlight); // In the future, support different kinds of scatter items.
|
void setHighlight(Highlight highlight); // In the future, support different kinds of scatter items.
|
||||||
void render() override; // Only call on render thread!
|
void render() override; // Only call on render thread!
|
||||||
QRectF getRect() const;
|
QRectF getRect() const;
|
||||||
bool contains(QPointF point) const;
|
bool contains(QPointF point) const;
|
||||||
private:
|
private:
|
||||||
|
QSGTexture *getTexture() const;
|
||||||
QRectF rect;
|
QRectF rect;
|
||||||
QSizeF textureSize;
|
QSizeF textureSize;
|
||||||
bool positionDirty, textureDirty;
|
bool positionDirty, textureDirty;
|
||||||
bool highlighted;
|
Highlight highlight;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Implementation detail of templates - move to serparate header file
|
// Implementation detail of templates - move to serparate header file
|
||||||
|
|
|
@ -27,6 +27,7 @@ ScatterSeries::~ScatterSeries()
|
||||||
ScatterSeries::Item::Item(StatsView &view, ScatterSeries *series, dive *d, double pos, double value) :
|
ScatterSeries::Item::Item(StatsView &view, ScatterSeries *series, dive *d, double pos, double value) :
|
||||||
item(view.createChartItem<ChartScatterItem>(ChartZValue::Series)),
|
item(view.createChartItem<ChartScatterItem>(ChartZValue::Series)),
|
||||||
d(d),
|
d(d),
|
||||||
|
selected(d->selected),
|
||||||
pos(pos),
|
pos(pos),
|
||||||
value(value)
|
value(value)
|
||||||
{
|
{
|
||||||
|
@ -40,7 +41,11 @@ void ScatterSeries::Item::updatePosition(ScatterSeries *series)
|
||||||
|
|
||||||
void ScatterSeries::Item::highlight(bool highlight)
|
void ScatterSeries::Item::highlight(bool highlight)
|
||||||
{
|
{
|
||||||
item->setHighlight(highlight);
|
ChartScatterItem::Highlight status = d->selected ?
|
||||||
|
ChartScatterItem::Highlight::Selected : ChartScatterItem::Highlight::Unselected;
|
||||||
|
if (highlight)
|
||||||
|
status = ChartScatterItem::Highlight::Highlighted;
|
||||||
|
item->setHighlight(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScatterSeries::append(dive *d, double pos, double value)
|
void ScatterSeries::append(dive *d, double pos, double value)
|
||||||
|
@ -164,3 +169,15 @@ void ScatterSeries::unhighlight()
|
||||||
items[idx].highlight(false);
|
items[idx].highlight(false);
|
||||||
highlighted.clear();
|
highlighted.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScatterSeries::divesSelected(const QVector<dive *> &)
|
||||||
|
{
|
||||||
|
for (Item &item: items) {
|
||||||
|
if (item.selected != item.d->selected) {
|
||||||
|
item.selected = item.d->selected;
|
||||||
|
int idx = &item - &items[0];
|
||||||
|
bool highlight = std::find(highlighted.begin(), highlighted.end(), idx) != highlighted.end();
|
||||||
|
item.highlight(highlight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ private:
|
||||||
struct Item {
|
struct Item {
|
||||||
ChartItemPtr<ChartScatterItem> item;
|
ChartItemPtr<ChartScatterItem> item;
|
||||||
dive *d;
|
dive *d;
|
||||||
|
bool selected;
|
||||||
double pos, value;
|
double pos, value;
|
||||||
Item(StatsView &view, ScatterSeries *series, dive *d, double pos, double value);
|
Item(StatsView &view, ScatterSeries *series, dive *d, double pos, double value);
|
||||||
void updatePosition(ScatterSeries *series);
|
void updatePosition(ScatterSeries *series);
|
||||||
|
@ -47,6 +48,7 @@ private:
|
||||||
std::vector<int> highlighted;
|
std::vector<int> highlighted;
|
||||||
const StatsVariable &varX;
|
const StatsVariable &varX;
|
||||||
const StatsVariable &varY;
|
const StatsVariable &varY;
|
||||||
|
void divesSelected(const QVector<dive *> &) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
inline const QColor backgroundColor(Qt::white);
|
inline const QColor backgroundColor(Qt::white);
|
||||||
inline const QColor fillColor(0x44, 0x76, 0xaa);
|
inline const QColor fillColor(0x44, 0x76, 0xaa);
|
||||||
inline const QColor borderColor(0x66, 0xb2, 0xff);
|
inline const QColor borderColor(0x66, 0xb2, 0xff);
|
||||||
|
inline const QColor selectedColor(0xaa, 0x76, 0x44);
|
||||||
|
inline const QColor selectedBorderColor(0xff, 0xb2, 0x66);
|
||||||
inline const QColor highlightedColor(Qt::yellow);
|
inline const QColor highlightedColor(Qt::yellow);
|
||||||
inline const QColor highlightedBorderColor(0xaa, 0xaa, 0x22);
|
inline const QColor highlightedBorderColor(0xaa, 0xaa, 0x22);
|
||||||
inline const QColor darkLabelColor(Qt::black);
|
inline const QColor darkLabelColor(Qt::black);
|
||||||
|
|
|
@ -16,3 +16,7 @@ QPointF StatsSeries::toScreen(QPointF p)
|
||||||
return xAxis && yAxis ? QPointF(xAxis->toScreen(p.x()), yAxis->toScreen(p.y()))
|
return xAxis && yAxis ? QPointF(xAxis->toScreen(p.x()), yAxis->toScreen(p.y()))
|
||||||
: QPointF(0.0, 0.0);
|
: QPointF(0.0, 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StatsSeries::divesSelected(const QVector<dive *> &)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
class StatsAxis;
|
class StatsAxis;
|
||||||
class StatsView;
|
class StatsView;
|
||||||
|
struct dive;
|
||||||
|
|
||||||
class StatsSeries {
|
class StatsSeries {
|
||||||
public:
|
public:
|
||||||
|
@ -17,6 +18,7 @@ public:
|
||||||
virtual bool hover(QPointF pos) = 0; // Called on mouse movement. Return true if an item of this series is highlighted.
|
virtual bool hover(QPointF pos) = 0; // Called on mouse movement. Return true if an item of this series is highlighted.
|
||||||
virtual void unhighlight() = 0; // Unhighlight any highlighted item.
|
virtual void unhighlight() = 0; // Unhighlight any highlighted item.
|
||||||
virtual void selectItemsUnderMouse(const QPointF &pos) = 0;
|
virtual void selectItemsUnderMouse(const QPointF &pos) = 0;
|
||||||
|
virtual void divesSelected(const QVector<dive *> &dives);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
StatsView &view;
|
StatsView &view;
|
||||||
|
|
|
@ -46,6 +46,7 @@ StatsView::StatsView(QQuickItem *parent) : QQuickItem(parent),
|
||||||
connect(&diveListNotifier, &DiveListNotifier::divesDeleted, this, &StatsView::replotIfVisible);
|
connect(&diveListNotifier, &DiveListNotifier::divesDeleted, this, &StatsView::replotIfVisible);
|
||||||
connect(&diveListNotifier, &DiveListNotifier::dataReset, this, &StatsView::replotIfVisible);
|
connect(&diveListNotifier, &DiveListNotifier::dataReset, this, &StatsView::replotIfVisible);
|
||||||
connect(&diveListNotifier, &DiveListNotifier::settingsChanged, this, &StatsView::replotIfVisible);
|
connect(&diveListNotifier, &DiveListNotifier::settingsChanged, this, &StatsView::replotIfVisible);
|
||||||
|
connect(&diveListNotifier, &DiveListNotifier::divesSelected, this, &StatsView::divesSelected);
|
||||||
|
|
||||||
setAcceptHoverEvents(true);
|
setAcceptHoverEvents(true);
|
||||||
setAcceptedMouseButtons(Qt::LeftButton);
|
setAcceptedMouseButtons(Qt::LeftButton);
|
||||||
|
@ -345,6 +346,15 @@ void StatsView::replotIfVisible()
|
||||||
plot(state);
|
plot(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StatsView::divesSelected(const QVector<dive *> &dives)
|
||||||
|
{
|
||||||
|
if (isVisible()) {
|
||||||
|
for (auto &series: series)
|
||||||
|
series->divesSelected(dives);
|
||||||
|
}
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
void StatsView::mouseMoveEvent(QMouseEvent *event)
|
void StatsView::mouseMoveEvent(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
if (!draggedItem)
|
if (!draggedItem)
|
||||||
|
|
|
@ -64,6 +64,7 @@ public:
|
||||||
void deleteChartItem(ChartItemPtr<T> &item);
|
void deleteChartItem(ChartItemPtr<T> &item);
|
||||||
private slots:
|
private slots:
|
||||||
void replotIfVisible();
|
void replotIfVisible();
|
||||||
|
void divesSelected(const QVector<dive *> &dives);
|
||||||
private:
|
private:
|
||||||
// QtQuick related things
|
// QtQuick related things
|
||||||
bool backgroundDirty;
|
bool backgroundDirty;
|
||||||
|
|
Loading…
Add table
Reference in a new issue