From 7237060eb71916092f78bd52df82ecd9bcbf17fe Mon Sep 17 00:00:00 2001 From: Alexander Vieth Date: Tue, 16 Apr 2024 11:44:11 +0200 Subject: [PATCH 01/19] Add unity build option (#10) * Add unity build option * Update conanfile.py --- .gitignore | 1 + CMakeLists.txt | 42 +++++++++++++++++++++++++++++++++++++++--- conanfile.py | 3 +++ 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 6de35bc..f572591 100644 --- a/.gitignore +++ b/.gitignore @@ -534,3 +534,4 @@ FodyWeavers.xsd Build/ .DS_Store +*.bak diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f62b58..77f2630 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,17 @@ cmake_minimum_required(VERSION 3.17) +option(MV_UNITY_BUILD "Combine target source files into batches for faster compilation" OFF) + +# ----------------------------------------------------------------------------- +# SpectralView Plugin +# ----------------------------------------------------------------------------- set(SVPLUGIN "SpectralViewPlugin") PROJECT(${SVPLUGIN}) +# ----------------------------------------------------------------------------- +# CMake Options +# ----------------------------------------------------------------------------- set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) @@ -16,6 +24,9 @@ if(MSVC) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD") endif(MSVC) +# ----------------------------------------------------------------------------- +# Set install directory +# ----------------------------------------------------------------------------- # Check if the directory to the ManiVault installation has been provided if(NOT DEFINED MV_INSTALL_DIR) set(MV_INSTALL_DIR "" CACHE PATH "Directory where ManiVault is installed") @@ -23,8 +34,14 @@ if(NOT DEFINED MV_INSTALL_DIR) endif() file(TO_CMAKE_PATH ${MV_INSTALL_DIR} MV_INSTALL_DIR) +# ----------------------------------------------------------------------------- +# Dependencies +# ----------------------------------------------------------------------------- find_package(Qt6 6.3.1 COMPONENTS Widgets WebEngineWidgets Concurrent REQUIRED) +# ----------------------------------------------------------------------------- +# Source files +# ----------------------------------------------------------------------------- set(PLUGIN src/SpectralViewPlugin.h src/SpectralViewPlugin.cpp @@ -95,16 +112,29 @@ source_group(Widget FILES ${WIDGETS}) source_group(Web FILES ${WEB}) source_group(Aux FILES ${AUX}) +# ----------------------------------------------------------------------------- +# CMake Target +# ----------------------------------------------------------------------------- add_library(${SVPLUGIN} SHARED ${SOURCES} ${WEB} ${AUX} ${RESOURCE_FILES}) -qt_wrap_cpp(SV_PARAMETERS_MOC ${PLUGIN_MOC_HEADERS} TARGET ${SVPLUGIN}) -target_sources(${SVPLUGIN} PRIVATE ${SV_PARAMETERS_MOC}) - +# ----------------------------------------------------------------------------- +# Target include directories +# ----------------------------------------------------------------------------- target_include_directories(${SVPLUGIN} PRIVATE "${MV_INSTALL_DIR}/$/include/") +# ----------------------------------------------------------------------------- +# Target properties +# ----------------------------------------------------------------------------- # Request C++17 target_compile_features(${SVPLUGIN} PRIVATE cxx_std_17) +if(MV_UNITY_BUILD) + set_target_properties(${SVPLUGIN} PROPERTIES UNITY_BUILD ON) +endif() + +# ----------------------------------------------------------------------------- +# Target library linking +# ----------------------------------------------------------------------------- target_link_libraries(${SVPLUGIN} PRIVATE Qt6::Widgets) target_link_libraries(${SVPLUGIN} PRIVATE Qt6::WebEngineWidgets) target_link_libraries(${SVPLUGIN} PRIVATE Qt6::Concurrent) @@ -123,6 +153,9 @@ target_link_libraries(${SVPLUGIN} PRIVATE "${POINTDATA_LINK_LIBRARY}") target_link_libraries(${SVPLUGIN} PRIVATE "${IMAGEDATA_LINK_LIBRARY}") target_link_libraries(${SVPLUGIN} PRIVATE "${CLUSTERDATA_LINK_LIBRARY}") +# ----------------------------------------------------------------------------- +# Target installation +# ----------------------------------------------------------------------------- install(TARGETS ${SVPLUGIN} RUNTIME DESTINATION Plugins COMPONENT PLUGINS # Windows .dll LIBRARY DESTINATION Plugins COMPONENT PLUGINS # Linux/Mac .so @@ -135,6 +168,9 @@ add_custom_command(TARGET ${SVPLUGIN} POST_BUILD --prefix ${MV_INSTALL_DIR}/$ ) +# ----------------------------------------------------------------------------- +# Miscellaneous +# ----------------------------------------------------------------------------- # Automatically set the debug environment (command + working directory) for MSVC in debug mode if(MSVC) set_property(TARGET ${SVPLUGIN} PROPERTY VS_DEBUGGER_WORKING_DIRECTORY $,${MV_INSTALL_DIR}/debug,${MV_INSTALL_DIR}/release>) diff --git a/conanfile.py b/conanfile.py index 048f98f..3695369 100644 --- a/conanfile.py +++ b/conanfile.py @@ -103,6 +103,9 @@ def generate(self): # Give the installation directory to CMake tc.variables["MV_INSTALL_DIR"] = self.install_dir + # Set some build options + tc.variables["MV_UNITY_BUILD"] = "ON" + tc.generate() def _configure_cmake(self): From e39865ffa0ac6c36d1c26e0df0b07f41cb28db22 Mon Sep 17 00:00:00 2001 From: Alexander Vieth Date: Fri, 19 Apr 2024 15:03:10 +0200 Subject: [PATCH 02/19] Add some more usage instructions --- Readme.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 81c48b3..70cc73d 100644 --- a/Readme.md +++ b/Readme.md @@ -13,10 +13,14 @@ git clone git@github.com:ManiVaultStudio/SpectralViewPlugin.git ## Usage How to use: -0. Load a data set, e.g. with the [ENVI](https://github.com/ManiVaultStudio/ENVILoader) or [general image](https://github.com/ManiVaultStudio/ImageLoaderPlugin) loader plugins. **Caveat**: It's encouraged to define dimension names that encode the wavelength of the respective image channel, e.g. "304.7", "1020" or "304.7 nm". This wavelength information will be displayed in the viewer. If no dimension names are given when loading the data, ManiVault automatically numbers the dimensions, i.e. "Dim 0", etc.; in this case, the dimension numbers are displayed on the x-Axis instead of wavelengths. +0. Load a data set, e.g. with the [ENVI](https://github.com/ManiVaultStudio/ENVILoader) or [general image](https://github.com/ManiVaultStudio/ImageLoaderPlugin) loader plugins. 1. Open a spectral viewer and drag & drop the point data into the viewer. At this point you will not see anything yet. Open data in another viewer, e.g. an image viewer, and make a selection. Now you'll see the average spectral values for the selected points. 2. Create cluster for your data set, e.g. using an analysis like [mean shift clustering](https://github.com/ManiVaultStudio/MeanShiftClustering) or through manual annotation in the [scatterplot](https://github.com/ManiVaultStudio/Scatterplot). Drag & drop the cluster data into the main view of the spectral viewer. 3. Perform a mapping like the "Spectral Angle Mapping" algorithm for a selected cluster. This will cerate a new image data set. +> **Caveats**: +> - This viewer only handles point data sets that have a image data set as a child. +> - It's encouraged to define dimension names that encode the wavelength of the respective image channel, e.g. "304.7", "1020" or "304.7 nm". This wavelength information will be displayed in the viewer. If no dimension names are given when loading the data, ManiVault automatically numbers the dimensions, i.e. "Dim 0", etc.; in this case, the dimension numbers are displayed on the x-Axis instead of wavelengths. +> - This viewer expects positive data values (as is common in spectral intensities); negative values might lead to unwanted behaviour. ## References Based on Popa et al. "Visual Analysis of RIS Data for Endmember Selection" (2022): From 75e0da8fa6514d74fe4318e3c973ee0e4d3fa851 Mon Sep 17 00:00:00 2001 From: Alexander Vieth Date: Fri, 19 Apr 2024 15:34:15 +0200 Subject: [PATCH 03/19] Ensure dimension name strings are valid floating points --- src/LineplotWidget.cpp | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/LineplotWidget.cpp b/src/LineplotWidget.cpp index f715522..624c0b8 100644 --- a/src/LineplotWidget.cpp +++ b/src/LineplotWidget.cpp @@ -60,7 +60,7 @@ void LineplotWidget::setData(const std::vector& yVals, const std::vector< // check if dimension name contains a) only numbers or "." b) numbers and trailing units c) text // if a) use the number b) remove the unit c) replace names with numeric dimension count - // https://godbolt.org/z/E4b1GbM19 + // https://godbolt.org/z/8Yeej4cj6 auto determineNumberAndExtract = [](const std::string & input) -> std::pair { std::regex pattern(R"(^\D*?\s*?(\d+(\.\d+)?)\D*?$)"); std::smatch match; @@ -71,6 +71,21 @@ void LineplotWidget::setData(const std::vector& yVals, const std::vector< return std::make_pair(false, ""); }; + // add a decimal point if there is none + auto unsureFloatString = [](std::string& input) -> void { + // Regular expressions to match float numbers + std::regex decimalRegex("([0-9]+)\\.([0-9]+)"); + std::smatch match; + + // append missing decimal point + if (!std::regex_match(input, match, decimalRegex)) + input.append(".0"); + + // remove leading 0s + if (!(input.size() > 2 && input[0] == '0' && input[1] == '.' && isdigit(input[2]))) + input.erase(0, input.find_first_not_of('0')); + }; + bool replaceAllNames = false; for (const auto& dimName : dimNames) { @@ -82,14 +97,17 @@ void LineplotWidget::setData(const std::vector& yVals, const std::vector< break; } - numericDimNames.push_back(QString::fromStdString(res.second)); + std::string dimName = res.second; + unsureFloatString(dimName); + + numericDimNames.push_back(QString::fromStdString(dimName)); } if (replaceAllNames) { numericDimNames.resize(numDimensions); for (size_t i = 0; i < numericDimNames.size(); i++) - numericDimNames[i] = QString::number(i); + numericDimNames[i] = QString::number(i) + ".0"; } // create json string that will be passed to js From 7e13cdbe8f60ad2a06a973f51017dcfe7c99adf4 Mon Sep 17 00:00:00 2001 From: Alexander Vieth Date: Fri, 19 Apr 2024 15:34:46 +0200 Subject: [PATCH 04/19] Do not accept point data that does not have image meta data --- src/SpectralViewPlugin.cpp | 183 +++++++++++++++++++------------------ 1 file changed, 94 insertions(+), 89 deletions(-) diff --git a/src/SpectralViewPlugin.cpp b/src/SpectralViewPlugin.cpp index 2b48c72..21c15fe 100644 --- a/src/SpectralViewPlugin.cpp +++ b/src/SpectralViewPlugin.cpp @@ -123,133 +123,138 @@ void SpectralViewPlugin::init() if (!dataTypes.contains(dataType)) { dropRegions << new DropWidget::DropRegion(this, "Incompatible data", "This type of data is not supported", "exclamation-circle", false); } + else if (dataset->getChildren({ ImageType }).size() < 1) { + dropRegions << new DropWidget::DropRegion(this, "Incompatible data", "Data must have an image set as it's first child", "exclamation-circle", false); + } + else + { + // Get points dataset from the core + auto candidateDataset = mv::data().getDataset(datasetId); - // Get points dataset from the core - auto candidateDataset = mv::data().getDataset(datasetId); + // Points dataset is about to be dropped + if (dataType == PointType) { - // Points dataset is about to be dropped - if (dataType == PointType) { + // Establish drop region description + const auto description = QString("Visualize %1 as line plot").arg(datasetGuiName); - // Establish drop region description - const auto description = QString("Visualize %1 as line plot").arg(datasetGuiName); + try { - try { + if (!_points.isValid()) { - if (!_points.isValid()) { - - // Load as point positions when no dataset is currently loaded - dropRegions << new DropWidget::DropRegion(this, "Point position", description, "map-marker-alt", true, [this, candidateDataset]() { - loadData({ candidateDataset }); - }); - } - else { - if (_points == candidateDataset) { - // already loaded - dropRegions << new DropWidget::DropRegion(this, "Warning", "Data already loaded", "exclamation-circle", false); + // Load as point positions when no dataset is currently loaded + dropRegions << new DropWidget::DropRegion(this, "Point position", description, "map-marker-alt", true, [this, candidateDataset]() { + loadData({ candidateDataset }); + }); } else { - // Establish drop region description - const auto description1 = QString("Visualize every point in %1 as one line").arg(datasetGuiName); - const auto description2 = QString("Visaualize the points in %1 as an average line").arg(datasetGuiName); + if (_points == candidateDataset) { + // already loaded + dropRegions << new DropWidget::DropRegion(this, "Warning", "Data already loaded", "exclamation-circle", false); + } + else { + // Establish drop region description + const auto description1 = QString("Visualize every point in %1 as one line").arg(datasetGuiName); + const auto description2 = QString("Visaualize the points in %1 as an average line").arg(datasetGuiName); - if (!candidateDataset->isFull() || candidateDataset->isDerivedData()) { + if (!candidateDataset->isFull() || candidateDataset->isDerivedData()) { - auto parent = candidateDataset->getDataHierarchyItem().getParent(); - auto points = parent->getDataset().get(); + auto parent = candidateDataset->getDataHierarchyItem().getParent(); + auto points = parent->getDataset().get(); - QString pointName = _points->getGuiName(); + QString pointName = _points->getGuiName(); - if (!_points->isFull() || _points->isDerivedData()) { - DataHierarchyItem* pointParents = _points->getDataHierarchyItem().getParent();; - pointName = pointParents->getDatasetReference()->getGuiName(); - } + if (!_points->isFull() || _points->isDerivedData()) { + DataHierarchyItem* pointParents = _points->getDataHierarchyItem().getParent();; + pointName = pointParents->getDatasetReference()->getGuiName(); + } - // Load as point positions when no dataset is currently loaded - dropRegions << new DropWidget::DropRegion(this, "Point position", description, "map-marker-alt", true, [this, candidateDataset]() { - _points = candidateDataset.get(); + // Load as point positions when no dataset is currently loaded + dropRegions << new DropWidget::DropRegion(this, "Point position", description, "map-marker-alt", true, [this, candidateDataset]() { + _points = candidateDataset.get(); - initializeImageRGB(); - _mainToolbarAction.setEnabled(true); - _model.removeAllEndmembers(); - }); + initializeImageRGB(); + _mainToolbarAction.setEnabled(true); + _model.removeAllEndmembers(); + }); - if (points->getNumPoints() == _points->getNumPoints() && candidateDataset->getParent()->getGuiName() == pointName) { + if (points->getNumPoints() == _points->getNumPoints() && candidateDataset->getParent()->getGuiName() == pointName) { - dropRegions << new DropWidget::DropRegion(this, "Endmembers", description1, "map-marker-alt", true, [this, candidateDataset]() { + dropRegions << new DropWidget::DropRegion(this, "Endmembers", description1, "map-marker-alt", true, [this, candidateDataset]() { - auto noEndmembers = candidateDataset.get()->getNumPoints(); + auto noEndmembers = candidateDataset.get()->getNumPoints(); - if (noEndmembers > 15) { - EndmembersCheckDialog endmembersCheckDialog(nullptr, noEndmembers); + if (noEndmembers > 15) { + EndmembersCheckDialog endmembersCheckDialog(nullptr, noEndmembers); - connect(&endmembersCheckDialog, &EndmembersCheckDialog::closeDialog, this, [this, candidateDataset]() { - addDataset(candidateDataset); - }); + connect(&endmembersCheckDialog, &EndmembersCheckDialog::closeDialog, this, [this, candidateDataset]() { + addDataset(candidateDataset); + }); - endmembersCheckDialog.exec(); + endmembersCheckDialog.exec(); - } - else - addDataset(candidateDataset); - }); + } + else + addDataset(candidateDataset); + }); - dropRegions << new DropWidget::DropRegion(this, "Average endmember", description2, "map-marker-alt", true, [this, candidateDataset]() { - addAverageDataset(candidateDataset); - }); + dropRegions << new DropWidget::DropRegion(this, "Average endmember", description2, "map-marker-alt", true, [this, candidateDataset]() { + addAverageDataset(candidateDataset); + }); + } } - } - else { - dropRegions << new DropWidget::DropRegion(this, "Points", description, "map-marker-alt", true, [this, candidateDataset]() { - _points = candidateDataset; + else { + dropRegions << new DropWidget::DropRegion(this, "Points", description, "map-marker-alt", true, [this, candidateDataset]() { + _points = candidateDataset; - initializeImageRGB(); - _mainToolbarAction.setEnabled(true); - _model.removeAllEndmembers(); - }); + initializeImageRGB(); + _mainToolbarAction.setEnabled(true); + _model.removeAllEndmembers(); + }); + } } } } + catch (std::exception& e) + { + exceptionMessageBox(QString("Unable to load '%1'").arg(datasetGuiName), e); + } + catch (...) { + exceptionMessageBox(QString("Unable to load '%1'").arg(datasetGuiName)); + } } - catch (std::exception& e) - { - exceptionMessageBox(QString("Unable to load '%1'").arg(datasetGuiName), e); - } - catch (...) { - exceptionMessageBox(QString("Unable to load '%1'").arg(datasetGuiName)); - } - } - if (dataType == ClusterType) { - const auto description = QString("Visualize every cluster in %1 as one line").arg(candidateDataset->getGuiName()); + if (dataType == ClusterType) { + const auto description = QString("Visualize every cluster in %1 as one line").arg(candidateDataset->getGuiName()); - if (_points.isValid()) { + if (_points.isValid()) { - QString pointsGuid = _points->getId(); + QString pointsGuid = _points->getId(); - if (!_points->isFull() || _points->isDerivedData()) { - DataHierarchyItem* pointParent = _points->getDataHierarchyItem().getParent(); - pointsGuid = pointParent->getDataset()->getId(); - } + if (!_points->isFull() || _points->isDerivedData()) { + DataHierarchyItem* pointParent = _points->getDataHierarchyItem().getParent(); + pointsGuid = pointParent->getDataset()->getId(); + } - DataHierarchyItem* parent = candidateDataset->getDataHierarchyItem().getParent(); + DataHierarchyItem* parent = candidateDataset->getDataHierarchyItem().getParent(); - if (parent && parent->getDataset()->getId() == pointsGuid) { + if (parent && parent->getDataset()->getId() == pointsGuid) { - dropRegions << new DropWidget::DropRegion(this, "Endmembers", description, "map-marker-alt", true, [this, candidateDataset]() { - _clusterNames.push_back(candidateDataset->getGuiName()); - _noLoadedClusters.push_back(candidateDataset.get()->getClusters().size()); - addDataset(candidateDataset); + dropRegions << new DropWidget::DropRegion(this, "Endmembers", description, "map-marker-alt", true, [this, candidateDataset]() { + _clusterNames.push_back(candidateDataset->getGuiName()); + _noLoadedClusters.push_back(candidateDataset.get()->getClusters().size()); + addDataset(candidateDataset); - }); + }); + } + else { + dropRegions << new DropWidget::DropRegion(this, "Warning", "Clusters have to be a child of and come from a set of same size as the loaded points", "exclamation-circle", false); + } } else { - dropRegions << new DropWidget::DropRegion(this, "Warning", "Clusters have to be a child of and come from a set of same size as the loaded points", "exclamation-circle", false); - } - } - else { - // Only allow user to visualize clusters as lines when there is a points dataset loaded - dropRegions << new DropWidget::DropRegion(this, "No points data loaded", "Clusters can only be visualized in concert with points data", "exclamation-circle", false); + // Only allow user to visualize clusters as lines when there is a points dataset loaded + dropRegions << new DropWidget::DropRegion(this, "No points data loaded", "Clusters can only be visualized in concert with points data", "exclamation-circle", false); + } } } From def2f2c997a6571dd397ff0f6ab0efe75b42fee8 Mon Sep 17 00:00:00 2001 From: Alexander Vieth Date: Fri, 19 Apr 2024 15:49:34 +0200 Subject: [PATCH 05/19] Fix gcc compile error --- src/LineplotWidget.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/LineplotWidget.cpp b/src/LineplotWidget.cpp index 624c0b8..73c8670 100644 --- a/src/LineplotWidget.cpp +++ b/src/LineplotWidget.cpp @@ -97,10 +97,10 @@ void LineplotWidget::setData(const std::vector& yVals, const std::vector< break; } - std::string dimName = res.second; - unsureFloatString(dimName); + std::string extractedDimName = res.second; + unsureFloatString(extractedDimName); - numericDimNames.push_back(QString::fromStdString(dimName)); + numericDimNames.push_back(QString::fromStdString(extractedDimName)); } if (replaceAllNames) From dfa283954a52f0b2ebe5205856ac3f805f2c91f2 Mon Sep 17 00:00:00 2001 From: Alexander Vieth Date: Tue, 7 May 2024 17:06:52 +0200 Subject: [PATCH 06/19] Fix using derived cluster datasets --- src/SpectralViewPlugin.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/SpectralViewPlugin.cpp b/src/SpectralViewPlugin.cpp index 21c15fe..a94ac9c 100644 --- a/src/SpectralViewPlugin.cpp +++ b/src/SpectralViewPlugin.cpp @@ -123,9 +123,6 @@ void SpectralViewPlugin::init() if (!dataTypes.contains(dataType)) { dropRegions << new DropWidget::DropRegion(this, "Incompatible data", "This type of data is not supported", "exclamation-circle", false); } - else if (dataset->getChildren({ ImageType }).size() < 1) { - dropRegions << new DropWidget::DropRegion(this, "Incompatible data", "Data must have an image set as it's first child", "exclamation-circle", false); - } else { // Get points dataset from the core @@ -134,6 +131,11 @@ void SpectralViewPlugin::init() // Points dataset is about to be dropped if (dataType == PointType) { + if (dataset->getChildren({ ImageType }).size() < 1) { + dropRegions << new DropWidget::DropRegion(this, "Incompatible data", "Data must have an image set as it's first child", "exclamation-circle", false); + return dropRegions; + } + // Establish drop region description const auto description = QString("Visualize %1 as line plot").arg(datasetGuiName); From 39a765f2fa24957090adfbf4663ffda9d04616ec Mon Sep 17 00:00:00 2001 From: Baldur van Lew Date: Fri, 24 May 2024 11:41:24 +0200 Subject: [PATCH 07/19] [skip ci] Added XCode 14 to build matrix --- .github/workflows/build.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 469e4b0..daa8be1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -53,6 +53,15 @@ jobs: build-xcode-version: 13.4 build-libcxx: libc++ + - name: Macos_xcode14.3 + os: macos-13 + build-compiler: apple-clang + build-cversion: 14 + build-config: Release + build-os: Macos + build-xcode-version: 14.3 + build-libcxx: libc++ + steps: - name: Checkout the source if: github.event_name != 'pull_request' From 35651aa63990b68c5253dd6eb8f8ea0218c5c3dc Mon Sep 17 00:00:00 2001 From: Baldur van Lew Date: Fri, 24 May 2024 11:42:06 +0200 Subject: [PATCH 08/19] Add zlib 1.3 compatibility for XCode 14 --- conanfile.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/conanfile.py b/conanfile.py index 3695369..1b590f6 100644 --- a/conanfile.py +++ b/conanfile.py @@ -6,7 +6,14 @@ import pathlib import subprocess from rules_support import PluginBranchInfo - +import re + +def compatibility(os, compiler, compiler_version): + # On macos fallback to zlib apple-clang 13 + if os == "Macos" and compiler == "apple-clang" and bool(re.match("14.*", compiler_version)): + print("Compatibility match") + return ["zlib/1.3:compiler.version=13"] + return None class SpectralViewPluginConan(ConanFile): """Class to package SpectralViewPlugin using conan From 04b4abc383711dd848f79902bf2006c8880aca43 Mon Sep 17 00:00:00 2001 From: Baldur van Lew Date: Tue, 28 May 2024 12:07:52 +0200 Subject: [PATCH 09/19] Use centrally defined build matrix --- .github/workflows/build.yml | 46 +++++++++---------------------------- 1 file changed, 11 insertions(+), 35 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index daa8be1..51e24f3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,8 +17,18 @@ env: # for matrix check https://docs.github.com/en/actions/reference/specifications-for-github-hosted-runners jobs: + prepare_matrix: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.matrix_setup.outputs.matrix }} + steps: + - name: Get matrix from file + id: matrix_setup + uses: ManiVaultStudio/github-actions/matrix_setup@main + cross-platform-build: name: Cross platform build + needs: prepare_matrix # The CMake configure and build commands are platform agnostic and should work equally # well on Windows or Mac. You can convert this to a matrix build if you need # cross-platform coverage. @@ -26,41 +36,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - include: - - name: Windows-msvc2019 - os: windows-2019 - compiler: msvc-2019 - build-cversion: 16 - build-runtime: MD - build-config: Release - - - name: Linux_gcc11 - os: ubuntu-22.04 - build-cc: gcc - build-cxx: g++ - build-compiler: gcc - build-cversion: 11 - build-config: Release - build-os: Linux - build-libcxx: libstdc++ - - - name: Macos_xcode13.4 - os: macos-12 - build-compiler: apple-clang - build-cversion: 13 - build-config: Release - build-os: Macos - build-xcode-version: 13.4 - build-libcxx: libc++ - - - name: Macos_xcode14.3 - os: macos-13 - build-compiler: apple-clang - build-cversion: 14 - build-config: Release - build-os: Macos - build-xcode-version: 14.3 - build-libcxx: libc++ + include: ${{ fromJson(needs.prepare_matrix.outputs.matrix) }} steps: - name: Checkout the source From 468c122e1afbdc405011c316233019e9eda70dd2 Mon Sep 17 00:00:00 2001 From: Alexander Vieth Date: Mon, 15 Jul 2024 11:07:49 +0200 Subject: [PATCH 10/19] Use cmake find package (#13) * Use find_package * ADd cluster and image data * No REQUIRED * Find package on CI --- CMakeLists.txt | 39 +++++++++++---------------------------- conanfile.py | 4 ++++ 2 files changed, 15 insertions(+), 28 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 77f2630..c6f393b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,20 +24,12 @@ if(MSVC) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD") endif(MSVC) -# ----------------------------------------------------------------------------- -# Set install directory -# ----------------------------------------------------------------------------- -# Check if the directory to the ManiVault installation has been provided -if(NOT DEFINED MV_INSTALL_DIR) - set(MV_INSTALL_DIR "" CACHE PATH "Directory where ManiVault is installed") - message(FATAL_ERROR "Please set MV_INSTALL_DIR to the directory where ManiVault is installed") -endif() -file(TO_CMAKE_PATH ${MV_INSTALL_DIR} MV_INSTALL_DIR) - # ----------------------------------------------------------------------------- # Dependencies # ----------------------------------------------------------------------------- -find_package(Qt6 6.3.1 COMPONENTS Widgets WebEngineWidgets Concurrent REQUIRED) +find_package(Qt6 COMPONENTS Widgets WebEngineWidgets Concurrent REQUIRED) + +find_package(ManiVault COMPONENTS Core PointData ClusterData ImageData CONFIG) # ----------------------------------------------------------------------------- # Source files @@ -120,7 +112,7 @@ add_library(${SVPLUGIN} SHARED ${SOURCES} ${WEB} ${AUX} ${RESOURCE_FILES}) # ----------------------------------------------------------------------------- # Target include directories # ----------------------------------------------------------------------------- -target_include_directories(${SVPLUGIN} PRIVATE "${MV_INSTALL_DIR}/$/include/") +target_include_directories(${SVPLUGIN} PRIVATE "${ManiVault_INCLUDE_DIR}") # ----------------------------------------------------------------------------- # Target properties @@ -139,19 +131,10 @@ target_link_libraries(${SVPLUGIN} PRIVATE Qt6::Widgets) target_link_libraries(${SVPLUGIN} PRIVATE Qt6::WebEngineWidgets) target_link_libraries(${SVPLUGIN} PRIVATE Qt6::Concurrent) -set(MV_LINK_PATH "${MV_INSTALL_DIR}/$/lib") -set(PLUGIN_LINK_PATH "${MV_INSTALL_DIR}/$/$,lib,Plugins>") -set(MV_LINK_SUFFIX $,${CMAKE_LINK_LIBRARY_SUFFIX},${CMAKE_SHARED_LIBRARY_SUFFIX}>) - -set(MV_LINK_LIBRARY "${MV_LINK_PATH}/${CMAKE_SHARED_LIBRARY_PREFIX}MV_Public${MV_LINK_SUFFIX}") -set(POINTDATA_LINK_LIBRARY "${PLUGIN_LINK_PATH}/${CMAKE_SHARED_LIBRARY_PREFIX}PointData${MV_LINK_SUFFIX}") -set(IMAGEDATA_LINK_LIBRARY "${PLUGIN_LINK_PATH}/${CMAKE_SHARED_LIBRARY_PREFIX}ImageData${MV_LINK_SUFFIX}") -set(CLUSTERDATA_LINK_LIBRARY "${PLUGIN_LINK_PATH}/${CMAKE_SHARED_LIBRARY_PREFIX}ClusterData${MV_LINK_SUFFIX}") - -target_link_libraries(${SVPLUGIN} PRIVATE "${MV_LINK_LIBRARY}") -target_link_libraries(${SVPLUGIN} PRIVATE "${POINTDATA_LINK_LIBRARY}") -target_link_libraries(${SVPLUGIN} PRIVATE "${IMAGEDATA_LINK_LIBRARY}") -target_link_libraries(${SVPLUGIN} PRIVATE "${CLUSTERDATA_LINK_LIBRARY}") +target_link_libraries(${SVPLUGIN} PRIVATE ManiVault::Core) +target_link_libraries(${SVPLUGIN} PRIVATE ManiVault::PointData) +target_link_libraries(${SVPLUGIN} PRIVATE ManiVault::ClusterData) +target_link_libraries(${SVPLUGIN} PRIVATE ManiVault::ImageData) # ----------------------------------------------------------------------------- # Target installation @@ -165,7 +148,7 @@ add_custom_command(TARGET ${SVPLUGIN} POST_BUILD COMMAND "${CMAKE_COMMAND}" --install ${CMAKE_CURRENT_BINARY_DIR} --config $ - --prefix ${MV_INSTALL_DIR}/$ + --prefix ${ManiVault_INSTALL_DIR}/$ ) # ----------------------------------------------------------------------------- @@ -173,6 +156,6 @@ add_custom_command(TARGET ${SVPLUGIN} POST_BUILD # ----------------------------------------------------------------------------- # Automatically set the debug environment (command + working directory) for MSVC in debug mode if(MSVC) - set_property(TARGET ${SVPLUGIN} PROPERTY VS_DEBUGGER_WORKING_DIRECTORY $,${MV_INSTALL_DIR}/debug,${MV_INSTALL_DIR}/release>) - set_property(TARGET ${SVPLUGIN} PROPERTY VS_DEBUGGER_COMMAND $,"${MV_INSTALL_DIR}/debug/ManiVault Studio.exe","${MV_INSTALL_DIR}/release/ManiVault Studio.exe">) + set_property(TARGET ${SVPLUGIN} PROPERTY VS_DEBUGGER_WORKING_DIRECTORY $,${ManiVault_INSTALL_DIR}/debug,${ManiVault_INSTALL_DIR}/release>) + set_property(TARGET ${SVPLUGIN} PROPERTY VS_DEBUGGER_COMMAND $,"${ManiVault_INSTALL_DIR}/debug/ManiVault Studio.exe","${ManiVault_INSTALL_DIR}/release/ManiVault Studio.exe">) endif() diff --git a/conanfile.py b/conanfile.py index 1b590f6..ca86e20 100644 --- a/conanfile.py +++ b/conanfile.py @@ -110,6 +110,10 @@ def generate(self): # Give the installation directory to CMake tc.variables["MV_INSTALL_DIR"] = self.install_dir + # Find ManiVault with find_package + self.manivault_dir = self.install_dir + '/cmake/mv/' + tc.variables["ManiVault_DIR"] = self.manivault_dir + # Set some build options tc.variables["MV_UNITY_BUILD"] = "ON" From 5e86d6b4c8ef81255bd9e06528c49efca8e8822a Mon Sep 17 00:00:00 2001 From: Thomas Kroes Date: Tue, 19 Nov 2024 11:20:32 +0100 Subject: [PATCH 11/19] Put in ViewPlugins project group --- CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index c6f393b..1eea941 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -151,6 +151,11 @@ add_custom_command(TARGET ${SVPLUGIN} POST_BUILD --prefix ${ManiVault_INSTALL_DIR}/$ ) +set_target_properties(${SVPLUGIN} + PROPERTIES + FOLDER ViewPlugins +) + # ----------------------------------------------------------------------------- # Miscellaneous # ----------------------------------------------------------------------------- From 460a228e5f140be74dc76bd4a4737f5f3bb91eef Mon Sep 17 00:00:00 2001 From: Alexander Vieth Date: Tue, 4 Feb 2025 15:51:29 +0100 Subject: [PATCH 12/19] Update CI 02/2025 (#14) * Update conanfile.py * Update build.yml --- .github/workflows/build.yml | 16 +++----- conanfile.py | 77 ++++++++++++++----------------------- 2 files changed, 34 insertions(+), 59 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 51e24f3..d38f2fb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,16 +4,10 @@ on: push: pull_request: workflow_dispatch: - inputs: - forceMacBuild: - description: 'If set true override the ENABLE_MACOS_BUILD to force a build' - type: boolean - default: false env: # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) BUILD_TYPE: Release - MACENABLED: ${{ inputs.forceMacBuild }} # for matrix check https://docs.github.com/en/actions/reference/specifications-for-github-hosted-runners jobs: @@ -41,14 +35,14 @@ jobs: steps: - name: Checkout the source if: github.event_name != 'pull_request' - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: submodules: recursive fetch-depth: 0 - name: Checkout the source - pull request if: github.event_name == 'pull_request' - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: submodules: recursive fetch-depth: 0 @@ -60,12 +54,12 @@ jobs: sudo xcode-select -switch /Applications/Xcode_${{matrix.build-xcode-version}}.app - name: Setup python version - uses: actions/setup-python@v1 + uses: actions/setup-python@v5 with: python-version: "3.11" - name: Start ssh key agent - uses: webfactory/ssh-agent@v0.7.0 + uses: webfactory/ssh-agent@v0.9.0 with: ssh-private-key: ${{ secrets.RULESSUPPORT_DEPLOY_KEY }} @@ -103,7 +97,7 @@ jobs: conan-cxx: g++-${{matrix.build-cversion}} - name: Mac build - if: startsWith(matrix.os, 'macos') && (env.MACENABLED == 'true' || vars.ENABLE_MACOS_BUILD == 'True') + if: startsWith(matrix.os, 'macos') uses: ManiVaultStudio/github-actions/conan_linuxmac_build@main with: conan-compiler: ${{matrix.build-compiler}} diff --git a/conanfile.py b/conanfile.py index ca86e20..54afe9b 100644 --- a/conanfile.py +++ b/conanfile.py @@ -6,27 +6,20 @@ import pathlib import subprocess from rules_support import PluginBranchInfo -import re -def compatibility(os, compiler, compiler_version): - # On macos fallback to zlib apple-clang 13 - if os == "Macos" and compiler == "apple-clang" and bool(re.match("14.*", compiler_version)): - print("Compatibility match") - return ["zlib/1.3:compiler.version=13"] - return None class SpectralViewPluginConan(ConanFile): """Class to package SpectralViewPlugin using conan Packages both RELEASE and DEBUG. - Uses rules_support (github.com/hdps/rulessupport) to derive + Uses rules_support (github.com/ManiVaultStudio/rulessupport) to derive versioninfo based on the branch naming convention - as described in https://github.com/hdps/core/wiki/Branch-naming-rules + as described in https://github.com/ManiVaultStudio/core/wiki/Branch-naming-rules """ name = "SpectralViewPlugin" description = "Viewer for viewing spectral data" topics = ("hdps", "plugin", "image data", "loading") - url = "https://github.com/hdps/SpectralViewPlugin" + url = "https://github.com/ManiVaultStudio/SpectralViewPlugin" author = "B. van Lew b.van_lew@lumc.nl" # conan recipe author license = "MIT" @@ -90,29 +83,28 @@ def generate(self): generator = "Xcode" if self.settings.os == "Linux": generator = "Ninja Multi-Config" - # Use the Qt provided .cmake files - qtpath = pathlib.Path(self.deps_cpp_info["qt"].rootpath) - qt_root = str(list(qtpath.glob("**/Qt6Config.cmake"))[0].parents[3].as_posix()) tc = CMakeToolchain(self, generator=generator) - if self.settings.os == "Windows" and self.options.shared: - tc.variables["CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS"] = True - if self.settings.os == "Linux" or self.settings.os == "Macos": - tc.variables["CMAKE_CXX_STANDARD_REQUIRED"] = "ON" - tc.variables["CMAKE_PREFIX_PATH"] = qt_root - - # Set the installation directory for ManiVault based on the MV_INSTALL_DIR environment variable - # or if none is specified, set it to the build/install dir. - if not os.environ.get("MV_INSTALL_DIR", None): - os.environ["MV_INSTALL_DIR"] = os.path.join(self.build_folder, "install") - print("MV_INSTALL_DIR: ", os.environ["MV_INSTALL_DIR"]) - self.install_dir = pathlib.Path(os.environ["MV_INSTALL_DIR"]).as_posix() - # Give the installation directory to CMake - tc.variables["MV_INSTALL_DIR"] = self.install_dir - - # Find ManiVault with find_package - self.manivault_dir = self.install_dir + '/cmake/mv/' - tc.variables["ManiVault_DIR"] = self.manivault_dir + + tc.variables["CMAKE_CXX_STANDARD_REQUIRED"] = "ON" + + # Use the Qt provided .cmake files + qt_path = pathlib.Path(self.deps_cpp_info["qt"].rootpath) + qt_cfg = list(qt_path.glob("**/Qt6Config.cmake"))[0] + qt_dir = qt_cfg.parents[0].as_posix() + qt_root = qt_cfg.parents[3].as_posix() + + # for Qt >= 6.4.2 + #tc.variables["Qt6_DIR"] = qt_dir + + # for Qt < 6.4.2 + tc.variables["Qt6_ROOT"] = qt_root + + # Use the ManiVault .cmake file to find ManiVault with find_package + mv_core_root = self.deps_cpp_info["hdps-core"].rootpath + manivault_dir = pathlib.Path(mv_core_root, "cmake", "mv").as_posix() + print("ManiVault_DIR: ", manivault_dir) + tc.variables["ManiVault_DIR"] = manivault_dir # Set some build options tc.variables["MV_UNITY_BUILD"] = "ON" @@ -126,23 +118,16 @@ def _configure_cmake(self): return cmake def build(self): - print("Build OS is : ", self.settings.os) - - # The SpectralViewPlugin plugins expect the HDPS package to be in this install dir - hdps_pkg_root = self.deps_cpp_info["hdps-core"].rootpath - print("Install dir type: ", self.install_dir) - shutil.copytree(hdps_pkg_root, self.install_dir) + print("Build OS is: ", self.settings.os) cmake = self._configure_cmake() cmake.build(build_type="Debug") - cmake.install(build_type="Debug") - - # cmake_release = self._configure_cmake() cmake.build(build_type="Release") - cmake.install(build_type="Release") def package(self): - package_dir = os.path.join(self.build_folder, "package") + package_dir = pathlib.Path(self.build_folder, "package") + debug_dir = package_dir / "Debug" + release_dir = package_dir / "Release" print("Packaging install dir: ", package_dir) subprocess.run( [ @@ -152,7 +137,7 @@ def package(self): "--config", "Debug", "--prefix", - os.path.join(package_dir, "Debug"), + debug_dir, ] ) subprocess.run( @@ -163,14 +148,10 @@ def package(self): "--config", "Release", "--prefix", - os.path.join(package_dir, "Release"), + release_dir, ] ) self.copy(pattern="*", src=package_dir) - # Add the debug support files to the package - # (*.pdb) if building the Visual Studio version - if self.settings.compiler == "Visual Studio": - self.copy("*.pdb", dst="Debug/Plugins", keep_path=False) def package_info(self): self.cpp_info.debug.libdirs = ["Debug/lib"] From 2ec154af716318fa0af1adaf320f0ce01001d078 Mon Sep 17 00:00:00 2001 From: Alexander Vieth Date: Fri, 28 Feb 2025 12:46:57 +0100 Subject: [PATCH 13/19] Update to Qt 6.8 (#16) * Add build arch * Update cmake * Update CI (relwithdebinfo) --- .github/workflows/build.yml | 2 ++ CMakeLists.txt | 22 +++++++++------------- conanfile.py | 25 ++++++++++--------------- 3 files changed, 21 insertions(+), 28 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d38f2fb..eee0103 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -90,6 +90,7 @@ jobs: conan-libcxx-version: ${{matrix.build-libcxx}} conan-build-type: ${{matrix.build-config}} conan-build-os: ${{matrix.build-os}} + build-arch: ${{matrix.build-arch}} conan-user: ${{secrets.LKEB_UPLOAD_USER}} conan-password: ${{secrets.LKEB_UPLOAD_USER_PASSWORD}} conan-pem: ${{secrets.LKEB_UPLOAD_CERT_CHAIN}} @@ -105,6 +106,7 @@ jobs: conan-libcxx-version: ${{matrix.build-libcxx}} conan-build-type: ${{matrix.build-config}} conan-build-os: ${{matrix.build-os}} + build-arch: ${{matrix.build-arch}} conan-user: ${{secrets.LKEB_UPLOAD_USER}} conan-password: ${{secrets.LKEB_UPLOAD_USER_PASSWORD}} conan-pem: ${{secrets.LKEB_UPLOAD_CERT_CHAIN}} diff --git a/CMakeLists.txt b/CMakeLists.txt index 1eea941..0f1ac75 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.17) +cmake_minimum_required(VERSION 3.22) option(MV_UNITY_BUILD "Combine target source files into batches for faster compilation" OFF) @@ -18,10 +18,10 @@ set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) if(MSVC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /DWIN32 /EHsc /MP /permissive- /Zc:__cplusplus /W3") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LTCG /NODEFAULTLIB:LIBCMT") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /DWIN32 /EHsc /MP /permissive- /Zc:__cplusplus /W3") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MD") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD") endif(MSVC) # ----------------------------------------------------------------------------- @@ -29,7 +29,7 @@ endif(MSVC) # ----------------------------------------------------------------------------- find_package(Qt6 COMPONENTS Widgets WebEngineWidgets Concurrent REQUIRED) -find_package(ManiVault COMPONENTS Core PointData ClusterData ImageData CONFIG) +find_package(ManiVault COMPONENTS Core PointData ClusterData ImageData CONFIG QUIET) # ----------------------------------------------------------------------------- # Source files @@ -43,10 +43,6 @@ set(PLUGIN src/Endmember.h ) -set(PLUGIN_MOC_HEADERS - src/SpectralViewPlugin.h -) - set(ACTIONS src/SettingsAction.h src/SettingsAction.cpp @@ -118,7 +114,7 @@ target_include_directories(${SVPLUGIN} PRIVATE "${ManiVault_INCLUDE_DIR}") # Target properties # ----------------------------------------------------------------------------- # Request C++17 -target_compile_features(${SVPLUGIN} PRIVATE cxx_std_17) +target_compile_features(${SVPLUGIN} PRIVATE cxx_std_20) if(MV_UNITY_BUILD) set_target_properties(${SVPLUGIN} PROPERTIES UNITY_BUILD ON) @@ -161,6 +157,6 @@ set_target_properties(${SVPLUGIN} # ----------------------------------------------------------------------------- # Automatically set the debug environment (command + working directory) for MSVC in debug mode if(MSVC) - set_property(TARGET ${SVPLUGIN} PROPERTY VS_DEBUGGER_WORKING_DIRECTORY $,${ManiVault_INSTALL_DIR}/debug,${ManiVault_INSTALL_DIR}/release>) - set_property(TARGET ${SVPLUGIN} PROPERTY VS_DEBUGGER_COMMAND $,"${ManiVault_INSTALL_DIR}/debug/ManiVault Studio.exe","${ManiVault_INSTALL_DIR}/release/ManiVault Studio.exe">) + set_property(TARGET ${SVPLUGIN} PROPERTY VS_DEBUGGER_WORKING_DIRECTORY $,${ManiVault_INSTALL_DIR}/Debug,$,${ManiVault_INSTALL_DIR}/RelWithDebInfo,${ManiVault_INSTALL_DIR}/Release>>) + set_property(TARGET ${SVPLUGIN} PROPERTY VS_DEBUGGER_COMMAND $,"${ManiVault_INSTALL_DIR}/Debug/ManiVault Studio.exe",$,"${ManiVault_INSTALL_DIR}/RelWithDebInfo/ManiVault Studio.exe","${ManiVault_INSTALL_DIR}/Release/ManiVault Studio.exe">>) endif() diff --git a/conanfile.py b/conanfile.py index 54afe9b..f3b019e 100644 --- a/conanfile.py +++ b/conanfile.py @@ -10,7 +10,7 @@ class SpectralViewPluginConan(ConanFile): """Class to package SpectralViewPlugin using conan - Packages both RELEASE and DEBUG. + Packages both RELEASE and RELWITHDEBINFO. Uses rules_support (github.com/ManiVaultStudio/rulessupport) to derive versioninfo based on the branch naming convention as described in https://github.com/ManiVaultStudio/core/wiki/Branch-naming-rules @@ -92,13 +92,8 @@ def generate(self): qt_path = pathlib.Path(self.deps_cpp_info["qt"].rootpath) qt_cfg = list(qt_path.glob("**/Qt6Config.cmake"))[0] qt_dir = qt_cfg.parents[0].as_posix() - qt_root = qt_cfg.parents[3].as_posix() - # for Qt >= 6.4.2 - #tc.variables["Qt6_DIR"] = qt_dir - - # for Qt < 6.4.2 - tc.variables["Qt6_ROOT"] = qt_root + tc.variables["Qt6_DIR"] = qt_dir # Use the ManiVault .cmake file to find ManiVault with find_package mv_core_root = self.deps_cpp_info["hdps-core"].rootpath @@ -121,12 +116,12 @@ def build(self): print("Build OS is: ", self.settings.os) cmake = self._configure_cmake() - cmake.build(build_type="Debug") + cmake.build(build_type="RelWithDebInfo") cmake.build(build_type="Release") def package(self): package_dir = pathlib.Path(self.build_folder, "package") - debug_dir = package_dir / "Debug" + relWithDebInfo_dir = package_dir / "RelWithDebInfo" release_dir = package_dir / "Release" print("Packaging install dir: ", package_dir) subprocess.run( @@ -135,9 +130,9 @@ def package(self): "--install", self.build_folder, "--config", - "Debug", + "RelWithDebInfo", "--prefix", - debug_dir, + relWithDebInfo_dir, ] ) subprocess.run( @@ -154,9 +149,9 @@ def package(self): self.copy(pattern="*", src=package_dir) def package_info(self): - self.cpp_info.debug.libdirs = ["Debug/lib"] - self.cpp_info.debug.bindirs = ["Debug/Plugins", "Debug"] - self.cpp_info.debug.includedirs = ["Debug/include", "Debug"] + self.cpp_info.relwithdebinfo.libdirs = ["RelWithDebInfo/lib"] + self.cpp_info.relwithdebinfo.bindirs = ["RelWithDebInfo/Plugins", "RelWithDebInfo"] + self.cpp_info.relwithdebinfo.includedirs = ["RelWithDebInfo/include", "RelWithDebInfo"] self.cpp_info.release.libdirs = ["Release/lib"] self.cpp_info.release.bindirs = ["Release/Plugins", "Release"] - self.cpp_info.release.includedirs = ["Release/include", "Release"] + self.cpp_info.release.includedirs = ["Release/include", "Release"] \ No newline at end of file From 37dd077002c61b31bd028adffb4bd8ea30a51b31 Mon Sep 17 00:00:00 2001 From: Thomas Kroes Date: Thu, 27 Feb 2025 13:56:43 +0100 Subject: [PATCH 14/19] Remove redundant override --- src/SpectralViewPlugin.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/SpectralViewPlugin.cpp b/src/SpectralViewPlugin.cpp index a94ac9c..f7e68be 100644 --- a/src/SpectralViewPlugin.cpp +++ b/src/SpectralViewPlugin.cpp @@ -1269,15 +1269,6 @@ void SpectralViewPlugin::computeAverageDataset(int width, int height, int numDim } -// ============================================================================= -// Factory -// ============================================================================= - -QIcon SpectralViewPluginFactory::getIcon(const QColor& color) const -{ - return Application::getIconFont("FontAwesome").getIcon("chart-line"); -} - ViewPlugin* SpectralViewPluginFactory::produce() { return new SpectralViewPlugin(this); From e3a11cdf70449cd28aba722f152dc65d946a4d54 Mon Sep 17 00:00:00 2001 From: Thomas Kroes Date: Thu, 27 Feb 2025 13:57:41 +0100 Subject: [PATCH 15/19] Set icon in plugin factory --- src/SpectralViewPlugin.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/SpectralViewPlugin.cpp b/src/SpectralViewPlugin.cpp index f7e68be..fe46845 100644 --- a/src/SpectralViewPlugin.cpp +++ b/src/SpectralViewPlugin.cpp @@ -1268,6 +1268,10 @@ void SpectralViewPlugin::computeAverageDataset(int width, int height, int numDim } } +SpectralViewPluginFactory::SpectralViewPluginFactory() +{ + setIconByName("chart-line"); +} ViewPlugin* SpectralViewPluginFactory::produce() { From 3c6579ce23446aaf7b18c5680ab8fc86a2d1ff43 Mon Sep 17 00:00:00 2001 From: Thomas Kroes Date: Thu, 27 Feb 2025 14:00:17 +0100 Subject: [PATCH 16/19] Simplify icon assignment --- src/EndmembersAction.cpp | 7 +++---- src/LineplotWidget.cpp | 6 +++--- src/MapAction.cpp | 5 ++--- src/SpectralViewPlugin.h | 6 ++---- src/ViewSettingsAction.cpp | 2 +- src/WavelengthsRGBAction.cpp | 2 +- 6 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/EndmembersAction.cpp b/src/EndmembersAction.cpp index 8b48e13..a04b83d 100644 --- a/src/EndmembersAction.cpp +++ b/src/EndmembersAction.cpp @@ -13,6 +13,7 @@ using namespace mv; using namespace mv::gui; +using namespace mv::util; EndmembersAction::EndmembersAction(SettingsAction& settingsAction) : WidgetAction(reinterpret_cast(&settingsAction), "EndmembersAction"), @@ -44,10 +45,8 @@ EndmembersAction::Widget::Widget(QWidget* parent, EndmembersAction* endmembersAc _removeEndmemberAction.setToolTip("Remove the selected endmember"); _saveEndmembersAction.setToolTip("Save the checked endmembers in the list"); - auto& fontAwesome = Application::getIconFont("FontAwesome"); - - _removeEndmemberAction.setIcon(fontAwesome.getIcon("trash-alt")); - _saveEndmembersAction.setIcon(fontAwesome.getIcon("save")); + _removeEndmemberAction.setIcon(StyledIcon("trash-alt")); + _saveEndmembersAction.setIcon(StyledIcon("save")); auto layout = new QVBoxLayout(); auto treeView = new QTreeView(); diff --git a/src/LineplotWidget.cpp b/src/LineplotWidget.cpp index 73c8670..0f17909 100644 --- a/src/LineplotWidget.cpp +++ b/src/LineplotWidget.cpp @@ -11,6 +11,8 @@ #include #include +using namespace mv::util; + LinePlotCommunicationObject::LinePlotCommunicationObject(LineplotWidget* parent) : mv::gui::WebCommunicationObject(), _parent(parent) @@ -24,9 +26,7 @@ void LinePlotCommunicationObject::js_setRGBWavelength(float wavelength, int inde } LineplotWidget::LineplotWidget() : - mv::gui::WebWidget(), _communicationObject(new LinePlotCommunicationObject(this)), - dataOptionBuffer(), loaded(false) { Q_INIT_RESOURCE(lineplot_resources); @@ -36,7 +36,7 @@ LineplotWidget::LineplotWidget() : setAcceptDrops(true); setMouseTracking(true); - setWindowIcon(mv::Application::getIconFont("FontAwesome").getIcon("chart-line")); + setWindowIcon(StyledIcon("chart-line")); } LineplotWidget::~LineplotWidget() { diff --git a/src/MapAction.cpp b/src/MapAction.cpp index 0e98581..c80b04e 100644 --- a/src/MapAction.cpp +++ b/src/MapAction.cpp @@ -34,9 +34,8 @@ MapAction::MapAction(Endmember& endmember) : _thresholdAction.setToolTip("Map pixels with value greater than threshold"); _updateAutoAction.setToolTip("Perform selected algorithm automatically"); _computeAction.setToolTip("Update map for the selected endmember"); - - auto& fontAwesome = Application::getIconFont("FontAwesome"); - _computeAction.setIcon(fontAwesome.getIcon("play")); + + _computeAction.setIconByName("play"); //_thresholdAction.setDefaultValue(0.15f); //_thresholdAction.defaultValueChanged(0.15f); diff --git a/src/SpectralViewPlugin.h b/src/SpectralViewPlugin.h index de8b112..f3816cb 100644 --- a/src/SpectralViewPlugin.h +++ b/src/SpectralViewPlugin.h @@ -133,11 +133,9 @@ class SpectralViewPluginFactory : public ViewPluginFactory FILE "SpectralViewPlugin.json") public: - SpectralViewPluginFactory() {} - ~SpectralViewPluginFactory() override {} + SpectralViewPluginFactory(); - /** Returns the plugin icon */ - QIcon getIcon(const QColor& color = Qt::black) const override; + ~SpectralViewPluginFactory() override {} ViewPlugin* produce() override; diff --git a/src/ViewSettingsAction.cpp b/src/ViewSettingsAction.cpp index 834dcb0..33013b5 100644 --- a/src/ViewSettingsAction.cpp +++ b/src/ViewSettingsAction.cpp @@ -14,7 +14,7 @@ ViewSettingsAction::ViewSettingsAction(SpectralViewPlugin& spectralViewPlugin) : _showSelectionAction(this, "Show selection", true), _stdAreaEnabledAction(this, "Show std. dev.", true) { - setIcon(Application::getIconFont("FontAwesome").getIcon("cog")); + setIconByName("gear"); setText("Global settings"); _showSelectionAction.setToolTip("Show a line for the current selection"); diff --git a/src/WavelengthsRGBAction.cpp b/src/WavelengthsRGBAction.cpp index 1f8f9a6..cb12c1e 100644 --- a/src/WavelengthsRGBAction.cpp +++ b/src/WavelengthsRGBAction.cpp @@ -15,7 +15,7 @@ WavelengthsRGBAction::WavelengthsRGBAction(SpectralViewPlugin& spectralViewPlugi _greenWavelengthAction(this, "Green", { "532" }, "532"), _blueWavelengthAction(this, "Blue", { "464" }, "464") { - setIcon(Application::getIconFont("FontAwesome").getIcon("grip-lines-vertical")); + setIconByName("grip-lines-vertical"); setText("RGB Wavelengths Settings"); _wavelengthsRGBEnabledAction.setToolTip("Show 3 RGB lines that can be moved"); From 63547f7399685176bedba8ed6e860658a3d0d219 Mon Sep 17 00:00:00 2001 From: Thomas Kroes Date: Thu, 27 Feb 2025 14:00:31 +0100 Subject: [PATCH 17/19] Use correct icon setter --- src/SpectralViewPlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SpectralViewPlugin.cpp b/src/SpectralViewPlugin.cpp index fe46845..be8670c 100644 --- a/src/SpectralViewPlugin.cpp +++ b/src/SpectralViewPlugin.cpp @@ -1299,7 +1299,7 @@ mv::gui::PluginTriggerActions SpectralViewPluginFactory::getPluginTriggerActions if (PluginFactory::areAllDatasetsOfTheSameType(datasets, PointType)) { if (numberOfDatasets >= 1) { if (datasets.first()->getDataType() == PointType) { - auto pluginTriggerAction = new PluginTriggerAction(const_cast(this), this, "Spectral Viewer", "Load dataset in spectral Viewer", getIcon(), [this, getInstance, datasets](PluginTriggerAction& pluginTriggerAction) -> void { + auto pluginTriggerAction = new PluginTriggerAction(const_cast(this), this, "Spectral Viewer", "Load dataset in spectral Viewer", icon(), [this, getInstance, datasets](PluginTriggerAction& pluginTriggerAction) -> void { for (const auto& dataset : datasets) getInstance()->loadData(Datasets({ dataset })); }); From c6e6161c867503b2a39d017ecf6bea74ce546537 Mon Sep 17 00:00:00 2001 From: Alexander Vieth Date: Tue, 3 Feb 2026 11:01:33 +0100 Subject: [PATCH 18/19] Plugin config file (#17) * Use PluginInfo.json * Specify CXX as language in cmake * safer cmake checks * Remove unused cmake definitions --- CMakeLists.txt | 21 +++++++++------------ PluginInfo.json | 9 +++++++++ src/SpectralViewPlugin.h | 2 +- src/SpectralViewPlugin.json | 5 ----- 4 files changed, 19 insertions(+), 18 deletions(-) create mode 100644 PluginInfo.json delete mode 100644 src/SpectralViewPlugin.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f1ac75..e24a34a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,8 +6,10 @@ option(MV_UNITY_BUILD "Combine target source files into batches for faster compi # SpectralView Plugin # ----------------------------------------------------------------------------- set(SVPLUGIN "SpectralViewPlugin") - -PROJECT(${SVPLUGIN}) +PROJECT(${SVPLUGIN} + DESCRIPTION "View plugin for ManiVault for spectral data" + LANGUAGES CXX +) # ----------------------------------------------------------------------------- # CMake Options @@ -15,14 +17,13 @@ PROJECT(${SVPLUGIN}) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) -set(CMAKE_AUTOUIC ON) -if(MSVC) +if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /DWIN32 /EHsc /MP /permissive- /Zc:__cplusplus /W3") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MD") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD") -endif(MSVC) +endif() # ----------------------------------------------------------------------------- # Dependencies @@ -87,7 +88,7 @@ set(WEB set(AUX res/lineplot_resources.qrc - src/SpectralViewPlugin.json + PluginInfo.json ) qt6_add_resources(RESOURCE_FILES res/lineplot_resources.qrc) @@ -113,7 +114,6 @@ target_include_directories(${SVPLUGIN} PRIVATE "${ManiVault_INCLUDE_DIR}") # ----------------------------------------------------------------------------- # Target properties # ----------------------------------------------------------------------------- -# Request C++17 target_compile_features(${SVPLUGIN} PRIVATE cxx_std_20) if(MV_UNITY_BUILD) @@ -147,16 +147,13 @@ add_custom_command(TARGET ${SVPLUGIN} POST_BUILD --prefix ${ManiVault_INSTALL_DIR}/$ ) -set_target_properties(${SVPLUGIN} - PROPERTIES - FOLDER ViewPlugins -) +mv_handle_plugin_config(${SVPLUGIN}) # ----------------------------------------------------------------------------- # Miscellaneous # ----------------------------------------------------------------------------- # Automatically set the debug environment (command + working directory) for MSVC in debug mode -if(MSVC) +if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") set_property(TARGET ${SVPLUGIN} PROPERTY VS_DEBUGGER_WORKING_DIRECTORY $,${ManiVault_INSTALL_DIR}/Debug,$,${ManiVault_INSTALL_DIR}/RelWithDebInfo,${ManiVault_INSTALL_DIR}/Release>>) set_property(TARGET ${SVPLUGIN} PROPERTY VS_DEBUGGER_COMMAND $,"${ManiVault_INSTALL_DIR}/Debug/ManiVault Studio.exe",$,"${ManiVault_INSTALL_DIR}/RelWithDebInfo/ManiVault Studio.exe","${ManiVault_INSTALL_DIR}/Release/ManiVault Studio.exe">>) endif() diff --git a/PluginInfo.json b/PluginInfo.json new file mode 100644 index 0000000..e7f7e64 --- /dev/null +++ b/PluginInfo.json @@ -0,0 +1,9 @@ +{ + "name" : "Spectral View", + "version" : { + "plugin" : "1.0.0", + "core" : ["1.3"] + }, + "type" : "View", + "dependencies" : ["Points", "Cluster", "Images"] +} \ No newline at end of file diff --git a/src/SpectralViewPlugin.h b/src/SpectralViewPlugin.h index f3816cb..bb7ddef 100644 --- a/src/SpectralViewPlugin.h +++ b/src/SpectralViewPlugin.h @@ -130,7 +130,7 @@ class SpectralViewPluginFactory : public ViewPluginFactory Q_INTERFACES(mv::plugin::ViewPluginFactory mv::plugin::PluginFactory) Q_OBJECT Q_PLUGIN_METADATA(IID "nl.tudelft.SpectralViewPlugin" - FILE "SpectralViewPlugin.json") + FILE "PluginInfo.json") public: SpectralViewPluginFactory(); diff --git a/src/SpectralViewPlugin.json b/src/SpectralViewPlugin.json deleted file mode 100644 index da46003..0000000 --- a/src/SpectralViewPlugin.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name" : "Spectral View", - "version" : "1", - "dependencies" : ["Points", "Cluster", "Images"] -} \ No newline at end of file From 17ffa424551681e237e92e93e908354e371065f1 Mon Sep 17 00:00:00 2001 From: Alexander Vieth Date: Tue, 26 May 2026 19:04:02 +0200 Subject: [PATCH 19/19] Add mv namespace (#18) --- src/Endmember.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Endmember.cpp b/src/Endmember.cpp index 744da30..b936eab 100644 --- a/src/Endmember.cpp +++ b/src/Endmember.cpp @@ -9,7 +9,7 @@ #include #include -Endmember::Endmember(SpectralViewPlugin& spectralViewPlugin, const Dataset& dataset, int index) : +Endmember::Endmember(SpectralViewPlugin& spectralViewPlugin, const mv::Dataset& dataset, int index) : WidgetAction(&spectralViewPlugin, "Endmember"), _spectralViewPlugin(spectralViewPlugin), _active(false), @@ -30,7 +30,7 @@ Endmember::Endmember(SpectralViewPlugin& spectralViewPlugin, const Dataset::guiNameChanged, this, [this]() { + connect(&_dataset, &mv::Dataset::guiNameChanged, this, [this]() { _generalAction.getDatasetNameAction().setString(_dataset->getGuiName()); //_generalAction.getNameAction().setDefaultString(newGuiName); });