diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 67472a6..61ed56b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -71,6 +71,7 @@ jobs: conan-password: ${{secrets.LKEB_UPLOAD_USER_PASSWORD}} conan-pem: ${{secrets.LKEB_UPLOAD_CERT_CHAIN}} rs_ssh_key: ${{ secrets.RULESSUPPORT_DEPLOY_KEY }} + sentry-upload: startsWith(github.ref, 'refs/heads/release/') sentry-url: ${{secrets.LKEB_SENTRY_URL }} sentry-org: ${{secrets.LKEB_SENTRY_ORG }} sentry-project: ${{secrets.LKEB_SENTRY_PROJECT }} diff --git a/src/ColoringAction.cpp b/src/ColoringAction.cpp index 18e04e8..c3fca1f 100644 --- a/src/ColoringAction.cpp +++ b/src/ColoringAction.cpp @@ -127,24 +127,29 @@ ColoringAction::ColoringAction(QObject* parent, const QString& title) : connect(&_scatterplotPlugin->getPositionDataset(), &Dataset::childAdded, this, &ColoringAction::updateColorByActionOptions); connect(&_scatterplotPlugin->getPositionDataset(), &Dataset::childRemoved, this, &ColoringAction::updateColorByActionOptions); - connect(&_scatterplotPlugin->getScatterplotWidget(), &ScatterplotWidget::renderModeChanged, this, &ColoringAction::updateScatterPlotWidgetColors); - connect(&_scatterplotPlugin->getScatterplotWidget(), &ScatterplotWidget::coloringModeChanged, this, &ColoringAction::updateScatterPlotWidgetColors); + connect(&_scatterplotPlugin->getScatterplotWidget(), &ScatterplotWidget::coloringModeChanged, this, [this](const ScatterplotWidget::ColoringMode& coloringMode) { + updateScatterPlotWidgetColors(); + updateColorMapActionsReadOnly(); + }); + + connect(&_scatterplotPlugin->getScatterplotWidget(), &ScatterplotWidget::renderModeChanged, this, [this](const ScatterplotWidget::RenderMode& renderMode) { + updateScatterPlotWidgetColors(); + updateColorMapActionsReadOnly(); + }); - connect(&_dimensionAction, &DimensionPickerAction::currentDimensionIndexChanged, this, &ColoringAction::updateScatterPlotWidgetColors); - connect(&_dimensionAction, &DimensionPickerAction::currentDimensionIndexChanged, this, &ColoringAction::updateColorMapActionScalarRange); + connect(&_dimensionAction, &DimensionPickerAction::currentDimensionIndexChanged, this, [this](const int32_t& currentDimensionIndex) { + updateScatterPlotWidgetColors(); + updateColorMapActionsReadOnly(); + updateColorMapActionScalarRange(); + }); connect(&_constantColorAction, &ColorAction::colorChanged, this, &ColoringAction::updateScatterplotWidgetColorMap); connect(&_colorMap1DAction, &ColorMapAction::imageChanged, this, &ColoringAction::updateScatterplotWidgetColorMap); connect(&_colorMap2DAction, &ColorMapAction::imageChanged, this, &ColoringAction::updateScatterplotWidgetColorMap); - connect(&_scatterplotPlugin->getScatterplotWidget(), &ScatterplotWidget::coloringModeChanged, this, &ColoringAction::updateScatterplotWidgetColorMap); - connect(&_scatterplotPlugin->getScatterplotWidget(), &ScatterplotWidget::renderModeChanged, this, &ColoringAction::updateScatterplotWidgetColorMap); connect(&_colorMap1DAction.getRangeAction(ColorMapAction::Axis::X), &DecimalRangeAction::rangeChanged, this, &ColoringAction::updateScatterPlotWidgetColorMapRange); connect(&_colorMap2DAction.getRangeAction(ColorMapAction::Axis::X), &DecimalRangeAction::rangeChanged, this, &ColoringAction::updateScatterPlotWidgetColorMapRange); - connect(&_scatterplotPlugin->getScatterplotWidget(), &ScatterplotWidget::coloringModeChanged, this, &ColoringAction::updateColorMapActionsReadOnly); - connect(&_scatterplotPlugin->getScatterplotWidget(), &ScatterplotWidget::renderModeChanged, this, &ColoringAction::updateColorMapActionsReadOnly); - const auto updateReadOnly = [this]() { setEnabled(_scatterplotPlugin->getPositionDataset().isValid() && _scatterplotPlugin->getScatterplotWidget().getRenderMode() == ScatterplotWidget::SCATTERPLOT); }; @@ -276,7 +281,8 @@ void ColoringAction::updateScatterplotWidgetColorMap() { case ScatterplotWidget::SCATTERPLOT: { - if (_colorByAction.getCurrentIndex() == 0) { + const int32_t currentIndex = _colorByAction.getCurrentIndex(); + if (currentIndex == 0) { QPixmap colorPixmap(1, 1); colorPixmap.fill(_constantColorAction.getColor()); @@ -285,7 +291,7 @@ void ColoringAction::updateScatterplotWidgetColorMap() scatterplotWidget.setScalarEffect(PointEffect::Color); scatterplotWidget.setColoringMode(ScatterplotWidget::ColoringMode::Constant); } - else if (_colorByAction.getCurrentIndex() == 1) { + else if (currentIndex == 1) { scatterplotWidget.setColorMap(_colorMap2DAction.getColorMapImage()); scatterplotWidget.setScalarEffect(PointEffect::Color2D); scatterplotWidget.setColoringMode(ScatterplotWidget::ColoringMode::Scatter); diff --git a/src/ScatterplotPlugin.cpp b/src/ScatterplotPlugin.cpp index 8a6610d..a7aed60 100644 --- a/src/ScatterplotPlugin.cpp +++ b/src/ScatterplotPlugin.cpp @@ -238,12 +238,30 @@ ScatterplotPlugin::ScatterplotPlugin(const PluginFactory* factory) : }); } else { - - // Use the clusters set for points color - dropRegions << new DropWidget::DropRegion(this, "Color", description, "palette", true, [this, candidateDataset]() { - _settingsAction.getColoringAction().addColorDataset(candidateDataset); - _settingsAction.getColoringAction().setCurrentColorDataset(candidateDataset); - }); + if (candidateDataset.isValid()) + { + // Check to set whether the number of data points comprised throughout all clusters is the same number + // as the number of data points in the dataset we are trying to color + int totalNumIndices = 0; + for (const Cluster& cluster : candidateDataset->getClusters()) + { + totalNumIndices += cluster.getIndices().size(); + } + + if (totalNumIndices == _positionDataset->getNumPoints()) + { + // Use the clusters set for points color + dropRegions << new DropWidget::DropRegion(this, "Color", description, "palette", true, [this, candidateDataset]() { + _settingsAction.getColoringAction().addColorDataset(candidateDataset); + _settingsAction.getColoringAction().setCurrentColorDataset(candidateDataset); + }); + } + else + { + // Number of indices in clusters doesn't match point dataset + dropRegions << new DropWidget::DropRegion(this, "Incompatible data", "Cluster data does not match number of data points", "exclamation-circle", false); + } + } } } else { @@ -264,8 +282,6 @@ ScatterplotPlugin::ScatterplotPlugin(const PluginFactory* factory) : getLearningCenterAction().addVideos(QStringList({ "Practitioner", "Developer" })); setOverlayActionsTargetWidget(_scatterPlotWidget); - - } ScatterplotPlugin::~ScatterplotPlugin() @@ -376,6 +392,10 @@ void ScatterplotPlugin::init() connect(&_settingsAction.getColoringAction().getColorByAction(), &OptionAction::currentIndexChanged, this, &ScatterplotPlugin::updateHeadsUpDisplay); connect(&_settingsAction.getPlotAction().getPointPlotAction().getSizeAction(), &ScalarAction::sourceDataChanged, this, &ScatterplotPlugin::updateHeadsUpDisplay); connect(&_settingsAction.getPlotAction().getPointPlotAction().getOpacityAction(), &ScalarAction::sourceDataChanged, this, &ScatterplotPlugin::updateHeadsUpDisplay); + + updateHeadsUpDisplayTextColor(); + + connect(&_settingsAction.getMiscellaneousAction().getBackgroundColorAction(), &ColorAction::colorChanged, this, &ScatterplotPlugin::updateHeadsUpDisplayTextColor); } void ScatterplotPlugin::loadData(const Datasets& datasets) @@ -795,9 +815,6 @@ void ScatterplotPlugin::loadColors(const Dataset& clusters) if (!clusters.isValid() || !_positionDataset.isValid()) return; - // Mapping from local to global indices - std::vector globalIndices; - // Get global indices from the position dataset int totalNumPoints = 0; if (_positionDataset->isDerivedData()) @@ -805,15 +822,17 @@ void ScatterplotPlugin::loadColors(const Dataset& clusters) else totalNumPoints = _positionDataset->getFullDataset()->getNumPoints(); + // Mapping from local to global indices + std::vector globalIndices; _positionDataset->getGlobalIndices(globalIndices); // Generate color buffer for global and local colors std::vector globalColors(totalNumPoints); - std::vector localColors(_positions.size()); + std::vector localColors(_numPoints); const auto& clusterVec = clusters->getClusters(); - if (totalNumPoints == _positions.size() && clusterVec.size() == totalNumPoints) + if (totalNumPoints == _numPoints && clusterVec.size() == totalNumPoints) { for (size_t i = 0; i < static_cast(clusterVec.size()); i++) { @@ -824,14 +843,15 @@ void ScatterplotPlugin::loadColors(const Dataset& clusters) } } - else + else if(globalIndices.size() == _numPoints) { // Loop over all clusters and populate global colors for (const auto& cluster : clusterVec) { - const auto color = cluster.getColor(); + const auto color = cluster.getColor(); + const auto colVec = Vector3f(color.redF(), color.greenF(), color.blueF()); for (const auto& index : cluster.getIndices()) - globalColors[index] = Vector3f(color.redF(), color.greenF(), color.blueF()); + globalColors[index] = colVec; } @@ -993,6 +1013,19 @@ void ScatterplotPlugin::updateHeadsUpDisplay() } } +void ScatterplotPlugin::updateHeadsUpDisplayTextColor() +{ + if (auto headsUpDisplayWidget = getWidget().findChild("HeadsUpDisplayWidget")) { + if (auto headsUpDisplayWidgetTreeView = headsUpDisplayWidget->findChild("TreeView")) { + QPalette palette = headsUpDisplayWidgetTreeView->palette(); + + palette.setColor(QPalette::Text, _settingsAction.getMiscellaneousAction().getBackgroundColorAction().getColor().lightnessF() > .5f ? Qt::black : Qt::white); + + headsUpDisplayWidgetTreeView->setPalette(palette); + } + } +} + void ScatterplotPlugin::fromVariantMap(const QVariantMap& variantMap) { ViewPlugin::fromVariantMap(variantMap); @@ -1014,6 +1047,8 @@ void ScatterplotPlugin::fromVariantMap(const QVariantMap& variantMap) _scatterPlotWidget->update(); } + + updateHeadsUpDisplayTextColor(); } QVariantMap ScatterplotPlugin::toVariantMap() const diff --git a/src/ScatterplotPlugin.h b/src/ScatterplotPlugin.h index 4ef3c3f..e795c72 100644 --- a/src/ScatterplotPlugin.h +++ b/src/ScatterplotPlugin.h @@ -95,6 +95,7 @@ class ScatterplotPlugin : public ViewPlugin void updateSelection(); void updateHeadsUpDisplay(); + void updateHeadsUpDisplayTextColor(); public: // Serialization diff --git a/src/ScatterplotWidget.cpp b/src/ScatterplotWidget.cpp index 535c985..ff6f6f8 100644 --- a/src/ScatterplotWidget.cpp +++ b/src/ScatterplotWidget.cpp @@ -41,6 +41,7 @@ ScatterplotWidget::ScatterplotWidget(mv::plugin::ViewPlugin* parentPlugin) : _pointRenderer(this), _isInitialized(false), _renderMode(SCATTERPLOT), + _scalarEffect(PointEffect::Color), _backgroundColor(255, 255, 255, 255), _coloringMode(ColoringMode::Constant), _dataRectangleAction(this, "Data rectangle"), @@ -334,7 +335,7 @@ void ScatterplotWidget::setScalars(const std::vector& scalars) void ScatterplotWidget::setColors(const std::vector& colors) { _pointRenderer.setColors(colors); - _pointRenderer.setScalarEffect(None); + setScalarEffect(PointEffect::None); update(); } @@ -367,6 +368,7 @@ void ScatterplotWidget::setPointScaling(mv::gui::PointScaling scalingMode) void ScatterplotWidget::setScalarEffect(PointEffect effect) { _pointRenderer.setScalarEffect(effect); + _scalarEffect = effect; update(); } @@ -621,7 +623,7 @@ void ScatterplotWidget::initializeGL() _densityRenderer.init(); // Set a default color map for both renderers - _pointRenderer.setScalarEffect(PointEffect::Color); + _pointRenderer.setScalarEffect(_scalarEffect); _pointRenderer.setPointScaling(Absolute); _pointRenderer.setSelectionOutlineColor(Vector3f(1, 0, 0)); diff --git a/src/ScatterplotWidget.h b/src/ScatterplotWidget.h index cf0618a..9e73b49 100644 --- a/src/ScatterplotWidget.h +++ b/src/ScatterplotWidget.h @@ -296,6 +296,7 @@ private slots: private: bool _isInitialized; /** Boolean determining whether the widget it properly initialized or not */ RenderMode _renderMode; /** Current render mode */ + PointEffect _scalarEffect; /** Current scalar effect */ QColor _backgroundColor; /** Background color */ ColoringMode _coloringMode; /** Type of point/density coloring */ DecimalRectangleAction _dataRectangleAction; /** Rectangle action for the bounds of the loaded data */