diff --git a/cpp/modmesh/view/CMakeLists.txt b/cpp/modmesh/view/CMakeLists.txt index 83885919..3a026d2c 100644 --- a/cpp/modmesh/view/CMakeLists.txt +++ b/cpp/modmesh/view/CMakeLists.txt @@ -7,6 +7,7 @@ set(MODMESH_VIEW_PYMODHEADERS ${CMAKE_CURRENT_SOURCE_DIR}/R3DWidget.hpp ${CMAKE_CURRENT_SOURCE_DIR}/RWorld.hpp ${CMAKE_CURRENT_SOURCE_DIR}/RManager.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/RParameter.hpp ${CMAKE_CURRENT_SOURCE_DIR}/RAxisMark.hpp ${CMAKE_CURRENT_SOURCE_DIR}/RPythonConsoleDockWidget.hpp ${CMAKE_CURRENT_SOURCE_DIR}/RStaticMesh.hpp @@ -20,6 +21,7 @@ set(MODMESH_VIEW_PYMODSOURCES ${CMAKE_CURRENT_SOURCE_DIR}/R3DWidget.cpp ${CMAKE_CURRENT_SOURCE_DIR}/RWorld.cpp ${CMAKE_CURRENT_SOURCE_DIR}/RManager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/RParameter.cpp ${CMAKE_CURRENT_SOURCE_DIR}/RAxisMark.cpp ${CMAKE_CURRENT_SOURCE_DIR}/RPythonConsoleDockWidget.cpp ${CMAKE_CURRENT_SOURCE_DIR}/RStaticMesh.cpp diff --git a/cpp/modmesh/view/RManager.cpp b/cpp/modmesh/view/RManager.cpp index 27b82643..2783ab8e 100644 --- a/cpp/modmesh/view/RManager.cpp +++ b/cpp/modmesh/view/RManager.cpp @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -211,6 +212,22 @@ void RManager::setUpMenu() this->addApplication(QString("linear_wave")); this->addApplication(QString("bad_euler1d")); } + + { + QAction * params = new RAction( + QString("Parameters"), + QString("Runtime parameters"), + []() + { + static int64_t int64V = 5566; + static double doubleV = 77.88; + auto params = createParameters(); + addParam(params, "global.a.b.int64_foo", &int64V); + addParam(params, "global.a.b.double_bar", &doubleV); + openParameterView(params); + }); + m_mainWindow->menuBar()->addAction(params); + } } void RManager::clearApplications() diff --git a/cpp/modmesh/view/RParameter.cpp b/cpp/modmesh/view/RParameter.cpp new file mode 100644 index 00000000..d50a2463 --- /dev/null +++ b/cpp/modmesh/view/RParameter.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023, Buganini Chiu + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include // Must be the first include. + +namespace modmesh +{ +pybind11::tuple createParameters(void) +{ + pybind11::module pui_module = pybind11::module::import("PUI"); + return pybind11::make_tuple( + pui_module.attr("StateDict")(), pybind11::list()); +} + +void openParameterView(pybind11::tuple & params) +{ + pybind11::module params_module = pybind11::module::import("modmesh.params"); + params_module.attr("openParameterView")(params[1]); +} + +} /* end namespace modmesh */ + +// vim: set ff=unix fenc=utf8 et sw=4 ts=4 sts=4: diff --git a/cpp/modmesh/view/RParameter.hpp b/cpp/modmesh/view/RParameter.hpp new file mode 100644 index 00000000..2811d0ae --- /dev/null +++ b/cpp/modmesh/view/RParameter.hpp @@ -0,0 +1,56 @@ +#pragma once + +/* + * Copyright (c) 2023, Buganini Chiu + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include // Must be the first include. + +namespace modmesh +{ + +pybind11::tuple createParameters(void); +void openParameterView(pybind11::tuple & params); + +template +void addParam(pybind11::tuple & params, const char * key, T * ptr) +{ + params[0][pybind11::str(key)] = *ptr; + auto binding = params[0](key); + binding.attr("bind")( + pybind11::cpp_function([ptr]() + { return *ptr; }), + pybind11::cpp_function([key, ptr](T value) + { + std::cout << "Set " << key << " = " << value << std::endl; + *ptr = value; })); + static_cast(params[1]).append(binding); +} + +} /* end namespace modmesh */ + +// vim: set ff=unix fenc=utf8 et sw=4 ts=4 sts=4: diff --git a/modmesh/params.py b/modmesh/params.py new file mode 100644 index 00000000..d59c43e9 --- /dev/null +++ b/modmesh/params.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# +# Copyright (c) 2023, Buganini Chiu +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# - Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# - Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# - Neither the name of the pstake nor the names of its contributors may be +# used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +import PUI +from PUI.PySide6 import State, PuiInQt, Window, VBox, Table, TextField +from PySide6 import QtWidgets + +if tuple([int(x) for x in PUI.__version__.split(".")]) != (0, 3): + raise ValueError("PUI too old") + + +class ParameterView(PuiInQt): + class TableAdapter: + def __init__(self, state, data): + self.state = state + self._data = data + + def data(self, row, col): + param = self._data[row] + return [param.key, param.value][col] + + def setData(self, row, col, value): + if col == 1: + self._data[row].value = value + + def editable(self, row, col): + return col > 0 + + def columnHeader(self, col): + return ["Key", "Value"][col] + + def rowCount(self): + return len(self._data) + + def columnCount(self): + return 2 + + def __init__(self, container, state): + super().__init__(container) + self.state = state + + def content(self): + data = State() + if not self.state.filter: + data.params = self.state.params + else: + data.params = [ + it + for it in self.state.params + if self.state.filter in it.key + ] + with VBox(): + TextField(self.state("filter")) + Table(self.TableAdapter(self.state, data.params)) + + +def openParameterView(params): + state = State() + state.filter = "" + state.params = params + pv = ParameterView(Window(size=(640, 480)), state) + pv.redraw() + + +if __name__ == "__main__": + class Example(): + def __init__(self): + self.app = QtWidgets.QApplication([]) + + def run(self): + from PUI.PySide6 import StateDict + paramsState = StateDict() + paramsState["a.b.foo_int64"] = 5566 + paramsState["a.b.bar_double"] = 77.88 + paramsList = [ + paramsState("a.b.foo_int64"), + paramsState("a.b.bar_double"), + ] + openParameterView(paramsList) + self.app.exec() + + root = Example() + root.run()