@@ -0,0 +1,79 | |||||
|
1 | find_package(PythonLibs 3 REQUIRED) | |||
|
2 | find_package(PythonInterp 3 REQUIRED) | |||
|
3 | find_package(PySide2 REQUIRED) | |||
|
4 | find_package(Shiboken2 REQUIRED) | |||
|
5 | include(PythonInfo) | |||
|
6 | find_python_site_packages(PYTHON_SITE_PACKAGES) | |||
|
7 | ||||
|
8 | set(BINDINGS_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}") | |||
|
9 | set(BINDINGS_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}") | |||
|
10 | ||||
|
11 | configure_file("${BINDINGS_SRC_DIR}/bindings.xml" "${BINDINGS_BUILD_DIR}/bindings.xml" COPYONLY) | |||
|
12 | configure_file("${BINDINGS_SRC_DIR}/main.py" "${BINDINGS_BUILD_DIR}/main.py" COPYONLY) | |||
|
13 | ||||
|
14 | execute_process(COMMAND "${PYTHON_EXECUTABLE}" "${BINDINGS_SRC_DIR}/src_list.py" cmake "${BINDINGS_BUILD_DIR}" OUTPUT_VARIABLE BINDINGS_SOURCE) | |||
|
15 | ||||
|
16 | set_property(SOURCE ${BINDINGS_SOURCE} PROPERTY SKIP_AUTOGEN ON) | |||
|
17 | ||||
|
18 | list(APPEND BINDINGS_INCLUDE_DIRS | |||
|
19 | ${PYTHON_INCLUDE_DIRS} | |||
|
20 | ${Qt5Core_INCLUDE_DIRS} | |||
|
21 | ${Qt5Widgets_INCLUDE_DIRS} | |||
|
22 | ${Qt5Gui_INCLUDE_DIRS} | |||
|
23 | ${CMAKE_CURRENT_SOURCE_DIR}/../../gui/include | |||
|
24 | ${CMAKE_CURRENT_SOURCE_DIR}/../../core/include | |||
|
25 | ${CMAKE_CURRENT_SOURCE_DIR}/../../core/external/TimeSeries/include | |||
|
26 | ) | |||
|
27 | list(REMOVE_DUPLICATES BINDINGS_INCLUDE_DIRS) | |||
|
28 | foreach(DIR ${BINDINGS_INCLUDE_DIRS}) | |||
|
29 | list(APPEND BINDINGS_INCLUDE_DIRS_ARGS "-I${DIR}") | |||
|
30 | endforeach() | |||
|
31 | ||||
|
32 | set(SHIBOKEN_OPTIONS --generator-set=shiboken | |||
|
33 | --enable-parent-ctor-heuristic | |||
|
34 | --enable-return-value-heuristic | |||
|
35 | --use-isnull-as-nb_nonzero | |||
|
36 | --avoid-protected-hack | |||
|
37 | --enable-pyside-extensions | |||
|
38 | -std=c++17) | |||
|
39 | add_custom_command( | |||
|
40 | OUTPUT ${BINDINGS_SOURCE} | |||
|
41 | COMMAND Shiboken2::shiboken2 ${SHIBOKEN_OPTIONS} | |||
|
42 | ${BINDINGS_INCLUDE_DIRS_ARGS} | |||
|
43 | --typesystem-paths=${PYSIDE_TYPESYSTEMS} | |||
|
44 | --output-directory=${CMAKE_CURRENT_BINARY_DIR} | |||
|
45 | ${CMAKE_CURRENT_SOURCE_DIR}/bindings.h ${CMAKE_CURRENT_SOURCE_DIR}/bindings.xml | |||
|
46 | ||||
|
47 | DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/bindings.xml" | |||
|
48 | IMPLICIT_DEPENDS CXX "${CMAKE_CURRENT_SOURCE_DIR}/bindings.h" | |||
|
49 | WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} | |||
|
50 | COMMENT "Generating Python bindings with shiboken2") | |||
|
51 | ||||
|
52 | include_directories( | |||
|
53 | ${PYSIDE_INCLUDE_DIR}/QtCore | |||
|
54 | ${PYSIDE_INCLUDE_DIR}/QtGui | |||
|
55 | ${PYSIDE_INCLUDE_DIR}/QtWidgets) | |||
|
56 | ||||
|
57 | include_directories( | |||
|
58 | ${PYTHON_SITE_PACKAGES}/numpy/core/include/ | |||
|
59 | ${PYTHON_INCLUDE_DIRS} | |||
|
60 | ${SHIBOKEN_INCLUDE_DIR} | |||
|
61 | ${PYSIDE_INCLUDE_DIR} | |||
|
62 | ${PYSIDE_INCLUDE_DIR}/QtCore | |||
|
63 | ${PYSIDE_INCLUDE_DIR}/QtGui | |||
|
64 | ${PYSIDE_INCLUDE_DIR}/QtWidgets) | |||
|
65 | ||||
|
66 | add_library(SciQLopBindings MODULE ${BINDINGS_SOURCE} numpy_wrappers.h) | |||
|
67 | set_target_properties( | |||
|
68 | SciQLopBindings | |||
|
69 | PROPERTIES | |||
|
70 | PREFIX "" | |||
|
71 | OUTPUT_NAME "SciQLopBindings" | |||
|
72 | ) | |||
|
73 | target_link_libraries(SciQLopBindings sciqlopapp) | |||
|
74 | target_link_libraries(SciQLopBindings Shiboken2::libshiboken) | |||
|
75 | target_link_libraries(SciQLopBindings PySide2::pyside2) | |||
|
76 | ||||
|
77 | add_executable(debug_sciqlop_app main.cpp ) | |||
|
78 | find_package (Python3 COMPONENTS Development) | |||
|
79 | target_link_libraries(debug_sciqlop_app PRIVATE Python3::Python) |
@@ -0,0 +1,16 | |||||
|
1 | #pragma once | |||
|
2 | #include <Data/IDataProvider.h> | |||
|
3 | ||||
|
4 | class PyDataProvider : public IDataProvider | |||
|
5 | { | |||
|
6 | public: | |||
|
7 | PyDataProvider() {} | |||
|
8 | ||||
|
9 | virtual TimeSeries::ITimeSerie getData(const std::string& key, double start_time, double stop_time) | |||
|
10 | {} | |||
|
11 | ||||
|
12 | virtual TimeSeries::ITimeSerie* getData(const DataProviderParameters& parameters) | |||
|
13 | { | |||
|
14 | return nullptr; | |||
|
15 | } | |||
|
16 | }; |
@@ -0,0 +1,12 | |||||
|
1 | #ifndef SCIQLOP_BINDINGS_H | |||
|
2 | #define SCIQLOP_BINDINGS_H | |||
|
3 | #define QT_ANNOTATE_ACCESS_SPECIFIER(a) __attribute__((annotate(#a))) | |||
|
4 | #include "../include/MainWindow.h" | |||
|
5 | #include "PyDataProvider.h" | |||
|
6 | #include "numpy_wrappers.h" | |||
|
7 | #include <Data/IDataProvider.h> | |||
|
8 | #include <Data/ScalarTimeSerie.h> | |||
|
9 | #include <SqpApplication.h> | |||
|
10 | ||||
|
11 | ||||
|
12 | #endif // SCIQLOP_BINDINGS_H |
@@ -0,0 +1,72 | |||||
|
1 | <?xml version="1.0"?> | |||
|
2 | <typesystem package="SciQLopBindings"> | |||
|
3 | <load-typesystem name="typesystem_core.xml" generate="no" /> | |||
|
4 | <load-typesystem name="typesystem_gui.xml" generate="no" /> | |||
|
5 | <load-typesystem name="typesystem_widgets.xml" generate="no" /> | |||
|
6 | <primitive-type name="std::string"/> | |||
|
7 | <primitive-type name="std::size_t"/> | |||
|
8 | <container-type name="std::vector" type="vector"> | |||
|
9 | <include file-name="vector" location="global"/> | |||
|
10 | <conversion-rule> | |||
|
11 | <native-to-target> | |||
|
12 | %INTYPE::size_type vectorSize = %in.size(); | |||
|
13 | PyObject* %out = PyList_New((int) vectorSize); | |||
|
14 | for (%INTYPE::size_type idx = 0; idx < vectorSize; ++idx) { | |||
|
15 | %INTYPE_0 cppItem(%in[idx]); | |||
|
16 | PyList_SET_ITEM(%out, idx, %CONVERTTOPYTHON[%INTYPE_0](cppItem)); | |||
|
17 | } | |||
|
18 | return %out; | |||
|
19 | </native-to-target> | |||
|
20 | <target-to-native> | |||
|
21 | <add-conversion type="PySequence"> | |||
|
22 | Shiboken::AutoDecRef seq(PySequence_Fast(%in, 0)); | |||
|
23 | int vectorSize = PySequence_Fast_GET_SIZE(seq.object()); | |||
|
24 | %out.reserve(vectorSize); | |||
|
25 | for (int idx = 0; idx < vectorSize; ++idx ) { | |||
|
26 | PyObject* pyItem = PySequence_Fast_GET_ITEM(seq.object(), idx); | |||
|
27 | %OUTTYPE_0 cppItem = %CONVERTTOCPP[%OUTTYPE_0](pyItem); | |||
|
28 | %out.push_back(cppItem); | |||
|
29 | } | |||
|
30 | </add-conversion> | |||
|
31 | </target-to-native> | |||
|
32 | </conversion-rule> | |||
|
33 | </container-type> | |||
|
34 | <object-type name="MainWindow" /> | |||
|
35 | <object-type name="SqpApplication"> | |||
|
36 | <modify-function signature="SqpApplication(int&,char**)" access="private"/> | |||
|
37 | </object-type> | |||
|
38 | <object-type name="PyDataProvider" /> | |||
|
39 | <function signature="SqpApplication_ctor()"/> | |||
|
40 | <function signature="init_resources()"/> | |||
|
41 | <primitive-type name="NpArray" target-lang-api-name="PyObject"> | |||
|
42 | <include file-name="numpy_wrappers.h" location="local"/> | |||
|
43 | <conversion-rule> | |||
|
44 | <native-to-target> | |||
|
45 | return %in.py_object(); | |||
|
46 | </native-to-target> | |||
|
47 | <target-to-native> | |||
|
48 | <add-conversion type="PyObject" check="NpArray::isNpArray(%in)"> | |||
|
49 | %out = %OUTTYPE(%in); | |||
|
50 | </add-conversion> | |||
|
51 | </target-to-native> | |||
|
52 | </conversion-rule> | |||
|
53 | </primitive-type> | |||
|
54 | <function signature="load_plugins(const SqpApplication&)"/> | |||
|
55 | <object-type name="ScalarTimeSerie"> | |||
|
56 | <add-function signature="ScalarTimeSerie(NpArray&,NpArray&)" return-type="ScalarTimeSerie"> | |||
|
57 | <inject-code class="target"> | |||
|
58 | %BEGIN_ALLOW_THREADS | |||
|
59 | %0 = new ScalarTimeSerieWrapper(); | |||
|
60 | %0.set_data(%1.to_std_vect(),%2.to_std_vect()); | |||
|
61 | %END_ALLOW_THREADS | |||
|
62 | </inject-code> | |||
|
63 | </add-function> | |||
|
64 | <add-function signature="size()" return-type="int" access="public" static="no"> | |||
|
65 | <inject-code class="target"> | |||
|
66 | %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(); | |||
|
67 | %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); | |||
|
68 | </inject-code> | |||
|
69 | </add-function> | |||
|
70 | </object-type> | |||
|
71 | <function signature="test_np_array(NpArray&)"/> | |||
|
72 | </typesystem> |
@@ -0,0 +1,26 | |||||
|
1 | #include <fstream> | |||
|
2 | #include <iostream> | |||
|
3 | #define PY_SSIZE_T_CLEAN | |||
|
4 | #define Py_DEBUG | |||
|
5 | #include <Python.h> | |||
|
6 | ||||
|
7 | int main(int argc, char** argv) | |||
|
8 | { | |||
|
9 | wchar_t* program = Py_DecodeLocale(argv[0], NULL); | |||
|
10 | if (program == NULL) | |||
|
11 | { | |||
|
12 | fprintf(stderr, "Fatal error: cannot decode argv[0]\n"); | |||
|
13 | exit(1); | |||
|
14 | } | |||
|
15 | Py_SetProgramName(program); /* optional but recommended */ | |||
|
16 | Py_Initialize(); | |||
|
17 | std::ifstream t(argv[1]); | |||
|
18 | std::string str((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>()); | |||
|
19 | PyRun_SimpleString(str.data()); | |||
|
20 | if (Py_FinalizeEx() < 0) | |||
|
21 | { | |||
|
22 | exit(120); | |||
|
23 | } | |||
|
24 | PyMem_RawFree(program); | |||
|
25 | return 0; | |||
|
26 | } |
@@ -0,0 +1,102 | |||||
|
1 | # This Python file uses the following encoding: utf-8 | |||
|
2 | import os | |||
|
3 | print(os.getcwd()) | |||
|
4 | import sys | |||
|
5 | from PySide2.QtWidgets import QApplication, QMainWindow, QDockWidget | |||
|
6 | from PySide2.QtCore import QSize, Qt | |||
|
7 | from PySide2 import QtGui | |||
|
8 | import os | |||
|
9 | from SciQLopBindings import SqpApplication, MainWindow, init_resources, load_plugins, SqpApplication_ctor | |||
|
10 | from qtconsole.rich_ipython_widget import RichJupyterWidget | |||
|
11 | from qtconsole.inprocess import QtInProcessKernelManager | |||
|
12 | ||||
|
13 | ||||
|
14 | class IPythonWidget(RichJupyterWidget): | |||
|
15 | """Live IPython console widget. | |||
|
16 | ||||
|
17 | .. image:: img/IPythonWidget.png | |||
|
18 | ||||
|
19 | :param custom_banner: Custom welcome message to be printed at the top of | |||
|
20 | the console. | |||
|
21 | """ | |||
|
22 | ||||
|
23 | def __init__(self, parent=None, custom_banner=None, *args, **kwargs): | |||
|
24 | if parent is not None: | |||
|
25 | kwargs["parent"] = parent | |||
|
26 | super(IPythonWidget, self).__init__(*args, **kwargs) | |||
|
27 | if custom_banner is not None: | |||
|
28 | self.banner = custom_banner | |||
|
29 | self.setWindowTitle(self.banner) | |||
|
30 | self.kernel_manager = kernel_manager = QtInProcessKernelManager() | |||
|
31 | kernel_manager.start_kernel() | |||
|
32 | self.kernel_client = kernel_client = self._kernel_manager.client() | |||
|
33 | kernel_client.start_channels() | |||
|
34 | ||||
|
35 | def stop(): | |||
|
36 | kernel_client.stop_channels() | |||
|
37 | kernel_manager.shutdown_kernel() | |||
|
38 | self.exit_requested.connect(stop) | |||
|
39 | ||||
|
40 | def sizeHint(self): | |||
|
41 | """Return a reasonable default size for usage in :class:`PlotWindow`""" | |||
|
42 | return QSize(500, 300) | |||
|
43 | ||||
|
44 | def pushVariables(self, variable_dict): | |||
|
45 | """ Given a dictionary containing name / value pairs, push those | |||
|
46 | variables to the IPython console widget. | |||
|
47 | ||||
|
48 | :param variable_dict: Dictionary of variables to be pushed to the | |||
|
49 | console's interactive namespace (```{variable_name: object, β¦}```) | |||
|
50 | """ | |||
|
51 | self.kernel_manager.kernel.shell.push(variable_dict) | |||
|
52 | ||||
|
53 | ||||
|
54 | class IPythonDockWidget(QDockWidget): | |||
|
55 | """Dock Widget including a :class:`IPythonWidget` inside | |||
|
56 | a vertical layout. | |||
|
57 | ||||
|
58 | .. image:: img/IPythonDockWidget.png | |||
|
59 | ||||
|
60 | :param available_vars: Dictionary of variables to be pushed to the | |||
|
61 | console's interactive namespace: ``{"variable_name": object, β¦}`` | |||
|
62 | :param custom_banner: Custom welcome message to be printed at the top of | |||
|
63 | the console | |||
|
64 | :param title: Dock widget title | |||
|
65 | :param parent: Parent :class:`qt.QMainWindow` containing this | |||
|
66 | :class:`qt.QDockWidget` | |||
|
67 | """ | |||
|
68 | def __init__(self, parent=None, available_vars=None, custom_banner=None, | |||
|
69 | title="Console"): | |||
|
70 | super(IPythonDockWidget, self).__init__(title, parent) | |||
|
71 | ||||
|
72 | self.ipyconsole = IPythonWidget(custom_banner=custom_banner) | |||
|
73 | ||||
|
74 | self.layout().setContentsMargins(0, 0, 0, 0) | |||
|
75 | self.setWidget(self.ipyconsole) | |||
|
76 | ||||
|
77 | if available_vars is not None: | |||
|
78 | self.ipyconsole.pushVariables(available_vars) | |||
|
79 | self.ipyconsole.pushVariables({"blah":self}) | |||
|
80 | ||||
|
81 | def showEvent(self, event): | |||
|
82 | """Make sure this widget is raised when it is shown | |||
|
83 | (when it is first created as a tab in PlotWindow or when it is shown | |||
|
84 | again after hiding). | |||
|
85 | """ | |||
|
86 | self.raise_() | |||
|
87 | ||||
|
88 | def print_process_id(): | |||
|
89 | print ('Process ID is:', os.getpid()) | |||
|
90 | ||||
|
91 | ||||
|
92 | if __name__ == "__main__": | |||
|
93 | init_resources() | |||
|
94 | app = SqpApplication_ctor() | |||
|
95 | QtGui.qApp = app | |||
|
96 | load_plugins(app) | |||
|
97 | main_window = MainWindow() | |||
|
98 | term = IPythonDockWidget(available_vars={"app":app, "main_window":main_window}, custom_banner="SciQLop IPython Console ") | |||
|
99 | main_window.addDockWidget(Qt.BottomDockWidgetArea, term) | |||
|
100 | main_window.show() | |||
|
101 | sys.exit(app.exec_()) | |||
|
102 |
@@ -0,0 +1,19 | |||||
|
1 | #include "numpy_wrappers.h" | |||
|
2 | ||||
|
3 | // ScalarTimeSerie ScalarTimeSerie_from_np(PyObject* time, PyObject* values) | |||
|
4 | //{ | |||
|
5 | // assert(time); | |||
|
6 | // assert(values); | |||
|
7 | // assert(PyArray_NDIM(time) == 1); | |||
|
8 | // assert(PyArray_NDIM(values) == 1); | |||
|
9 | // assert(PyArray_ISFLOAT(time)); | |||
|
10 | // assert(PyArray_ISFLOAT(values)); | |||
|
11 | // assert(PyArray_DIM(time, 0) == PyArray_DIM(values, 0)); | |||
|
12 | // assert(PyArray_IS_C_CONTIGUOUS(time)); | |||
|
13 | // assert(PyArray_IS_C_CONTIGUOUS(values)); | |||
|
14 | // int size = PyArray_DIM(time, 0); | |||
|
15 | // ScalarTimeSerie ts(size); | |||
|
16 | // for (int i = 0; i < size; i++) | |||
|
17 | // { | |||
|
18 | // } | |||
|
19 | //} |
@@ -0,0 +1,178 | |||||
|
1 | #ifndef NUMPY_WRAPPERS_H | |||
|
2 | #define NUMPY_WRAPPERS_H | |||
|
3 | #include <Data/ScalarTimeSerie.h> | |||
|
4 | #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION | |||
|
5 | #if defined(slots) && (defined(__GNUC__) || defined(_MSC_VER) || defined(__clang__)) | |||
|
6 | #pragma push_macro("slots") | |||
|
7 | #undef slots | |||
|
8 | extern "C" | |||
|
9 | { | |||
|
10 | /* | |||
|
11 | * Python 2 uses the "register" keyword, which is deprecated in C++ 11 | |||
|
12 | * and forbidden in C++17. | |||
|
13 | */ | |||
|
14 | #if defined(__clang__) | |||
|
15 | #pragma clang diagnostic push | |||
|
16 | #pragma clang diagnostic ignored "-Wdeprecated-register" | |||
|
17 | #endif | |||
|
18 | ||||
|
19 | #include <Python.h> | |||
|
20 | #include <numpy/arrayobject.h> | |||
|
21 | ||||
|
22 | #if defined(__clang__) | |||
|
23 | #pragma clang diagnostic pop | |||
|
24 | #endif | |||
|
25 | } | |||
|
26 | #else | |||
|
27 | #include <Python.h> | |||
|
28 | #include <numpy/arrayobject.h> | |||
|
29 | #endif | |||
|
30 | #include <assert.h> | |||
|
31 | ||||
|
32 | inline int init_numpy() | |||
|
33 | { | |||
|
34 | import_array(); // PyError if not successful | |||
|
35 | return 0; | |||
|
36 | } | |||
|
37 | const static int numpy_initialized = init_numpy(); | |||
|
38 | template <typename dest_type = PyObject> | |||
|
39 | struct PyObjectWrapper | |||
|
40 | { | |||
|
41 | private: | |||
|
42 | PyObject* _py_obj; | |||
|
43 | ||||
|
44 | void inc_refcount() | |||
|
45 | { | |||
|
46 | if (_py_obj) | |||
|
47 | Py_IncRef(_py_obj); | |||
|
48 | } | |||
|
49 | void dec_refcount() | |||
|
50 | { | |||
|
51 | if (_py_obj) | |||
|
52 | Py_DecRef(_py_obj); | |||
|
53 | } | |||
|
54 | ||||
|
55 | public: | |||
|
56 | PyObjectWrapper() : _py_obj { nullptr } {} | |||
|
57 | PyObjectWrapper(const PyObjectWrapper& other) : _py_obj { other._py_obj } { inc_refcount(); }; | |||
|
58 | PyObjectWrapper(PyObjectWrapper&& other) : _py_obj { other._py_obj } | |||
|
59 | { | |||
|
60 | other._py_obj = nullptr; | |||
|
61 | } | |||
|
62 | PyObjectWrapper(PyObject* obj) : _py_obj { obj } { inc_refcount(); } | |||
|
63 | ~PyObjectWrapper() { dec_refcount(); } | |||
|
64 | PyObjectWrapper& operator=(PyObjectWrapper&& other) | |||
|
65 | { | |||
|
66 | this->_py_obj = other._py_obj; | |||
|
67 | other._py_obj = nullptr; | |||
|
68 | return *this; | |||
|
69 | } | |||
|
70 | PyObjectWrapper& operator=(const PyObjectWrapper& other) | |||
|
71 | { | |||
|
72 | dec_refcount(); | |||
|
73 | this->_py_obj = other._py_obj; | |||
|
74 | inc_refcount(); | |||
|
75 | return *this; | |||
|
76 | } | |||
|
77 | ||||
|
78 | PyObject* py_object() { return _py_obj; } | |||
|
79 | inline dest_type* get() { return reinterpret_cast<dest_type*>(_py_obj); } | |||
|
80 | inline bool is_null() { return _py_obj == nullptr; } | |||
|
81 | }; | |||
|
82 | ||||
|
83 | struct NpArray | |||
|
84 | { | |||
|
85 | private: | |||
|
86 | PyObjectWrapper<PyArrayObject> _py_obj; | |||
|
87 | NpArray(NpArray& other) = delete; | |||
|
88 | NpArray(const NpArray& other) = delete; | |||
|
89 | NpArray(const NpArray&& other) = delete; | |||
|
90 | ||||
|
91 | public: | |||
|
92 | static bool isNpArray(PyObject* obj) | |||
|
93 | { | |||
|
94 | return obj && PyArray_Check(reinterpret_cast<PyArrayObject*>(obj)) | |||
|
95 | && PyArray_IS_C_CONTIGUOUS(reinterpret_cast<PyArrayObject*>(obj)); | |||
|
96 | } | |||
|
97 | NpArray() : _py_obj { nullptr } {} | |||
|
98 | NpArray(NpArray&& other) : _py_obj { std::move(other._py_obj) } {} | |||
|
99 | explicit NpArray(PyObject* obj) : _py_obj { obj } | |||
|
100 | { | |||
|
101 | std::cout << "NpArray ctor" << std::endl; | |||
|
102 | assert(isNpArray(obj)); | |||
|
103 | assert(PyArray_ISFLOAT(_py_obj.get())); | |||
|
104 | } | |||
|
105 | ||||
|
106 | NpArray& operator=(const NpArray& other) | |||
|
107 | { | |||
|
108 | this->_py_obj = other._py_obj; | |||
|
109 | return *this; | |||
|
110 | } | |||
|
111 | ||||
|
112 | NpArray& operator=(NpArray&& other) | |||
|
113 | { | |||
|
114 | this->_py_obj = std::move(other._py_obj); | |||
|
115 | return *this; | |||
|
116 | } | |||
|
117 | ||||
|
118 | std::vector<std::size_t> shape() | |||
|
119 | { | |||
|
120 | std::vector<std::size_t> shape; | |||
|
121 | if (!_py_obj.is_null()) | |||
|
122 | { | |||
|
123 | if (int ndim = PyArray_NDIM(_py_obj.get()); ndim > 0) | |||
|
124 | { | |||
|
125 | if (ndim < 10) | |||
|
126 | { | |||
|
127 | shape.resize(ndim); | |||
|
128 | std::copy_n(PyArray_SHAPE(_py_obj.get()), ndim, std::begin(shape)); | |||
|
129 | } | |||
|
130 | } | |||
|
131 | } | |||
|
132 | return shape; | |||
|
133 | } | |||
|
134 | ||||
|
135 | std::size_t flat_size() | |||
|
136 | { | |||
|
137 | auto s = this->shape(); | |||
|
138 | return std::accumulate(std::cbegin(s), std::cend(s), 0); | |||
|
139 | } | |||
|
140 | ||||
|
141 | double data(std::size_t pos) | |||
|
142 | { | |||
|
143 | if (!_py_obj.is_null()) | |||
|
144 | { | |||
|
145 | return reinterpret_cast<double*>(PyArray_DATA(_py_obj.get()))[pos]; | |||
|
146 | } | |||
|
147 | return nan("NAN"); | |||
|
148 | } | |||
|
149 | ||||
|
150 | std::vector<double> to_std_vect() | |||
|
151 | { | |||
|
152 | auto sz = flat_size(); | |||
|
153 | std::vector<double> v(sz); | |||
|
154 | auto d_ptr = reinterpret_cast<double*>(PyArray_DATA(_py_obj.get())); | |||
|
155 | std::copy(d_ptr, d_ptr + sz, std::begin(v)); | |||
|
156 | return v; | |||
|
157 | } | |||
|
158 | ||||
|
159 | PyObject* py_object() { return _py_obj.py_object(); } | |||
|
160 | }; | |||
|
161 | ||||
|
162 | inline int test_np_array(NpArray& arr) | |||
|
163 | { | |||
|
164 | auto shape = arr.shape(); | |||
|
165 | std::cout << "len(shape)=" << shape.size() << std::endl; | |||
|
166 | std::for_each(std::cbegin(shape), std::cend(shape), [](auto sz) { | |||
|
167 | static int i = 0; | |||
|
168 | std::cout << "shape[" << i++ << "]=" << sz << std::endl; | |||
|
169 | }); | |||
|
170 | auto flatsize = std::accumulate(std::cbegin(shape), std::cend(shape), 0); | |||
|
171 | for (auto i = 0; i < flatsize; i++) | |||
|
172 | { | |||
|
173 | std::cout << "data[" << i << "]=" << arr.data(i) << std::endl; | |||
|
174 | } | |||
|
175 | return 1; | |||
|
176 | } | |||
|
177 | ||||
|
178 | #endif //#ifndef NUMPY_WRAPPERS_H |
@@ -0,0 +1,49 | |||||
|
1 | #!/bin/env python3 | |||
|
2 | # taken from https://github.com/radareorg/cutter/blob/master/src/bindings/src_list.py | |||
|
3 | ||||
|
4 | ||||
|
5 | import os | |||
|
6 | import re | |||
|
7 | import sys | |||
|
8 | ||||
|
9 | ||||
|
10 | script_path = os.path.dirname(os.path.realpath(__file__)) | |||
|
11 | ||||
|
12 | ||||
|
13 | def get_cpp_files_gen(args, include_package=True): | |||
|
14 | with open(os.path.join(script_path, "bindings.xml"),'r') as f: | |||
|
15 | txt = f.read() | |||
|
16 | package = re.findall("<typesystem *package=.*", txt)[0].split('"')[1] | |||
|
17 | types = re.findall('(.*object-type *name=.*|.*value-type *name=.*)', txt) | |||
|
18 | types = [t.split('"')[1] for t in types] | |||
|
19 | ||||
|
20 | cpp_files_gen = [f"{package.lower()}_module_wrapper.cpp"] | |||
|
21 | cpp_files_gen.extend([f"{typename.lower()}_wrapper.cpp" for typename in types]) | |||
|
22 | ||||
|
23 | if include_package: | |||
|
24 | cpp_files_gen = [os.path.join(package, f) for f in cpp_files_gen] | |||
|
25 | ||||
|
26 | if len(args) > 0: | |||
|
27 | cpp_files_gen = [os.path.join(args[0], f) for f in cpp_files_gen] | |||
|
28 | ||||
|
29 | return cpp_files_gen | |||
|
30 | ||||
|
31 | ||||
|
32 | def cmd_cmake(args): | |||
|
33 | sys.stdout.write(";".join(get_cpp_files_gen(args))) | |||
|
34 | ||||
|
35 | ||||
|
36 | def cmd_qmake(args): | |||
|
37 | sys.stdout.write("\n".join(get_cpp_files_gen(args)) + "\n") | |||
|
38 | ||||
|
39 | ||||
|
40 | def cmd_meson(args): | |||
|
41 | sys.stdout.write(";".join(get_cpp_files_gen(args, include_package=False))) | |||
|
42 | ||||
|
43 | ||||
|
44 | cmds = {"cmake": cmd_cmake, "qmake": cmd_qmake, "meson": cmd_meson} | |||
|
45 | ||||
|
46 | if len(sys.argv) < 2 or sys.argv[1] not in cmds: | |||
|
47 | print(f"""usage: {sys.argv[0]} [{"/".join(cmds.keys())}] [base path]""") | |||
|
48 | exit(1) | |||
|
49 | cmds[sys.argv[1]](sys.argv[2:]) |
@@ -0,0 +1,84 | |||||
|
1 | ||||
|
2 | set(_module PySide2) | |||
|
3 | ||||
|
4 | find_package(${_module} ${${_module}_FIND_VERSION} CONFIG QUIET) | |||
|
5 | set(_lib_target ${_module}::pyside2) | |||
|
6 | ||||
|
7 | if(NOT ${_module}_FOUND) | |||
|
8 | include(PythonInfo) | |||
|
9 | find_python_site_packages(PYTHON_SITE_PACKAGES) | |||
|
10 | get_python_extension_suffix(PYTHON_EXTENSION_SUFFIX) | |||
|
11 | execute_process( | |||
|
12 | COMMAND "${PYTHON_EXECUTABLE}" -c "if True: | |||
|
13 | from PySide2 import _config | |||
|
14 | print(_config.pyside_library_soversion.split('.')[0]) | |||
|
15 | " | |||
|
16 | OUTPUT_VARIABLE ${_module}_FIND_VERSION_MAJOR | |||
|
17 | OUTPUT_STRIP_TRAILING_WHITESPACE) | |||
|
18 | execute_process( | |||
|
19 | COMMAND "${PYTHON_EXECUTABLE}" -c "if True: | |||
|
20 | from PySide2 import _config | |||
|
21 | print(_config.pyside_library_soversion.split('.')[1]) | |||
|
22 | " | |||
|
23 | OUTPUT_VARIABLE ${_module}_FIND_VERSION_MINOR | |||
|
24 | OUTPUT_STRIP_TRAILING_WHITESPACE) | |||
|
25 | ||||
|
26 | find_library(PYSIDE_LIBRARY | |||
|
27 | NAMES | |||
|
28 | "pyside2${PYTHON_EXTENSION_SUFFIX}" | |||
|
29 | "libpyside2${PYTHON_EXTENSION_SUFFIX}" | |||
|
30 | "pyside2${PYTHON_EXTENSION_SUFFIX}.${${_module}_FIND_VERSION_MAJOR}.${${_module}_FIND_VERSION_MINOR}" | |||
|
31 | "libpyside2${PYTHON_EXTENSION_SUFFIX}.${${_module}_FIND_VERSION_MAJOR}.${${_module}_FIND_VERSION_MINOR}" | |||
|
32 | PATHS "${PYTHON_SITE_PACKAGES}/PySide2") | |||
|
33 | ||||
|
34 | find_path(PYSIDE_INCLUDE_DIR | |||
|
35 | pyside.h | |||
|
36 | PATHS "${PYTHON_SITE_PACKAGES}/PySide2/include") | |||
|
37 | ||||
|
38 | find_path(PYSIDE_TYPESYSTEMS | |||
|
39 | typesystem_core.xml | |||
|
40 | PATHS "${PYTHON_SITE_PACKAGES}/PySide2/typesystems") | |||
|
41 | endif() | |||
|
42 | ||||
|
43 | if(TARGET ${_lib_target}) | |||
|
44 | get_target_property(_is_imported ${_lib_target} IMPORTED) | |||
|
45 | if(_is_imported) | |||
|
46 | get_target_property(_imported_location ${_lib_target} IMPORTED_LOCATION) | |||
|
47 | if(NOT _imported_location) | |||
|
48 | message(STATUS "Target ${_lib_target} does not specify its IMPORTED_LOCATION! Trying to find it ourselves...") | |||
|
49 | set(_find_args) | |||
|
50 | if(${_module}_CONFIG) | |||
|
51 | get_filename_component(_pyside2_lib_dir "${${_module}_CONFIG}/../../../" ABSOLUTE) | |||
|
52 | set(_find_args PATHS "${_pyside2_lib_dir}") | |||
|
53 | endif() | |||
|
54 | find_library(PYSIDE_LIBRARY | |||
|
55 | NAMES | |||
|
56 | "pyside2${PYTHON_CONFIG_SUFFIX}" | |||
|
57 | "pyside2${PYTHON_CONFIG_SUFFIX}.${${_module}_FIND_VERSION_MAJOR}.${${_module}_FIND_VERSION_MINOR}" | |||
|
58 | ${_find_args}) | |||
|
59 | if(NOT PYSIDE_LIBRARY) | |||
|
60 | set(_message_type WARNING) | |||
|
61 | if(${_module}_FIND_REQUIRED) | |||
|
62 | set(_message_type FATAL_ERROR) | |||
|
63 | endif() | |||
|
64 | message(${_message_type} "Failed to manually find library for ${_module}") | |||
|
65 | return() | |||
|
66 | endif() | |||
|
67 | message(STATUS "IMPORTED_LOCATION for ${_lib_target} found: ${PYSIDE_LIBRARY}") | |||
|
68 | set_target_properties(${_lib_target} PROPERTIES IMPORTED_LOCATION "${PYSIDE_LIBRARY}") | |||
|
69 | endif() | |||
|
70 | endif() | |||
|
71 | else() | |||
|
72 | include(FindPackageHandleStandardArgs) | |||
|
73 | find_package_handle_standard_args(${_module} | |||
|
74 | FOUND_VAR ${_module}_FOUND | |||
|
75 | REQUIRED_VARS PYSIDE_LIBRARY PYSIDE_INCLUDE_DIR PYSIDE_TYPESYSTEMS | |||
|
76 | VERSION_VAR ${_module}_VERSION) | |||
|
77 | ||||
|
78 | add_library(${_module}::pyside2 INTERFACE IMPORTED) | |||
|
79 | set_target_properties(${_module}::pyside2 PROPERTIES | |||
|
80 | INTERFACE_INCLUDE_DIRECTORIES "${PYSIDE_INCLUDE_DIR}" | |||
|
81 | INTERFACE_LINK_LIBRARIES "${PYSIDE_LIBRARY}") | |||
|
82 | endif() | |||
|
83 | ||||
|
84 | mark_as_advanced(PYSIDE_INCLUDE_DIR PYSIDE_LIBRARY PYSIDE_BINARY) |
@@ -0,0 +1,106 | |||||
|
1 | ||||
|
2 | set(_module Shiboken2) | |||
|
3 | ||||
|
4 | find_package(${_module} ${${_module}_FIND_VERSION} CONFIG QUIET) | |||
|
5 | set(_executable_target ${_module}::shiboken2) | |||
|
6 | set(_lib_target ${_module}::libshiboken) | |||
|
7 | ||||
|
8 | if(NOT ${_module}_FOUND) | |||
|
9 | include(PythonInfo) | |||
|
10 | find_python_site_packages(PYTHON_SITE_PACKAGES) | |||
|
11 | get_python_extension_suffix(PYTHON_EXTENSION_SUFFIX) | |||
|
12 | ||||
|
13 | execute_process( | |||
|
14 | COMMAND "${PYTHON_EXECUTABLE}" -c "if True: | |||
|
15 | from shiboken2 import _config | |||
|
16 | print(_config.shiboken_library_soversion.split('.')[0]) | |||
|
17 | " | |||
|
18 | OUTPUT_VARIABLE ${_module}_FIND_VERSION_MAJOR | |||
|
19 | OUTPUT_STRIP_TRAILING_WHITESPACE) | |||
|
20 | execute_process( | |||
|
21 | COMMAND "${PYTHON_EXECUTABLE}" -c "if True: | |||
|
22 | from shiboken2 import _config | |||
|
23 | print(_config.shiboken_library_soversion.split('.')[1]) | |||
|
24 | " | |||
|
25 | OUTPUT_VARIABLE ${_module}_FIND_VERSION_MINOR | |||
|
26 | OUTPUT_STRIP_TRAILING_WHITESPACE) | |||
|
27 | ||||
|
28 | find_library(SHIBOKEN_LIBRARY | |||
|
29 | NAMES | |||
|
30 | "libshiboken2${PYTHON_EXTENSION_SUFFIX}.${${_module}_FIND_VERSION_MAJOR}.${${_module}_FIND_VERSION_MINOR}" | |||
|
31 | "shiboken2${PYTHON_EXTENSION_SUFFIX}" | |||
|
32 | PATHS "${PYTHON_SITE_PACKAGES}/shiboken2") | |||
|
33 | ||||
|
34 | find_path(SHIBOKEN_INCLUDE_DIR | |||
|
35 | shiboken.h | |||
|
36 | PATHS "${PYTHON_SITE_PACKAGES}/shiboken2_generator/include") | |||
|
37 | ||||
|
38 | find_file(SHIBOKEN_BINARY | |||
|
39 | shiboken2 | |||
|
40 | PATHS "${PYTHON_SITE_PACKAGES}/shiboken2_generator") | |||
|
41 | endif() | |||
|
42 | ||||
|
43 | if(TARGET ${_executable_target}) | |||
|
44 | get_target_property(_is_imported ${_executable_target} IMPORTED) | |||
|
45 | if(_is_imported) | |||
|
46 | get_target_property(_imported_location ${_executable_target} IMPORTED_LOCATION) | |||
|
47 | if(NOT _imported_location) | |||
|
48 | message(STATUS "Target ${_executable_target} does not specify its IMPORTED_LOCATION! Trying to find it ourselves...") | |||
|
49 | find_file(SHIBOKEN_BINARY | |||
|
50 | shiboken2 | |||
|
51 | PATHS "${SHIBOKEN_SHARED_LIBRARY_DIR}/../bin" | |||
|
52 | NO_DEFAULT_PATH) | |||
|
53 | if(NOT SHIBOKEN_BINARY) | |||
|
54 | set(_message_type WARNING) | |||
|
55 | if(${_module}_FIND_REQUIRED) | |||
|
56 | set(_message_type FATAL_ERROR) | |||
|
57 | endif() | |||
|
58 | message(${_message_type} "Failed to manually find executable for ${_module}") | |||
|
59 | return() | |||
|
60 | endif() | |||
|
61 | message(STATUS "IMPORTED_LOCATION for ${_executable_target} found: ${SHIBOKEN_BINARY}") | |||
|
62 | set_target_properties(${_executable_target} PROPERTIES IMPORTED_LOCATION "${SHIBOKEN_BINARY}") | |||
|
63 | endif() | |||
|
64 | endif() | |||
|
65 | ||||
|
66 | get_target_property(_is_imported ${_lib_target} IMPORTED) | |||
|
67 | if(_is_imported) | |||
|
68 | get_target_property(_imported_location ${_lib_target} IMPORTED_LOCATION) | |||
|
69 | if(NOT _imported_location) | |||
|
70 | message(STATUS "Target ${_lib_target} does not specify its IMPORTED_LOCATION! Trying to find it ourselves...") | |||
|
71 | find_library(SHIBOKEN_LIBRARY | |||
|
72 | NAMES | |||
|
73 | "shiboken2${SHIBOKEN_PYTHON_EXTENSION_SUFFIX}" | |||
|
74 | "shiboken2${SHIBOKEN_PYTHON_EXTENSION_SUFFIX}.${${_module}_FIND_VERSION_MAJOR}.${${_module}_FIND_VERSION_MINOR}" | |||
|
75 | PATHS "${SHIBOKEN_SHARED_LIBRARY_DIR}") | |||
|
76 | if(NOT SHIBOKEN_LIBRARY) | |||
|
77 | set(_message_type WARNING) | |||
|
78 | if(${_module}_FIND_REQUIRED) | |||
|
79 | set(_message_type FATAL_ERROR) | |||
|
80 | endif() | |||
|
81 | message(${_message_type} "Failed to manually find library for ${_module}") | |||
|
82 | return() | |||
|
83 | endif() | |||
|
84 | message(STATUS "IMPORTED_LOCATION for ${_lib_target} found: ${SHIBOKEN_LIBRARY}") | |||
|
85 | set_target_properties(${_lib_target} PROPERTIES IMPORTED_LOCATION "${SHIBOKEN_LIBRARY}") | |||
|
86 | endif() | |||
|
87 | endif() | |||
|
88 | else() | |||
|
89 | include(FindPackageHandleStandardArgs) | |||
|
90 | find_package_handle_standard_args(${_module} | |||
|
91 | FOUND_VAR ${_module}_FOUND | |||
|
92 | REQUIRED_VARS SHIBOKEN_LIBRARY SHIBOKEN_INCLUDE_DIR SHIBOKEN_BINARY | |||
|
93 | VERSION_VAR ${_module}_VERSION) | |||
|
94 | ||||
|
95 | add_library(${_module}::libshiboken INTERFACE IMPORTED) | |||
|
96 | set_target_properties(${_module}::libshiboken PROPERTIES | |||
|
97 | INTERFACE_INCLUDE_DIRECTORIES "${SHIBOKEN_INCLUDE_DIR}" | |||
|
98 | INTERFACE_LINK_LIBRARIES "${SHIBOKEN_LIBRARY}") | |||
|
99 | ||||
|
100 | add_executable(${_module}::shiboken2 IMPORTED) | |||
|
101 | set_target_properties(${_module}::shiboken2 PROPERTIES | |||
|
102 | IMPORTED_LOCATION "${SHIBOKEN_BINARY}") | |||
|
103 | endif() | |||
|
104 | ||||
|
105 | mark_as_advanced(SHIBOKEN_INCLUDE_DIR SHIBOKEN_LIBRARY SHIBOKEN_BINARY) | |||
|
106 |
@@ -0,0 +1,32 | |||||
|
1 | ||||
|
2 | function(find_python_site_packages VAR) | |||
|
3 | if(Python_SITELIB) | |||
|
4 | set("${VAR}" "${Python_SITELIB}" PARENT_SCOPE) | |||
|
5 | return() | |||
|
6 | endif() | |||
|
7 | ||||
|
8 | execute_process( | |||
|
9 | COMMAND "${PYTHON_EXECUTABLE}" -c "if True: | |||
|
10 | from distutils import sysconfig | |||
|
11 | print(sysconfig.get_python_lib(prefix=None, plat_specific=True))" | |||
|
12 | OUTPUT_VARIABLE "${VAR}" | |||
|
13 | OUTPUT_STRIP_TRAILING_WHITESPACE) | |||
|
14 | set("${VAR}" "${${VAR}}" PARENT_SCOPE) | |||
|
15 | endfunction() | |||
|
16 | ||||
|
17 | function(get_python_extension_suffix VAR) | |||
|
18 | # from PySide2 CMakeLists.txt | |||
|
19 | # Result of imp.get_suffixes() depends on the platform, but generally looks something like: | |||
|
20 | # [('.cpython-34m-x86_64-linux-gnu.so', 'rb', 3), ('.cpython-34m.so', 'rb', 3), | |||
|
21 | # ('.abi3.so', 'rb', 3), ('.so', 'rb', 3), ('.py', 'r', 1), ('.pyc', 'rb', 2)] | |||
|
22 | # We pick the first most detailed one, strip of the file extension part. | |||
|
23 | ||||
|
24 | execute_process( | |||
|
25 | COMMAND "${PYTHON_EXECUTABLE}" -c "if True: | |||
|
26 | import sysconfig | |||
|
27 | print(sysconfig.get_config_var('EXT_SUFFIX')) | |||
|
28 | " | |||
|
29 | OUTPUT_VARIABLE "${VAR}" | |||
|
30 | OUTPUT_STRIP_TRAILING_WHITESPACE) | |||
|
31 | set("${VAR}" "${${VAR}}" PARENT_SCOPE) | |||
|
32 | endfunction() |
@@ -1,47 +1,61 | |||||
1 | include_directories(include) |
|
1 | include_directories(include) | |
2 |
|
2 | |||
3 | FILE (GLOB_RECURSE app_SRCS |
|
3 | FILE (GLOB_RECURSE app_SRCS | |
4 | include/*.h |
|
4 | include/*.h | |
5 |
src/ |
|
5 | src/MainWindow.cpp | |
|
6 | src/toolbar.cpp | |||
6 | resources/*.qrc |
|
7 | resources/*.qrc | |
7 | ) |
|
8 | ) | |
8 |
|
9 | |||
9 | QT5_WRAP_UI(UiGenerated_SRCS |
|
10 | QT5_WRAP_UI(UiGenerated_SRCS | |
10 | ui/MainWindow.ui |
|
11 | ui/MainWindow.ui | |
11 | ) |
|
12 | ) | |
12 |
|
13 | |||
|
14 | add_library(sciqlopapp ${UiGenerated_SRCS} ${app_SRCS}) | |||
|
15 | ||||
13 | if(ENABLE_WIN32_CONSOLE) |
|
16 | if(ENABLE_WIN32_CONSOLE) | |
14 | add_executable(sciqlopapp ${app_SRCS} ${UiGenerated_SRCS}) |
|
17 | add_executable(sciqlop src/Main.cpp) | |
15 | else() |
|
18 | else() | |
16 |
add_executable(sciqlop |
|
19 | add_executable(sciqlop WIN32 src/Main.cpp) | |
17 | endif() |
|
20 | endif() | |
18 |
|
21 | |||
19 | if(NOT BUILD_SHARED_LIBS) |
|
22 | if(NOT BUILD_SHARED_LIBS) | |
20 | add_definitions(-DQT_STATICPLUGIN) |
|
23 | add_definitions(-DQT_STATICPLUGIN) | |
21 | if(BUILD_PLUGINS) |
|
24 | if(BUILD_PLUGINS) | |
22 | #target_link_libraries(sciqlopapp mockplugin) |
|
25 | #target_link_libraries(sciqlopapp mockplugin) | |
23 | #target_link_libraries(sciqlopapp amdaplugin) |
|
26 | #target_link_libraries(sciqlopapp amdaplugin) | |
24 | target_link_libraries(sciqlopapp python_providers) |
|
27 | target_link_libraries(sciqlopapp python_providers) | |
25 | endif() |
|
28 | endif() | |
26 | endif() |
|
29 | endif() | |
27 |
|
30 | |||
28 | if(NOT BUILD_PLUGINS) |
|
31 | if(NOT BUILD_PLUGINS) | |
29 | add_definitions(-DSQP_NO_PLUGINS) |
|
32 | add_definitions(-DSQP_NO_PLUGINS) | |
30 | endif() |
|
33 | endif() | |
31 |
|
34 | |||
32 | target_link_libraries(sciqlopapp |
|
35 | target_link_libraries(sciqlopapp | |
33 | Qt5::Core |
|
36 | Qt5::Core | |
34 | Qt5::Widgets |
|
37 | Qt5::Widgets | |
35 | Qt5::Network |
|
38 | Qt5::Network | |
36 | Qt5::PrintSupport |
|
39 | Qt5::PrintSupport | |
37 | Qt5::Svg |
|
40 | Qt5::Svg | |
38 | sciqlopgui |
|
41 | sciqlopgui | |
39 | sciqlopcore |
|
42 | sciqlopcore | |
40 | ) |
|
43 | ) | |
41 |
|
44 | |||
42 | install(TARGETS sciqlopapp DESTINATION ${CMAKE_INSTALL_BINDIR}) |
|
45 | target_link_libraries(sciqlop | |
|
46 | sciqlopapp | |||
|
47 | ) | |||
|
48 | ||||
|
49 | install(TARGETS sciqlopapp | |||
|
50 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} | |||
|
51 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} | |||
|
52 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) | |||
|
53 | ||||
|
54 | ||||
|
55 | install(TARGETS sciqlop DESTINATION ${CMAKE_INSTALL_BINDIR}) | |||
43 | install(FILES resources/SciQLOP.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications/) |
|
56 | install(FILES resources/SciQLOP.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications/) | |
44 | install(FILES resources/SciQLOP.appdata.xml DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/metainfo/) |
|
57 | install(FILES resources/SciQLOP.appdata.xml DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/metainfo/) | |
45 | install(FILES resources/sciqlopLOGO.svg DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/SciQLOP/icons/) |
|
58 | install(FILES resources/sciqlopLOGO.svg DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/SciQLOP/icons/) | |
46 |
|
59 | |||
47 |
|
60 | |||
|
61 | add_subdirectory(PySide2-bindings) |
@@ -1,68 +1,120 | |||||
1 | /*------------------------------------------------------------------------------ |
|
1 | /*------------------------------------------------------------------------------ | |
2 | -- This file is a part of the SciQLop Software |
|
2 | -- This file is a part of the SciQLop Software | |
3 | -- Copyright (C) 2017, Plasma Physics Laboratory - CNRS |
|
3 | -- Copyright (C) 2017, Plasma Physics Laboratory - CNRS | |
4 | -- |
|
4 | -- | |
5 | -- This program is free software; you can redistribute it and/or modify |
|
5 | -- This program is free software; you can redistribute it and/or modify | |
6 | -- it under the terms of the GNU General Public License as published by |
|
6 | -- it under the terms of the GNU General Public License as published by | |
7 | -- the Free Software Foundation; either version 2 of the License, or |
|
7 | -- the Free Software Foundation; either version 2 of the License, or | |
8 | -- (at your option) any later version. |
|
8 | -- (at your option) any later version. | |
9 | -- |
|
9 | -- | |
10 | -- This program is distributed in the hope that it will be useful, |
|
10 | -- This program is distributed in the hope that it will be useful, | |
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | -- GNU General Public License for more details. |
|
13 | -- GNU General Public License for more details. | |
14 | -- |
|
14 | -- | |
15 | -- You should have received a copy of the GNU General Public License |
|
15 | -- You should have received a copy of the GNU General Public License | |
16 | -- along with this program; if not, write to the Free Software |
|
16 | -- along with this program; if not, write to the Free Software | |
17 | -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
17 | -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | -------------------------------------------------------------------------------*/ |
|
18 | -------------------------------------------------------------------------------*/ | |
19 | /*-- Author : Alexis Jeandet |
|
19 | /*-- Author : Alexis Jeandet | |
20 | -- Mail : alexis.jeandet@member.fsf.org |
|
20 | -- Mail : alexis.jeandet@member.fsf.org | |
21 | ----------------------------------------------------------------------------*/ |
|
21 | ----------------------------------------------------------------------------*/ | |
22 | #ifndef SCIQLOP_MAINWINDOW_H |
|
22 | #ifndef SCIQLOP_MAINWINDOW_H | |
23 | #define SCIQLOP_MAINWINDOW_H |
|
23 | #define SCIQLOP_MAINWINDOW_H | |
24 |
|
24 | |||
25 | #include <QListWidgetItem> |
|
25 | #include <PluginManager/PluginManager.h> | |
|
26 | #include <QDir> | |||
26 | #include <QLoggingCategory> |
|
27 | #include <QLoggingCategory> | |
27 | #include <QMainWindow> |
|
28 | #include <QMainWindow> | |
28 | #include <QProgressBar> |
|
29 | #include <QProgressBar> | |
29 | #include <QProgressDialog> |
|
30 | #include <QProgressDialog> | |
30 | #include <QThread> |
|
31 | #include <QThread> | |
31 | #include <QVBoxLayout> |
|
32 | #include <QVBoxLayout> | |
32 | #include <QWidget> |
|
33 | #include <QWidget> | |
|
34 | #include <QtPlugin> | |||
|
35 | #include <SqpApplication.h> | |||
33 |
|
36 | |||
34 | #include <Common/spimpl.h> |
|
37 | #include <Common/spimpl.h> | |
35 |
|
38 | |||
36 | #include <memory> |
|
39 | #include <memory> | |
37 |
|
40 | |||
38 | Q_DECLARE_LOGGING_CATEGORY(LOG_MainWindow) |
|
41 | namespace Ui | |
39 |
|
42 | { | ||
40 | namespace Ui { |
|
|||
41 | class MainWindow; |
|
43 | class MainWindow; | |
42 | } // namespace Ui |
|
44 | } // namespace Ui | |
43 |
|
45 | |||
44 |
|
46 | |||
45 |
class MainWindow : public QMainWindow |
|
47 | class MainWindow : public QMainWindow | |
|
48 | { | |||
46 | Q_OBJECT |
|
49 | Q_OBJECT | |
47 |
|
50 | |||
48 | public: |
|
51 | public: | |
49 |
explicit MainWindow(QWidget |
|
52 | explicit MainWindow(QWidget* parent = nullptr); | |
50 | virtual ~MainWindow() override; |
|
53 | virtual ~MainWindow() override; | |
51 | public slots: |
|
54 | public slots: | |
52 |
|
55 | |||
53 | protected: |
|
56 | protected: | |
54 |
void changeEvent(QEvent |
|
57 | void changeEvent(QEvent* e) override; | |
55 |
void closeEvent(QCloseEvent |
|
58 | void closeEvent(QCloseEvent* event) override; | |
56 |
|
59 | |||
57 |
void keyPressEvent(QKeyEvent |
|
60 | void keyPressEvent(QKeyEvent* event) override; | |
58 |
|
61 | |||
59 | private: |
|
62 | private: | |
60 | std::unique_ptr<Ui::MainWindow> m_Ui; |
|
63 | std::unique_ptr<Ui::MainWindow> m_Ui; | |
61 | // QWidget *m_progressWidget; |
|
64 | // QWidget *m_progressWidget; | |
62 | // QVBoxLayout *m_progressLayout; |
|
65 | // QVBoxLayout *m_progressLayout; | |
63 | // QList<QLopService*> m_qlopServices; |
|
66 | // QList<QLopService*> m_qlopServices; | |
64 | class MainWindowPrivate; |
|
67 | class MainWindowPrivate; | |
65 | spimpl::unique_impl_ptr<MainWindowPrivate> impl; |
|
68 | spimpl::unique_impl_ptr<MainWindowPrivate> impl; | |
66 | }; |
|
69 | }; | |
67 |
|
70 | |||
|
71 | inline void init_resources() | |||
|
72 | { | |||
|
73 | #ifdef QT_STATICPLUGIN | |||
|
74 | #ifndef SQP_NO_PLUGINS | |||
|
75 | Q_IMPORT_PLUGIN(PythonProviders) | |||
|
76 | Q_INIT_RESOURCE(python_providers); | |||
|
77 | #endif | |||
|
78 | #endif | |||
|
79 | Q_INIT_RESOURCE(sqpguiresources); | |||
|
80 | SqpApplication::setOrganizationName("LPP"); | |||
|
81 | SqpApplication::setOrganizationDomain("lpp.fr"); | |||
|
82 | SqpApplication::setApplicationName("SciQLop"); | |||
|
83 | ||||
|
84 | QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); | |||
|
85 | } | |||
|
86 | ||||
|
87 | inline void load_plugins(const SqpApplication& a) | |||
|
88 | { | |||
|
89 | // Loads plugins | |||
|
90 | auto pluginDir = QDir { a.applicationDirPath() }; | |||
|
91 | auto pluginLookupPath = { | |||
|
92 | #if _WIN32 || _WIN64 | |||
|
93 | a.applicationDirPath() + "/SciQLop" | |||
|
94 | #else | |||
|
95 | a.applicationDirPath() + "/../lib64/SciQLop", | |||
|
96 | a.applicationDirPath() + "/../lib64/sciqlop", | |||
|
97 | a.applicationDirPath() + "/../lib/SciQLop", | |||
|
98 | a.applicationDirPath() + "/../lib/sciqlop", | |||
|
99 | #endif | |||
|
100 | }; | |||
|
101 | ||||
|
102 | #if _WIN32 || _WIN64 | |||
|
103 | pluginDir.mkdir(PLUGIN_DIRECTORY_NAME); | |||
|
104 | pluginDir.cd(PLUGIN_DIRECTORY_NAME); | |||
|
105 | #endif | |||
|
106 | ||||
|
107 | PluginManager pluginManager {}; | |||
|
108 | ||||
|
109 | for (auto&& path : pluginLookupPath) | |||
|
110 | { | |||
|
111 | QDir directory { path }; | |||
|
112 | if (directory.exists()) | |||
|
113 | { | |||
|
114 | pluginManager.loadPlugins(directory); | |||
|
115 | } | |||
|
116 | } | |||
|
117 | pluginManager.loadStaticPlugins(); | |||
|
118 | } | |||
|
119 | ||||
68 | #endif // SCIQLOP_MAINWINDOW_H |
|
120 | #endif // SCIQLOP_MAINWINDOW_H |
@@ -1,98 +1,51 | |||||
1 | /*------------------------------------------------------------------------------ |
|
1 | /*------------------------------------------------------------------------------ | |
2 | -- This file is a part of the QLop Software |
|
2 | -- This file is a part of the QLop Software | |
3 | -- Copyright (C) 2015, Plasma Physics Laboratory - CNRS |
|
3 | -- Copyright (C) 2015, Plasma Physics Laboratory - CNRS | |
4 | -- |
|
4 | -- | |
5 | -- This program is free software; you can redistribute it and/or modify |
|
5 | -- This program is free software; you can redistribute it and/or modify | |
6 | -- it under the terms of the GNU General Public License as published by |
|
6 | -- it under the terms of the GNU General Public License as published by | |
7 | -- the Free Software Foundation; either version 2 of the License, or |
|
7 | -- the Free Software Foundation; either version 2 of the License, or | |
8 | -- (at your option) any later version. |
|
8 | -- (at your option) any later version. | |
9 | -- |
|
9 | -- | |
10 | -- This program is distributed in the hope that it will be useful, |
|
10 | -- This program is distributed in the hope that it will be useful, | |
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | -- GNU General Public License for more details. |
|
13 | -- GNU General Public License for more details. | |
14 | -- |
|
14 | -- | |
15 | -- You should have received a copy of the GNU General Public License |
|
15 | -- You should have received a copy of the GNU General Public License | |
16 | -- along with this program; if not, write to the Free Software |
|
16 | -- along with this program; if not, write to the Free Software | |
17 | -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
17 | -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | -------------------------------------------------------------------------------*/ |
|
18 | -------------------------------------------------------------------------------*/ | |
19 | /*-- Author : Alexis Jeandet |
|
19 | /*-- Author : Alexis Jeandet | |
20 | -- Mail : alexis.jeandet@member.fsf.org |
|
20 | -- Mail : alexis.jeandet@member.fsf.org | |
21 | ----------------------------------------------------------------------------*/ |
|
21 | ----------------------------------------------------------------------------*/ | |
22 | #include "MainWindow.h" |
|
22 | #include "MainWindow.h" | |
23 | #include <QProcessEnvironment> |
|
23 | #include <QProcessEnvironment> | |
24 | #include <QThread> |
|
24 | #include <QThread> | |
25 | #include <SqpApplication.h> |
|
25 | #include <SqpApplication.h> | |
26 | #include <qglobal.h> |
|
26 | #include <qglobal.h> | |
27 |
|
27 | |||
28 | #include <PluginManager/PluginManager.h> |
|
28 | #include <PluginManager/PluginManager.h> | |
29 | #include <QDir> |
|
29 | #include <QDir> | |
30 | #include <QtPlugin> |
|
30 | #include <QtPlugin> | |
31 |
|
31 | |||
32 | #include <QLoggingCategory> |
|
32 | #include <QLoggingCategory> | |
33 |
|
33 | |||
34 | Q_LOGGING_CATEGORY(LOG_Main, "Main") |
|
|||
35 |
|
34 | |||
36 | namespace |
|
35 | namespace | |
37 | { |
|
36 | { | |
38 |
|
37 | |||
39 | const auto PLUGIN_DIRECTORY_NAME = QStringLiteral("plugins"); |
|
38 | const auto PLUGIN_DIRECTORY_NAME = QStringLiteral("plugins"); | |
40 |
|
39 | |||
41 |
|
40 | |||
42 | } // namespace |
|
41 | } // namespace | |
43 |
|
42 | |||
44 | int main(int argc, char* argv[]) |
|
43 | int main(int argc, char* argv[]) | |
45 | { |
|
44 | { | |
46 | #ifdef QT_STATICPLUGIN |
|
45 | init_resources(); | |
47 | #ifndef SQP_NO_PLUGINS |
|
|||
48 | Q_IMPORT_PLUGIN(PythonProviders) |
|
|||
49 | Q_INIT_RESOURCE(python_providers); |
|
|||
50 | #endif |
|
|||
51 | #endif |
|
|||
52 | Q_INIT_RESOURCE(sqpguiresources); |
|
|||
53 |
|
||||
54 | SqpApplication::setOrganizationName("LPP"); |
|
|||
55 | SqpApplication::setOrganizationDomain("lpp.fr"); |
|
|||
56 | SqpApplication::setApplicationName("SciQLop"); |
|
|||
57 |
|
||||
58 | QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); |
|
|||
59 |
|
||||
60 | SqpApplication a { argc, argv }; |
|
46 | SqpApplication a { argc, argv }; | |
61 |
|
47 | load_plugins(a); | ||
62 | MainWindow w; |
|
48 | MainWindow w; | |
63 | w.show(); |
|
49 | w.show(); | |
64 |
|
||||
65 | // Loads plugins |
|
|||
66 | auto pluginDir = QDir { a.applicationDirPath() }; |
|
|||
67 | auto pluginLookupPath = { |
|
|||
68 | #if _WIN32 || _WIN64 |
|
|||
69 | a.applicationDirPath() + "/SciQLop" |
|
|||
70 | #else |
|
|||
71 | a.applicationDirPath() + "/../lib64/SciQLop", |
|
|||
72 | a.applicationDirPath() + "/../lib64/sciqlop", |
|
|||
73 | a.applicationDirPath() + "/../lib/SciQLop", |
|
|||
74 | a.applicationDirPath() + "/../lib/sciqlop", |
|
|||
75 | #endif |
|
|||
76 | }; |
|
|||
77 |
|
||||
78 | #if _WIN32 || _WIN64 |
|
|||
79 | pluginDir.mkdir(PLUGIN_DIRECTORY_NAME); |
|
|||
80 | pluginDir.cd(PLUGIN_DIRECTORY_NAME); |
|
|||
81 | #endif |
|
|||
82 |
|
||||
83 | PluginManager pluginManager {}; |
|
|||
84 |
|
||||
85 | for (auto&& path : pluginLookupPath) |
|
|||
86 | { |
|
|||
87 | QDir directory { path }; |
|
|||
88 | if (directory.exists()) |
|
|||
89 | { |
|
|||
90 | qCDebug(LOG_Main()) |
|
|||
91 | << QObject::tr("Plugin directory: %1").arg(directory.absolutePath()); |
|
|||
92 | pluginManager.loadPlugins(directory); |
|
|||
93 | } |
|
|||
94 | } |
|
|||
95 | pluginManager.loadStaticPlugins(); |
|
|||
96 |
|
||||
97 | return a.exec(); |
|
50 | return a.exec(); | |
98 | } |
|
51 | } |
@@ -1,113 +1,120 | |||||
1 | #ifndef SCIQLOP_SQPAPPLICATION_H |
|
1 | #ifndef SCIQLOP_SQPAPPLICATION_H | |
2 | #define SCIQLOP_SQPAPPLICATION_H |
|
2 | #define SCIQLOP_SQPAPPLICATION_H | |
3 |
|
3 | |||
4 | #include "SqpApplication.h" |
|
4 | #include "SqpApplication.h" | |
5 |
|
5 | |||
6 | #include <QAction> |
|
6 | #include <QAction> | |
7 | #include <QApplication> |
|
7 | #include <QApplication> | |
8 | #include <QLoggingCategory> |
|
8 | #include <QLoggingCategory> | |
9 | #include <QMenuBar> |
|
9 | #include <QMenuBar> | |
10 | #include <QProxyStyle> |
|
10 | #include <QProxyStyle> | |
11 | #include <QStyleOption> |
|
11 | #include <QStyleOption> | |
12 | #include <QWidget> |
|
12 | #include <QWidget> | |
13 | #include <QWidgetAction> |
|
13 | #include <QWidgetAction> | |
14 |
|
14 | |||
15 | #include <Common/spimpl.h> |
|
15 | #include <Common/spimpl.h> | |
16 |
|
16 | |||
17 | Q_DECLARE_LOGGING_CATEGORY(LOG_SqpApplication) |
|
17 | Q_DECLARE_LOGGING_CATEGORY(LOG_SqpApplication) | |
18 |
|
18 | |||
19 | #if defined(sqpApp) |
|
19 | #if defined(sqpApp) | |
20 | #undef sqpApp |
|
20 | #undef sqpApp | |
21 | #endif |
|
21 | #endif | |
22 | #define sqpApp (static_cast<SqpApplication*>(QCoreApplication::instance())) |
|
22 | #define sqpApp (static_cast<SqpApplication*>(QCoreApplication::instance())) | |
23 |
|
23 | |||
24 | class DataSourceController; |
|
24 | class DataSourceController; | |
25 | class NetworkController; |
|
25 | class NetworkController; | |
26 | class TimeController; |
|
26 | class TimeController; | |
27 | class VariableController; |
|
27 | class VariableController; | |
28 | class VariableController2; |
|
28 | class VariableController2; | |
29 | class VariableModel2; |
|
29 | class VariableModel2; | |
30 | class DragDropGuiController; |
|
30 | class DragDropGuiController; | |
31 | class ActionsGuiController; |
|
31 | class ActionsGuiController; | |
32 | class CatalogueController; |
|
32 | class CatalogueController; | |
33 |
|
33 | |||
34 | /* stolen from here https://forum.qt.io/topic/90403/show-tooltip-immediatly/6 */ |
|
34 | /* stolen from here https://forum.qt.io/topic/90403/show-tooltip-immediatly/6 */ | |
35 | class MyProxyStyle : public QProxyStyle |
|
35 | class MyProxyStyle : public QProxyStyle | |
36 | { |
|
36 | { | |
37 | public: |
|
37 | public: | |
38 | using QProxyStyle::QProxyStyle; |
|
38 | using QProxyStyle::QProxyStyle; | |
39 |
|
39 | |||
40 | int styleHint(StyleHint hint, const QStyleOption* option = nullptr, |
|
40 | int styleHint(StyleHint hint, const QStyleOption* option = nullptr, | |
41 | const QWidget* widget = nullptr, QStyleHintReturn* returnData = nullptr) const override |
|
41 | const QWidget* widget = nullptr, QStyleHintReturn* returnData = nullptr) const override | |
42 | { |
|
42 | { | |
43 | if (widget) |
|
43 | if (widget) | |
44 | auto cname = widget->metaObject()->className(); |
|
44 | auto cname = widget->metaObject()->className(); | |
45 | if (hint == QStyle::SH_ToolButton_PopupDelay && widget |
|
45 | if (hint == QStyle::SH_ToolButton_PopupDelay && widget | |
46 | /*&& widget->inherits(QWidgetAction::staticMetaObject.className())*/) |
|
46 | /*&& widget->inherits(QWidgetAction::staticMetaObject.className())*/) | |
47 | { |
|
47 | { | |
48 | return 0; |
|
48 | return 0; | |
49 | } |
|
49 | } | |
50 |
|
50 | |||
51 | return QProxyStyle::styleHint(hint, option, widget, returnData); |
|
51 | return QProxyStyle::styleHint(hint, option, widget, returnData); | |
52 | } |
|
52 | } | |
53 | }; |
|
53 | }; | |
54 |
|
54 | |||
55 | /** |
|
55 | /** | |
56 | * @brief The SqpApplication class aims to make the link between SciQlop |
|
56 | * @brief The SqpApplication class aims to make the link between SciQlop | |
57 | * and its plugins. This is the intermediate class that SciQlop has to use |
|
57 | * and its plugins. This is the intermediate class that SciQlop has to use | |
58 | * in the way to connect a data source. Please first use load method to initialize |
|
58 | * in the way to connect a data source. Please first use load method to initialize | |
59 | * a plugin specified by its metadata name (JSON plugin source) then others specifics |
|
59 | * a plugin specified by its metadata name (JSON plugin source) then others specifics | |
60 | * method will be able to access it. |
|
60 | * method will be able to access it. | |
61 | * You can load a data source driver plugin then create a data source. |
|
61 | * You can load a data source driver plugin then create a data source. | |
62 | */ |
|
62 | */ | |
63 |
|
63 | |||
64 | class SqpApplication : public QApplication |
|
64 | class SqpApplication : public QApplication | |
65 | { |
|
65 | { | |
66 | Q_OBJECT |
|
66 | Q_OBJECT | |
67 | public: |
|
67 | public: | |
68 | explicit SqpApplication(int& argc, char** argv); |
|
68 | explicit SqpApplication(int& argc, char** argv); | |
69 | ~SqpApplication() override; |
|
69 | ~SqpApplication() override; | |
70 | void initialize(); |
|
70 | void initialize(); | |
71 |
|
71 | |||
72 | /// Accessors for the differents sciqlop controllers |
|
72 | /// Accessors for the differents sciqlop controllers | |
73 | DataSourceController& dataSourceController() noexcept; |
|
73 | DataSourceController& dataSourceController() noexcept; | |
74 | NetworkController& networkController() noexcept; |
|
74 | NetworkController& networkController() noexcept; | |
75 | TimeController& timeController() noexcept; |
|
75 | TimeController& timeController() noexcept; | |
76 | VariableController2& variableController() noexcept; |
|
76 | VariableController2& variableController() noexcept; | |
77 | std::shared_ptr<VariableController2> variableControllerOwner() noexcept; |
|
77 | std::shared_ptr<VariableController2> variableControllerOwner() noexcept; | |
78 | CatalogueController& catalogueController() noexcept; |
|
78 | CatalogueController& catalogueController() noexcept; | |
79 |
|
79 | |||
80 | /// Accessors for the differents sciqlop helpers, these helpers classes are like controllers but |
|
80 | /// Accessors for the differents sciqlop helpers, these helpers classes are like controllers but | |
81 | /// doesn't live in a thread and access gui |
|
81 | /// doesn't live in a thread and access gui | |
82 | DragDropGuiController& dragDropGuiController() noexcept; |
|
82 | DragDropGuiController& dragDropGuiController() noexcept; | |
83 | ActionsGuiController& actionsGuiController() noexcept; |
|
83 | ActionsGuiController& actionsGuiController() noexcept; | |
84 |
|
84 | |||
85 | enum class PlotsInteractionMode |
|
85 | enum class PlotsInteractionMode | |
86 | { |
|
86 | { | |
87 | None, |
|
87 | None, | |
88 | ZoomBox, |
|
88 | ZoomBox, | |
89 | DragAndDrop, |
|
89 | DragAndDrop, | |
90 | SelectionZones |
|
90 | SelectionZones | |
91 | }; |
|
91 | }; | |
92 |
|
92 | |||
93 | enum class PlotsCursorMode |
|
93 | enum class PlotsCursorMode | |
94 | { |
|
94 | { | |
95 | NoCursor, |
|
95 | NoCursor, | |
96 | Vertical, |
|
96 | Vertical, | |
97 | Temporal, |
|
97 | Temporal, | |
98 | Horizontal, |
|
98 | Horizontal, | |
99 | Cross |
|
99 | Cross | |
100 | }; |
|
100 | }; | |
101 |
|
101 | |||
102 | PlotsInteractionMode plotsInteractionMode() const; |
|
102 | PlotsInteractionMode plotsInteractionMode() const; | |
103 | void setPlotsInteractionMode(PlotsInteractionMode mode); |
|
103 | void setPlotsInteractionMode(PlotsInteractionMode mode); | |
104 |
|
104 | |||
105 | PlotsCursorMode plotsCursorMode() const; |
|
105 | PlotsCursorMode plotsCursorMode() const; | |
106 | void setPlotsCursorMode(PlotsCursorMode mode); |
|
106 | void setPlotsCursorMode(PlotsCursorMode mode); | |
107 |
|
107 | |||
108 | private: |
|
108 | private: | |
109 | class SqpApplicationPrivate; |
|
109 | class SqpApplicationPrivate; | |
110 | spimpl::unique_impl_ptr<SqpApplicationPrivate> impl; |
|
110 | spimpl::unique_impl_ptr<SqpApplicationPrivate> impl; | |
111 | }; |
|
111 | }; | |
112 |
|
112 | |||
|
113 | inline SqpApplication* SqpApplication_ctor() | |||
|
114 | { | |||
|
115 | static int argc; | |||
|
116 | static char** argv; | |||
|
117 | return new SqpApplication(argc, argv); | |||
|
118 | } | |||
|
119 | ||||
113 | #endif // SCIQLOP_SQPAPPLICATION_H |
|
120 | #endif // SCIQLOP_SQPAPPLICATION_H |
@@ -1,194 +1,152 | |||||
1 | /* |
|
1 | /* | |
2 | This file is part of SciQLop. |
|
2 | This file is part of SciQLop. | |
3 |
|
3 | |||
4 | SciQLop is free software: you can redistribute it and/or modify |
|
4 | SciQLop is free software: you can redistribute it and/or modify | |
5 | it under the terms of the GNU General Public License as published by |
|
5 | it under the terms of the GNU General Public License as published by | |
6 | the Free Software Foundation, either version 3 of the License, or |
|
6 | the Free Software Foundation, either version 3 of the License, or | |
7 | (at your option) any later version. |
|
7 | (at your option) any later version. | |
8 |
|
8 | |||
9 | SciQLop is distributed in the hope that it will be useful, |
|
9 | SciQLop is distributed in the hope that it will be useful, | |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | GNU General Public License for more details. |
|
12 | GNU General Public License for more details. | |
13 |
|
13 | |||
14 | You should have received a copy of the GNU General Public License |
|
14 | You should have received a copy of the GNU General Public License | |
15 | along with SciQLop. If not, see <https://www.gnu.org/licenses/>. |
|
15 | along with SciQLop. If not, see <https://www.gnu.org/licenses/>. | |
16 | */ |
|
16 | */ | |
17 | #include "Catalogue2/eventsmodel.h" |
|
17 | #include "Catalogue2/eventsmodel.h" | |
18 | #include <Common/containers.h> |
|
18 | #include <Common/containers.h> | |
19 | #include <SqpApplication.h> |
|
19 | #include <SqpApplication.h> | |
20 |
|
20 | |||
21 | EventsModel::EventsModel(QObject* parent) : QAbstractItemModel(parent) {} |
|
21 | EventsModel::EventsModel(QObject* parent) : QAbstractItemModel(parent) {} | |
22 |
|
22 | |||
23 | EventsModel::ItemType EventsModel::type(const QModelIndex& index) const |
|
23 | EventsModel::ItemType EventsModel::type(const QModelIndex& index) const | |
24 | { |
|
24 | { | |
25 | if (EventsModelItem* item = to_item(index)) |
|
25 | if (EventsModelItem* item = to_item(index)) | |
26 | { |
|
26 | { | |
27 | return item->type; |
|
27 | return item->type; | |
28 | } |
|
28 | } | |
29 | return ItemType::None; |
|
29 | return ItemType::None; | |
30 | } |
|
30 | } | |
31 |
|
31 | |||
32 | QVariant EventsModel::data(const QModelIndex& index, int role) const |
|
32 | QVariant EventsModel::data(const QModelIndex& index, int role) const | |
33 | { |
|
33 | { | |
34 | if (index.isValid()) |
|
34 | if (index.isValid()) | |
35 | { |
|
35 | { | |
36 | return to_item(index)->data(index.column(), role); |
|
36 | return to_item(index)->data(index.column(), role); | |
37 | } |
|
37 | } | |
38 | return QVariant {}; |
|
38 | return QVariant {}; | |
39 | } |
|
39 | } | |
40 |
|
40 | |||
41 | QModelIndex EventsModel::index(int row, int column, const QModelIndex& parent) const |
|
41 | QModelIndex EventsModel::index(int row, int column, const QModelIndex& parent) const | |
42 | { |
|
42 | { | |
43 | if (!hasIndex(row, column, parent)) |
|
43 | if (!hasIndex(row, column, parent)) | |
44 | { |
|
44 | { | |
45 | return QModelIndex(); |
|
45 | return QModelIndex(); | |
46 | } |
|
46 | } | |
47 |
|
47 | |||
48 | switch (type(parent)) |
|
48 | switch (type(parent)) | |
49 | { |
|
49 | { | |
50 | case ItemType::None: // is an event |
|
50 | case ItemType::None: // is an event | |
51 | return createIndex(row, column, _items[row].get()); |
|
51 | return createIndex(row, column, _items[row].get()); | |
52 | case ItemType::Event: // is a product |
|
52 | case ItemType::Event: // is a product | |
53 | return createIndex(row, column, to_item(parent)->children[row].get()); |
|
53 | return createIndex(row, column, to_item(parent)->children[row].get()); | |
54 | case ItemType::Product: |
|
54 | case ItemType::Product: | |
55 | QModelIndex(); |
|
55 | QModelIndex(); | |
56 | } |
|
56 | } | |
57 |
|
57 | |||
58 | return QModelIndex(); |
|
58 | return QModelIndex(); | |
59 | } |
|
59 | } | |
60 |
|
60 | |||
61 | QModelIndex EventsModel::parent(const QModelIndex& index) const |
|
61 | QModelIndex EventsModel::parent(const QModelIndex& index) const | |
62 | { |
|
62 | { | |
63 | auto item = to_item(index); |
|
63 | auto item = to_item(index); | |
64 | if (item->type == ItemType::Product) |
|
64 | if (item->type == ItemType::Product) | |
65 | { |
|
65 | { | |
66 | auto repoIndex = SciQLop::containers::index_of(_items, item->parent); |
|
66 | auto repoIndex = SciQLop::containers::index_of(_items, item->parent); | |
67 | return createIndex(repoIndex, 0, item->parent); |
|
67 | return createIndex(repoIndex, 0, item->parent); | |
68 | } |
|
68 | } | |
69 | return QModelIndex(); |
|
69 | return QModelIndex(); | |
70 | } |
|
70 | } | |
71 |
|
71 | |||
72 | int EventsModel::rowCount(const QModelIndex& parent) const |
|
72 | int EventsModel::rowCount(const QModelIndex& parent) const | |
73 | { |
|
73 | { | |
74 | if (parent.column() > 0) |
|
74 | if (parent.column() > 0) | |
75 | { |
|
75 | { | |
76 | return 0; |
|
76 | return 0; | |
77 | } |
|
77 | } | |
78 | switch (type(parent)) |
|
78 | switch (type(parent)) | |
79 | { |
|
79 | { | |
80 | case ItemType::None: |
|
80 | case ItemType::None: | |
81 | return _items.size(); |
|
81 | return _items.size(); | |
82 | case ItemType::Event: |
|
82 | case ItemType::Event: | |
83 | return to_item(parent)->children.size(); |
|
83 | return to_item(parent)->children.size(); | |
84 | case ItemType::Product: |
|
84 | case ItemType::Product: | |
85 | break; |
|
85 | break; | |
86 | } |
|
86 | } | |
87 | return 0; |
|
87 | return 0; | |
88 | } |
|
88 | } | |
89 |
|
89 | |||
90 | int EventsModel::columnCount(const QModelIndex& parent) const |
|
90 | int EventsModel::columnCount(const QModelIndex& parent) const | |
91 | { |
|
91 | { | |
92 | return static_cast<int>(EventsModel::Columns::NbColumn); |
|
92 | return static_cast<int>(EventsModel::Columns::NbColumn); | |
93 | } |
|
93 | } | |
94 |
|
94 | |||
95 | QVariant EventsModel::headerData(int section, Qt::Orientation orientation, int role) const |
|
95 | QVariant EventsModel::headerData(int section, Qt::Orientation orientation, int role) const | |
96 | { |
|
96 | { | |
97 | if (orientation == Qt::Horizontal && role == Qt::DisplayRole && section < ColumnsNames.size()) |
|
97 | if (orientation == Qt::Horizontal && role == Qt::DisplayRole && section < ColumnsNames.size()) | |
98 | { |
|
98 | { | |
99 | return ColumnsNames[section]; |
|
99 | return ColumnsNames[section]; | |
100 | } |
|
100 | } | |
101 |
|
101 | |||
102 | return QVariant(); |
|
102 | return QVariant(); | |
103 | } |
|
103 | } | |
104 |
|
104 | |||
105 | void EventsModel::sort(int column, Qt::SortOrder order) |
|
105 | void EventsModel::sort(int column, Qt::SortOrder order) | |
106 | { |
|
106 | { | |
107 | beginResetModel(); |
|
107 | beginResetModel(); | |
108 | switch (static_cast<Columns>(column)) |
|
108 | switch (static_cast<Columns>(column)) | |
109 | { |
|
109 | { | |
110 | case EventsModel::Columns::Name: |
|
110 | case EventsModel::Columns::Name: | |
111 | std::sort(std::begin(_items), std::end(_items), |
|
111 | std::sort(std::begin(_items), std::end(_items), | |
112 | [inverse = order != Qt::SortOrder::AscendingOrder]( |
|
112 | [inverse = order != Qt::SortOrder::AscendingOrder]( | |
113 | const std::unique_ptr<EventsModelItem>& a, |
|
113 | const std::unique_ptr<EventsModelItem>& a, | |
114 | const std::unique_ptr<EventsModelItem>& b) { |
|
114 | const std::unique_ptr<EventsModelItem>& b) { | |
115 | static int i = 0; |
|
|||
116 | i++; |
|
|||
117 | if (!a->event()) |
|
|||
118 | { |
|
|||
119 | throw; |
|
|||
120 | } |
|
|||
121 | if (!b->event()) |
|
|||
122 | { |
|
|||
123 | throw; |
|
|||
124 | } |
|
|||
125 | return (a->event()->name < b->event()->name) xor inverse; |
|
115 | return (a->event()->name < b->event()->name) xor inverse; | |
126 | }); |
|
116 | }); | |
127 | break; |
|
117 | break; | |
128 | case EventsModel::Columns::TStart: |
|
118 | case EventsModel::Columns::TStart: | |
129 | std::sort(std::begin(_items), std::end(_items), |
|
119 | std::sort(std::begin(_items), std::end(_items), | |
130 | [inverse = order != Qt::SortOrder::AscendingOrder]( |
|
120 | [inverse = order != Qt::SortOrder::AscendingOrder]( | |
131 | const std::unique_ptr<EventsModelItem>& a, |
|
121 | const std::unique_ptr<EventsModelItem>& a, | |
132 | const std::unique_ptr<EventsModelItem>& b) { |
|
122 | const std::unique_ptr<EventsModelItem>& b) { | |
133 | static int i = 0; |
|
123 | if (auto t1 = a->event()->startTime(); auto t2 = b->event()->startTime()) | |
134 | i++; |
|
|||
135 | if (!a) |
|
|||
136 | { |
|
|||
137 | throw; |
|
|||
138 | } |
|
|||
139 | if (!b) |
|
|||
140 | { |
|
|||
141 | throw; |
|
|||
142 | } |
|
|||
143 | if (!a->event()) |
|
|||
144 | { |
|
|||
145 | throw; |
|
|||
146 | } |
|
|||
147 | if (!b->event()) |
|
|||
148 | { |
|
124 | { | |
149 |
|
|
125 | if (t1 and t2) | |
|
126 | return bool((t1.value() < t2.value()) xor inverse); | |||
150 | } |
|
127 | } | |
151 | return (a->event()->name < b->event()->name) xor inverse; |
|
128 | return true; | |
152 | }); |
|
129 | }); | |
153 | // std::sort(std::begin(_items), std::end(_items), |
|
|||
154 | // [inverse = order != Qt::SortOrder::AscendingOrder]( |
|
|||
155 | // const std::unique_ptr<EventsModelItem>& a, |
|
|||
156 | // const std::unique_ptr<EventsModelItem>& b) { |
|
|||
157 | // static int i = 0; |
|
|||
158 | // i++; |
|
|||
159 | // if (a and b) |
|
|||
160 | // { |
|
|||
161 | // if (a->type == ItemType::Event and b->type == ItemType::Event) |
|
|||
162 | // { |
|
|||
163 | // if (auto e1 = a->event(); auto e2 = b->event()) |
|
|||
164 | // { |
|
|||
165 | // return bool((e1->startTime() < e2->startTime()) xor |
|
|||
166 | // inverse); |
|
|||
167 | // } |
|
|||
168 | // } |
|
|||
169 | // } |
|
|||
170 | // return false; |
|
|||
171 | // }); |
|
|||
172 | break; |
|
130 | break; | |
173 | case EventsModel::Columns::TEnd: |
|
131 | case EventsModel::Columns::TEnd: | |
174 | std::sort(std::begin(_items), std::end(_items), |
|
132 | std::sort(std::begin(_items), std::end(_items), | |
175 | [inverse = order != Qt::SortOrder::AscendingOrder]( |
|
133 | [inverse = order != Qt::SortOrder::AscendingOrder]( | |
176 | const std::unique_ptr<EventsModelItem>& a, |
|
134 | const std::unique_ptr<EventsModelItem>& a, | |
177 | const std::unique_ptr<EventsModelItem>& b) { |
|
135 | const std::unique_ptr<EventsModelItem>& b) { | |
178 | if (auto t1 = a->event()->stopTime(); auto t2 = b->event()->stopTime()) |
|
136 | if (auto t1 = a->event()->stopTime(); auto t2 = b->event()->stopTime()) | |
179 | { |
|
137 | { | |
180 | if (t1 and t2) |
|
138 | if (t1 and t2) | |
181 | return bool((t1.value() < t2.value()) xor inverse); |
|
139 | return bool((t1.value() < t2.value()) xor inverse); | |
182 | } |
|
140 | } | |
183 | return true; |
|
141 | return true; | |
184 | }); |
|
142 | }); | |
185 | break; |
|
143 | break; | |
186 | case EventsModel::Columns::Product: |
|
144 | case EventsModel::Columns::Product: | |
187 | break; |
|
145 | break; | |
188 | case EventsModel::Columns::Tags: |
|
146 | case EventsModel::Columns::Tags: | |
189 | break; |
|
147 | break; | |
190 | default: |
|
148 | default: | |
191 | break; |
|
149 | break; | |
192 | } |
|
150 | } | |
193 | endResetModel(); |
|
151 | endResetModel(); | |
194 | } |
|
152 | } |
@@ -1,10 +1,10 | |||||
1 | include(sciqlop_tests) |
|
1 | include(sciqlop_tests) | |
2 | subdirs(GUITestUtils) |
|
2 | subdirs(GUITestUtils) | |
3 | declare_test(simple_graph simple_graph simple_graph/main.cpp "sciqlopgui;TestUtils;GUITestUtils;Qt5::Test") |
|
3 | declare_test(simple_graph simple_graph simple_graph/main.cpp "sciqlopgui;TestUtils;GUITestUtils;Qt5::Test") | |
4 | declare_test(multiple_sync_graph multiple_sync_graph multiple_sync_graph/main.cpp "sciqlopgui;TestUtils;GUITestUtils;Qt5::Test") |
|
4 | declare_test(multiple_sync_graph multiple_sync_graph multiple_sync_graph/main.cpp "sciqlopgui;TestUtils;GUITestUtils;Qt5::Test") | |
5 |
|
5 | declare_test(catalogue_browser catalogue_browser catalogue/browser/main.cpp "sciqlopgui;TestUtils;GUITestUtils;Qt5::Test") | ||
6 | if(NOT WIN32) |
|
6 | if(NOT WIN32) | |
7 | declare_manual_test(event_list event_list catalogue/event_list/main.cpp "sciqlopgui;TestUtils;GUITestUtils;Qt5::Test") |
|
7 | declare_manual_test(event_list event_list catalogue/event_list/main.cpp "sciqlopgui;TestUtils;GUITestUtils;Qt5::Test") | |
8 | declare_manual_test(repository_list repository_list catalogue/repository_list/main.cpp "sciqlopgui;TestUtils;GUITestUtils;Qt5::Test") |
|
8 | declare_manual_test(repository_list repository_list catalogue/repository_list/main.cpp "sciqlopgui;TestUtils;GUITestUtils;Qt5::Test") | |
9 | declare_manual_test(catalogue_browser catalogue_browser catalogue/browser/main.cpp "sciqlopgui;TestUtils;GUITestUtils;Qt5::Test") |
|
9 | declare_manual_test(catalogue_browser_m catalogue_browser_m catalogue/browser/main.cpp "sciqlopgui;TestUtils;GUITestUtils;Qt5::Test") | |
10 | endif() No newline at end of file |
|
10 | endif() |
@@ -1,69 +1,85 | |||||
1 | #include <QMainWindow> |
|
1 | #include <QMainWindow> | |
2 | #include <QObject> |
|
2 | #include <QObject> | |
3 | #include <QScreen> |
|
3 | #include <QScreen> | |
4 | #include <QString> |
|
4 | #include <QString> | |
5 | #include <QWheelEvent> |
|
5 | #include <QWheelEvent> | |
6 | #include <QtTest> |
|
6 | #include <QtTest> | |
|
7 | #include <cstdlib> | |||
7 |
|
8 | |||
8 |
|
9 | |||
9 | #include <Common/cpp_utils.h> |
|
10 | #include <Common/cpp_utils.h> | |
10 | #include <SqpApplication.h> |
|
11 | #include <SqpApplication.h> | |
11 |
|
12 | |||
12 | #include <GUITestUtils.h> |
|
13 | #include <GUITestUtils.h> | |
13 |
|
14 | |||
14 | #include <Catalogue/CatalogueController.h> |
|
15 | #include <Catalogue/CatalogueController.h> | |
15 | #include <Catalogue2/browser.h> |
|
16 | #include <Catalogue2/browser.h> | |
16 |
|
17 | |||
|
18 | template <int EventsCount = 1000> | |||
|
19 | auto build_CatalogueBrowser_test() | |||
|
20 | { | |||
|
21 | sqpApp->catalogueController().add("test"); | |||
|
22 | sqpApp->catalogueController().add("stuff"); | |||
|
23 | sqpApp->catalogueController().add("default"); | |||
|
24 | sqpApp->catalogueController().add("new catalogue", "default"); | |||
|
25 | auto catalogue = sqpApp->catalogueController().add("new catalogue2", "default"); | |||
|
26 | for (auto _ : std::array<char, EventsCount>()) | |||
|
27 | { | |||
|
28 | static int i = 0; | |||
|
29 | auto event = CatalogueController::make_event_ptr(); | |||
|
30 | event->name = std::string("Event ") + std::to_string(i++); | |||
|
31 | event->tags = { "tag1", "tag2" }; | |||
|
32 | event->products = { CatalogueController::Event_t::Product_t { | |||
|
33 | std::string("Product2") + std::to_string(rand() % 30), | |||
|
34 | static_cast<double>(1532357932 + rand() % 100), | |||
|
35 | static_cast<double>(1532358932 + rand() % 100) }, | |||
|
36 | CatalogueController::Event_t::Product_t { | |||
|
37 | std::string("Product2") + std::to_string(rand() % 30), | |||
|
38 | static_cast<double>(1532357932 + rand() % 200), | |||
|
39 | static_cast<double>(1532358932 + rand() % 200) }, | |||
|
40 | CatalogueController::Event_t::Product_t { | |||
|
41 | std::string("Product2") + std::to_string(rand() % 30), | |||
|
42 | static_cast<double>(1532357932 + rand() % 70), | |||
|
43 | static_cast<double>(1532358932 + rand() % 70) } }; | |||
|
44 | catalogue->add(event); | |||
|
45 | } | |||
|
46 | return std::make_unique<CataloguesBrowser>(); | |||
|
47 | } | |||
17 |
|
48 | |||
18 | class A_CatalogueBrowser : public QObject |
|
49 | class A_CatalogueBrowser : public QObject | |
19 | { |
|
50 | { | |
20 | Q_OBJECT |
|
51 | Q_OBJECT | |
21 | public: |
|
52 | public: | |
22 | explicit A_CatalogueBrowser(QObject* parent = Q_NULLPTR) : QObject(parent) {} |
|
53 | explicit A_CatalogueBrowser(QObject* parent = Q_NULLPTR) : QObject(parent) {} | |
23 |
|
54 | |||
24 | private slots: |
|
55 | private slots: | |
|
56 | void can_sort_events() | |||
|
57 | { | |||
|
58 | auto w = build_CatalogueBrowser_test(); | |||
|
59 | QVERIFY(prepare_gui_test(w.get())); | |||
|
60 | // GET_CHILD_WIDGET_FOR_GUI_TESTS((*w.get()),,,) | |||
|
61 | for (int i = 0; i < 1000000; i++) | |||
|
62 | { | |||
|
63 | QThread::usleep(100); | |||
|
64 | QCoreApplication::processEvents(); | |||
|
65 | } | |||
|
66 | } | |||
25 | }; |
|
67 | }; | |
26 |
|
68 | |||
27 |
|
|
69 | QT_BEGIN_NAMESPACE | |
28 |
|
|
70 | QTEST_ADD_GPU_BLACKLIST_SUPPORT_DEFS | |
29 |
|
|
71 | QT_END_NAMESPACE | |
30 | // int main(int argc, char* argv[]) |
|
|||
31 | //{ |
|
|||
32 | // SqpApplication app { argc, argv }; |
|
|||
33 | // app.setAttribute(Qt::AA_Use96Dpi, true); |
|
|||
34 | // QTEST_DISABLE_KEYPAD_NAVIGATION; |
|
|||
35 | // QTEST_ADD_GPU_BLACKLIST_SUPPORT; |
|
|||
36 | // An_EventList tc; |
|
|||
37 | // QTEST_SET_MAIN_SOURCE_PATH; |
|
|||
38 | // return QTest::qExec(&tc, argc, argv); |
|
|||
39 | //} |
|
|||
40 |
|
||||
41 | #include "main.moc" |
|
|||
42 |
|
||||
43 |
|
||||
44 | int main(int argc, char* argv[]) |
|
72 | int main(int argc, char* argv[]) | |
45 | { |
|
73 | { | |
46 | Q_INIT_RESOURCE(sqpguiresources); |
|
74 | Q_INIT_RESOURCE(sqpguiresources); | |
47 | QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); |
|
|||
48 |
|
75 | |||
49 | SqpApplication a { argc, argv }; |
|
76 | SqpApplication app { argc, argv }; | |
50 | CataloguesBrowser w; |
|
77 | app.setAttribute(Qt::AA_Use96Dpi, true); | |
51 | sqpApp->catalogueController().add("test"); |
|
78 | QTEST_DISABLE_KEYPAD_NAVIGATION; | |
52 | sqpApp->catalogueController().add("stuff"); |
|
79 | QTEST_ADD_GPU_BLACKLIST_SUPPORT; | |
53 | sqpApp->catalogueController().add("default"); |
|
80 | A_CatalogueBrowser tc; | |
54 | sqpApp->catalogueController().add("new catalogue", "default"); |
|
81 | QTEST_SET_MAIN_SOURCE_PATH; | |
55 | auto catalogue = sqpApp->catalogueController().add("new catalogue2", "default"); |
|
82 | return QTest::qExec(&tc, argc, argv); | |
56 | for (auto _ : std::array<char, 1000>()) |
|
|||
57 | { |
|
|||
58 | static int i = 0; |
|
|||
59 | auto event = CatalogueController::make_event_ptr(); |
|
|||
60 | event->name = std::string("Event ") + std::to_string(i++); |
|
|||
61 | event->tags = {"tag1", "tag2"}; |
|
|||
62 | event->products = { CatalogueController::Event_t::Product_t { "Product1", 10., 11. }, |
|
|||
63 | CatalogueController::Event_t::Product_t { "Product2", 11., 12. }, |
|
|||
64 | CatalogueController::Event_t::Product_t { "Product3", 10.2, 11. } }; |
|
|||
65 | catalogue->add(event); |
|
|||
66 | } |
|
|||
67 | w.show(); |
|
|||
68 | return a.exec(); |
|
|||
69 | } |
|
83 | } | |
|
84 | ||||
|
85 | #include "main.moc" |
@@ -1,168 +1,168 | |||||
1 | #include "python_providers.h" |
|
1 | #include "python_providers.h" | |
2 | #include <Data/DataProviderParameters.h> |
|
2 | #include <Data/DataProviderParameters.h> | |
3 | #include <Data/DateTimeRange.h> |
|
3 | #include <Data/DateTimeRange.h> | |
4 | #include <Data/IDataProvider.h> |
|
4 | #include <Data/IDataProvider.h> | |
5 | #include <Data/ScalarTimeSerie.h> |
|
5 | #include <Data/ScalarTimeSerie.h> | |
6 | #include <Data/SpectrogramTimeSerie.h> |
|
6 | #include <Data/SpectrogramTimeSerie.h> | |
7 | #include <Data/TimeSeriesUtils.h> |
|
7 | #include <Data/TimeSeriesUtils.h> | |
8 | #include <Data/VectorTimeSerie.h> |
|
8 | #include <Data/VectorTimeSerie.h> | |
9 | #include <DataSource/DataSourceController.h> |
|
9 | #include <DataSource/DataSourceController.h> | |
10 | #include <DataSource/DataSourceItem.h> |
|
10 | #include <DataSource/DataSourceItem.h> | |
11 | #include <DataSource/DataSourceItemAction.h> |
|
11 | #include <DataSource/DataSourceItemAction.h> | |
12 | #include <QDir> |
|
12 | #include <QDir> | |
13 | #include <QStandardPaths> |
|
13 | #include <QStandardPaths> | |
14 | #include <QStringList> |
|
14 | #include <QStringList> | |
15 | #include <SqpApplication.h> |
|
15 | #include <SqpApplication.h> | |
16 | #include <TimeSeries.h> |
|
16 | #include <TimeSeries.h> | |
17 | #include <functional> |
|
17 | #include <functional> | |
18 | #include <iostream> |
|
18 | #include <iostream> | |
19 |
|
19 | |||
20 |
|
20 | |||
21 | const auto DATA_SOURCE_NAME = QStringLiteral("PythonProviders"); |
|
21 | const auto DATA_SOURCE_NAME = QStringLiteral("PythonProviders"); | |
22 |
|
22 | |||
23 | class PythonProvider : public IDataProvider |
|
23 | class PythonProvider : public IDataProvider | |
24 | { |
|
24 | { | |
25 | public: |
|
25 | public: | |
26 | explicit PythonProvider(PythonInterpreter::provider_funct_t f) : _pythonFunction { f } {} |
|
26 | explicit PythonProvider(PythonInterpreter::provider_funct_t f) : _pythonFunction { f } {} | |
27 |
|
27 | |||
28 | PythonProvider(const PythonProvider& other) : _pythonFunction { other._pythonFunction } {} |
|
28 | PythonProvider(const PythonProvider& other) : _pythonFunction { other._pythonFunction } {} | |
29 |
|
29 | |||
30 | std::shared_ptr<IDataProvider> clone() const override |
|
30 | // std::shared_ptr<IDataProvider> clone() const override | |
31 | { |
|
31 | // { | |
32 | return std::make_shared<PythonProvider>(*this); |
|
32 | // return std::make_shared<PythonProvider>(*this); | |
33 | } |
|
33 | // } | |
34 | virtual TimeSeries::ITimeSerie* getData(const DataProviderParameters& parameters) override |
|
34 | virtual TimeSeries::ITimeSerie* getData(const DataProviderParameters& parameters) override | |
35 | { |
|
35 | { | |
36 | auto product = parameters.m_Data.value("PRODUCT", "").toString().toStdString(); |
|
36 | auto product = parameters.m_Data.value("PRODUCT", "").toString().toStdString(); | |
37 | auto range = parameters.m_Range; |
|
37 | auto range = parameters.m_Range; | |
38 | std::vector<std::tuple<std::string, std::string>> metadata; |
|
38 | std::vector<std::tuple<std::string, std::string>> metadata; | |
39 | std::transform(parameters.m_Data.constKeyValueBegin(), parameters.m_Data.constKeyValueEnd(), |
|
39 | std::transform(parameters.m_Data.constKeyValueBegin(), parameters.m_Data.constKeyValueEnd(), | |
40 | std::back_inserter(metadata), [](const auto& item) { |
|
40 | std::back_inserter(metadata), [](const auto& item) { | |
41 | return std::tuple<std::string, std::string> { item.first.toStdString(), |
|
41 | return std::tuple<std::string, std::string> { item.first.toStdString(), | |
42 | item.second.toString().toStdString() }; |
|
42 | item.second.toString().toStdString() }; | |
43 | }); |
|
43 | }); | |
44 | auto result = _pythonFunction(metadata, range.m_TStart, range.m_TEnd); |
|
44 | auto result = _pythonFunction(metadata, range.m_TStart, range.m_TEnd); | |
45 | return TimeSeriesUtils::copy(result); |
|
45 | return TimeSeriesUtils::copy(result); | |
46 | } |
|
46 | } | |
47 |
|
47 | |||
48 | private: |
|
48 | private: | |
49 | PythonInterpreter::provider_funct_t _pythonFunction; |
|
49 | PythonInterpreter::provider_funct_t _pythonFunction; | |
50 | }; |
|
50 | }; | |
51 |
|
51 | |||
52 |
|
52 | |||
53 | void PythonProviders::initialize() |
|
53 | void PythonProviders::initialize() | |
54 | { |
|
54 | { | |
55 | auto app_path = sqpApp->applicationDirPath(); |
|
55 | auto app_path = sqpApp->applicationDirPath(); | |
56 | _interpreter.eval_str("import sys"); |
|
56 | _interpreter.eval_str("import sys"); | |
57 | for(const auto& path:{"/../lib","/../lib64","/../core","/../../lib"}) |
|
57 | for(const auto& path:{"/../lib","/../lib64","/../core","/../../lib"}) | |
58 | { |
|
58 | { | |
59 | QDir d{app_path+path}; |
|
59 | QDir d{app_path+path}; | |
60 | if(d.exists()) |
|
60 | if(d.exists()) | |
61 | { |
|
61 | { | |
62 | _interpreter.eval_str("sys.path.append(\""+d.path().toStdString()+"\")"); |
|
62 | _interpreter.eval_str("sys.path.append(\""+d.path().toStdString()+"\")"); | |
63 | } |
|
63 | } | |
64 | } |
|
64 | } | |
65 |
|
65 | |||
66 | _interpreter.add_register_callback( |
|
66 | _interpreter.add_register_callback( | |
67 | [this](const std::vector<PythonInterpreter::product_t>& product_list, |
|
67 | [this](const std::vector<PythonInterpreter::product_t>& product_list, | |
68 | PythonInterpreter::provider_funct_t f) { this->register_product(product_list, f); }); |
|
68 | PythonInterpreter::provider_funct_t f) { this->register_product(product_list, f); }); | |
69 |
|
69 | |||
70 | for (const auto& path : QStandardPaths::standardLocations(QStandardPaths::AppLocalDataLocation)) |
|
70 | for (const auto& path : QStandardPaths::standardLocations(QStandardPaths::AppLocalDataLocation)) | |
71 | { |
|
71 | { | |
72 | auto dir = QDir(path + "/python"); |
|
72 | auto dir = QDir(path + "/python"); | |
73 | if (dir.exists()) |
|
73 | if (dir.exists()) | |
74 | { |
|
74 | { | |
75 | for (const auto& entry : |
|
75 | for (const auto& entry : | |
76 | dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name)) |
|
76 | dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name)) | |
77 | { |
|
77 | { | |
78 | if (entry.isFile() && entry.suffix() == "py") |
|
78 | if (entry.isFile() && entry.suffix() == "py") | |
79 | { |
|
79 | { | |
80 | _interpreter.eval(entry.absoluteFilePath().toStdString()); |
|
80 | _interpreter.eval(entry.absoluteFilePath().toStdString()); | |
81 | } |
|
81 | } | |
82 | } |
|
82 | } | |
83 | } |
|
83 | } | |
84 | } |
|
84 | } | |
85 | for (const auto& embed_file : { ":/test.py", ":/amda.py", ":/cdaweb.py"}) |
|
85 | for (const auto& embed_file : { ":/test.py", ":/amda.py", ":/cdaweb.py"}) | |
86 | { |
|
86 | { | |
87 | QFile file(embed_file); |
|
87 | QFile file(embed_file); | |
88 | file.open(QFile::ReadOnly); |
|
88 | file.open(QFile::ReadOnly); | |
89 | if(file.isOpen()) |
|
89 | if(file.isOpen()) | |
90 | _interpreter.eval_str(file.readAll().toStdString()); |
|
90 | _interpreter.eval_str(file.readAll().toStdString()); | |
91 | } |
|
91 | } | |
92 | _interpreter.release(); |
|
92 | _interpreter.release(); | |
93 | } |
|
93 | } | |
94 |
|
94 | |||
95 | PythonProviders::~PythonProviders() {} |
|
95 | PythonProviders::~PythonProviders() {} | |
96 |
|
96 | |||
97 | std::unique_ptr<DataSourceItem> make_folder_item(const QString& name) |
|
97 | std::unique_ptr<DataSourceItem> make_folder_item(const QString& name) | |
98 | { |
|
98 | { | |
99 | return std::make_unique<DataSourceItem>(DataSourceItemType::NODE, name); |
|
99 | return std::make_unique<DataSourceItem>(DataSourceItemType::NODE, name); | |
100 | } |
|
100 | } | |
101 |
|
101 | |||
102 | template <typename T> |
|
102 | template <typename T> | |
103 | DataSourceItem* make_path_items( |
|
103 | DataSourceItem* make_path_items( | |
104 | const T& path_list_begin, const T& path_list_end, DataSourceItem* root) |
|
104 | const T& path_list_begin, const T& path_list_end, DataSourceItem* root) | |
105 | { |
|
105 | { | |
106 | std::for_each(path_list_begin, path_list_end, [&root](const auto& folder_name) mutable { |
|
106 | std::for_each(path_list_begin, path_list_end, [&root](const auto& folder_name) mutable { | |
107 | auto folder_ptr = root->findItem(folder_name); |
|
107 | auto folder_ptr = root->findItem(folder_name); | |
108 | if (folder_ptr == nullptr) |
|
108 | if (folder_ptr == nullptr) | |
109 | { |
|
109 | { | |
110 | auto folder = make_folder_item(folder_name); |
|
110 | auto folder = make_folder_item(folder_name); | |
111 | folder_ptr = folder.get(); |
|
111 | folder_ptr = folder.get(); | |
112 | root->appendChild(std::move(folder)); |
|
112 | root->appendChild(std::move(folder)); | |
113 | } |
|
113 | } | |
114 | root = folder_ptr; |
|
114 | root = folder_ptr; | |
115 | }); |
|
115 | }); | |
116 | return root; |
|
116 | return root; | |
117 | } |
|
117 | } | |
118 |
|
118 | |||
119 | std::unique_ptr<DataSourceItem> make_product_item( |
|
119 | std::unique_ptr<DataSourceItem> make_product_item( | |
120 | const QVariantHash& metaData, const QUuid& dataSourceUid) |
|
120 | const QVariantHash& metaData, const QUuid& dataSourceUid) | |
121 | { |
|
121 | { | |
122 | auto result = std::make_unique<DataSourceItem>(DataSourceItemType::PRODUCT, metaData); |
|
122 | auto result = std::make_unique<DataSourceItem>(DataSourceItemType::PRODUCT, metaData); | |
123 |
|
123 | |||
124 | // Adds plugin name to product metadata |
|
124 | // Adds plugin name to product metadata | |
125 | result->setData(DataSourceItem::PLUGIN_DATA_KEY, DATA_SOURCE_NAME); |
|
125 | result->setData(DataSourceItem::PLUGIN_DATA_KEY, DATA_SOURCE_NAME); | |
126 | result->setData(DataSourceItem::ID_DATA_KEY, metaData.value(DataSourceItem::NAME_DATA_KEY)); |
|
126 | result->setData(DataSourceItem::ID_DATA_KEY, metaData.value(DataSourceItem::NAME_DATA_KEY)); | |
127 |
|
127 | |||
128 | auto productName = metaData.value(DataSourceItem::NAME_DATA_KEY).toString(); |
|
128 | auto productName = metaData.value(DataSourceItem::NAME_DATA_KEY).toString(); | |
129 |
|
129 | |||
130 | // Add action to load product from DataSourceController |
|
130 | // Add action to load product from DataSourceController | |
131 | result->addAction( |
|
131 | result->addAction( | |
132 | std::make_unique<DataSourceItemAction>(QObject::tr("Load %1 product").arg(productName), |
|
132 | std::make_unique<DataSourceItemAction>(QObject::tr("Load %1 product").arg(productName), | |
133 | [productName, dataSourceUid](DataSourceItem& item) { |
|
133 | [productName, dataSourceUid](DataSourceItem& item) { | |
134 | if (auto app = sqpApp) |
|
134 | if (auto app = sqpApp) | |
135 | { |
|
135 | { | |
136 | app->dataSourceController().loadProductItem(dataSourceUid, item); |
|
136 | app->dataSourceController().loadProductItem(dataSourceUid, item); | |
137 | } |
|
137 | } | |
138 | })); |
|
138 | })); | |
139 |
|
139 | |||
140 | return result; |
|
140 | return result; | |
141 | } |
|
141 | } | |
142 |
|
142 | |||
143 | void PythonProviders::register_product( |
|
143 | void PythonProviders::register_product( | |
144 | const std::vector<PythonInterpreter::product_t>& product_list, |
|
144 | const std::vector<PythonInterpreter::product_t>& product_list, | |
145 | PythonInterpreter::provider_funct_t f) |
|
145 | PythonInterpreter::provider_funct_t f) | |
146 | { |
|
146 | { | |
147 | auto& dataSourceController = sqpApp->dataSourceController(); |
|
147 | auto& dataSourceController = sqpApp->dataSourceController(); | |
148 | QString test = DATA_SOURCE_NAME + QUuid::createUuid().toString(); |
|
148 | QString test = DATA_SOURCE_NAME + QUuid::createUuid().toString(); | |
149 | auto id = dataSourceController.registerDataSource(test); |
|
149 | auto id = dataSourceController.registerDataSource(test); | |
150 | auto root = make_folder_item(test); |
|
150 | auto root = make_folder_item(test); | |
151 | std::for_each(std::cbegin(product_list), std::cend(product_list), |
|
151 | std::for_each(std::cbegin(product_list), std::cend(product_list), | |
152 | [id, f, root = root.get()](const auto& product) { |
|
152 | [id, f, root = root.get()](const auto& product) { | |
153 | const auto& path = std::get<0>(product); |
|
153 | const auto& path = std::get<0>(product); | |
154 | auto path_list = QString::fromStdString(path).split('/', QString::SkipEmptyParts); |
|
154 | auto path_list = QString::fromStdString(path).split('/', QString::SkipEmptyParts); | |
155 | auto name = *(std::cend(path_list) - 1); |
|
155 | auto name = *(std::cend(path_list) - 1); | |
156 | auto path_item |
|
156 | auto path_item | |
157 | = make_path_items(std::cbegin(path_list), std::cend(path_list) - 1, root); |
|
157 | = make_path_items(std::cbegin(path_list), std::cend(path_list) - 1, root); | |
158 | QVariantHash metaData { { DataSourceItem::NAME_DATA_KEY, name } }; |
|
158 | QVariantHash metaData { { DataSourceItem::NAME_DATA_KEY, name } }; | |
159 | std::for_each(std::cbegin(std::get<2>(product)), std::cend(std::get<2>(product)), |
|
159 | std::for_each(std::cbegin(std::get<2>(product)), std::cend(std::get<2>(product)), | |
160 | [&metaData](const auto& mdata) { |
|
160 | [&metaData](const auto& mdata) { | |
161 | metaData[QString::fromStdString(mdata.first)] |
|
161 | metaData[QString::fromStdString(mdata.first)] | |
162 | = QString::fromStdString(mdata.second); |
|
162 | = QString::fromStdString(mdata.second); | |
163 | }); |
|
163 | }); | |
164 | path_item->appendChild(make_product_item(metaData, id)); |
|
164 | path_item->appendChild(make_product_item(metaData, id)); | |
165 | }); |
|
165 | }); | |
166 | dataSourceController.setDataSourceItem(id, std::move(root)); |
|
166 | dataSourceController.setDataSourceItem(id, std::move(root)); | |
167 | dataSourceController.setDataProvider(id, std::make_unique<PythonProvider>(f)); |
|
167 | dataSourceController.setDataProvider(id, std::make_unique<PythonProvider>(f)); | |
168 | } |
|
168 | } |
General Comments 0
You need to be logged in to leave comments.
Login now