Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ add_subdirectory(ExampleLoader)
add_subdirectory(ExampleWriter)
add_subdirectory(ExampleData)
add_subdirectory(ExampleDependencies)
add_subdirectory(ExampleActions)

set_target_properties(ExampleViewPlugin ExampleViewJSPlugin ExampleViewOpenGLPlugin ExampleAnalysisPlugin ExampleTransformationPlugin ExampleLoaderPlugin ExampleWriterPlugin ExampleDataPlugin ExampleDependenciesPlugin
set_target_properties(ExampleViewPlugin ExampleViewJSPlugin ExampleViewOpenGLPlugin ExampleAnalysisPlugin ExampleTransformationPlugin ExampleLoaderPlugin ExampleWriterPlugin ExampleDataPlugin ExampleDependenciesPlugin ExampleActionsPlugin
PROPERTIES
FOLDER ExamplePlugins
)
119 changes: 119 additions & 0 deletions ExampleActions/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
cmake_minimum_required(VERSION 3.22)

option(MV_UNITY_BUILD "Combine target source files into batches for faster compilation" OFF)

# -----------------------------------------------------------------------------
# ExampleView Plugin
# -----------------------------------------------------------------------------
PROJECT("ExampleActionsPlugin" LANGUAGES CXX)

# -----------------------------------------------------------------------------
# CMake Options
# -----------------------------------------------------------------------------
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)

if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /DWIN32 /EHsc /MP /permissive- /Zc:__cplusplus")
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()

# -----------------------------------------------------------------------------
# Dependencies
# -----------------------------------------------------------------------------
find_package(Qt6 COMPONENTS Widgets WebEngineWidgets REQUIRED)

find_package(ManiVault COMPONENTS Core PointData CONFIG QUIET)

# -----------------------------------------------------------------------------
# Include Common directory
# -----------------------------------------------------------------------------
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../Common ${CMAKE_CURRENT_BINARY_DIR}/Common)

# -----------------------------------------------------------------------------
# Source files
# -----------------------------------------------------------------------------
# Define the plugin sources
set(PLUGIN_SOURCES
src/ExampleActionsPlugin.h
src/ExampleActionsPlugin.cpp
src/ActionsWidget.h
src/ActionsWidget.cpp
src/ActionsFilterModel.h
src/ActionsFilterModel.cpp
PluginInfo.json
)

set(PLUGIN_MOC_HEADERS
src/ExampleActionsPlugin.h
)

source_group(Plugin FILES ${PLUGIN_SOURCES})
source_group(Common FILES ${COMMON_FILES})

# -----------------------------------------------------------------------------
# CMake Target
# -----------------------------------------------------------------------------
# Create dynamic library for the plugin
add_library(${PROJECT_NAME} SHARED ${PLUGIN_SOURCES} ${COMMON_FILES})

# -----------------------------------------------------------------------------
# Target include directories
# -----------------------------------------------------------------------------
# Include ManiVault headers, including system data plugins
target_include_directories(${PROJECT_NAME} PRIVATE "${ManiVault_INCLUDE_DIR}")

# -----------------------------------------------------------------------------
# Target properties
# -----------------------------------------------------------------------------
# Request C++20
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20)

# Enable unity build
if(MV_UNITY_BUILD)
set_target_properties(${PROJECT_NAME} PROPERTIES UNITY_BUILD ON)
endif()

# -----------------------------------------------------------------------------
# Target library linking
# -----------------------------------------------------------------------------
# Link to Qt libraries
target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Widgets)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::WebEngineWidgets)

# Link to ManiVault and data plugins
target_link_libraries(${PROJECT_NAME} PRIVATE ManiVault::Core)
target_link_libraries(${PROJECT_NAME} PRIVATE ManiVault::PointData)

# -----------------------------------------------------------------------------
# Target installation
# -----------------------------------------------------------------------------
# Install the shared plugin library to the "Plugins" folder in the ManiVault install directory
install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION Plugins COMPONENT PLUGINS # Windows .dll
LIBRARY DESTINATION Plugins COMPONENT PLUGINS # Linux/Mac .so
)

add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND "${CMAKE_COMMAND}"
--install ${CMAKE_CURRENT_BINARY_DIR}
--config $<CONFIGURATION>
--prefix ${ManiVault_INSTALL_DIR}/$<CONFIGURATION>
)

# Append plugin version to output file
# 0 disables automatic folder placement (same as plugin type)
# since we want to place all example plugins in a separate folder
mv_handle_plugin_config(${PROJECT_NAME} 0)

# -----------------------------------------------------------------------------
# Miscellaneous
# -----------------------------------------------------------------------------
# Automatically set the debug environment (command + working directory) for MSVC
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
set_property(TARGET ${PROJECT_NAME} PROPERTY VS_DEBUGGER_WORKING_DIRECTORY $<IF:$<CONFIG:DEBUG>,${ManiVault_INSTALL_DIR}/Debug,$<IF:$<CONFIG:RELWITHDEBINFO>,${ManiVault_INSTALL_DIR}/RelWithDebInfo,${ManiVault_INSTALL_DIR}/Release>>)
set_property(TARGET ${PROJECT_NAME} PROPERTY VS_DEBUGGER_COMMAND $<IF:$<CONFIG:DEBUG>,"${ManiVault_INSTALL_DIR}/Debug/ManiVault Studio.exe",$<IF:$<CONFIG:RELWITHDEBINFO>,"${ManiVault_INSTALL_DIR}/RelWithDebInfo/ManiVault Studio.exe","${ManiVault_INSTALL_DIR}/Release/ManiVault Studio.exe">>)
endif()
9 changes: 9 additions & 0 deletions ExampleActions/PluginInfo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name" : "Example Actions",
"version" : {
"plugin" : "1.4",
"core" : ["1.3"]
},
"type" : "View",
"dependencies" : ["Points"]
}
10 changes: 10 additions & 0 deletions ExampleActions/src/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# To learn more about .editorconfig see https://aka.ms/editorconfigdocs
root = true

# All files
[*]
indent_style = space

# Cpp files
[*.{h,cpp}]
indent_size = 4
53 changes: 53 additions & 0 deletions ExampleActions/src/ActionsFilterModel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include "ActionsFilterModel.h"

ActionsFilterModel::ActionsFilterModel(QObject* parent) :
QSortFilterProxyModel(parent)
{
}

void ActionsFilterModel::setSearchRoles(QVector<int> roles)
{
searchRoles = std::move(roles);
}

bool ActionsFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
{
const QModelIndex idx = sourceModel()->index(sourceRow, 0, sourceParent);

if (!idx.isValid())
return false;

if (rowMatches(idx))
return true;

const auto childCount = sourceModel()->rowCount(idx);

for (int i = 0; i < childCount; ++i)
{
if (filterAcceptsRow(i, idx))
return true;
}

return false;
}

bool ActionsFilterModel::rowMatches(const QModelIndex& idx) const
{
const auto re = filterRegularExpression();
if (!re.isValid() || re.pattern().isEmpty())
return true;

// Always include DisplayRole at minimum
const QString display = sourceModel()->data(idx, Qt::DisplayRole).toString();
if (display.contains(re))
return true;

for (int r : searchRoles) {
const auto string = sourceModel()->data(idx, r).toString();

if (!string.isEmpty() && string.contains(re))
return true;
}

return false;
}
47 changes: 47 additions & 0 deletions ExampleActions/src/ActionsFilterModel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#pragma once

#include <QSortFilterProxyModel>
#include <QVector>

/**
* A QSortFilterProxyModel that filters recursively through all child items.
*
* @author Thomas Kroes
*/
class ActionsFilterModel final : public QSortFilterProxyModel
{
Q_OBJECT
public:

/**
* Construct with optional parent.
* @param parent The parent QObject.
*/
explicit ActionsFilterModel(QObject* parent = nullptr);

// Optional: include tooltips and ids in matching.
void setSearchRoles(QVector<int> roles);

protected:

/**
* Reimplemented to filter recursively.
* @param sourceRow The row in the source model.
* @param sourceParent The parent index in the source model.
* @return True if the row should be included in the filtered model.
*/
bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override;

private:

/**
* Check if a row matches the current filter.
* @param idx The index of the row to check.
* @return True if the row matches the filter, false otherwise.
*/
bool rowMatches(const QModelIndex& idx) const;


private:
QVector<int> searchRoles; /** The roles to search in. */
};
Loading