##// END OF EJS Templates
Added cpp_utils as subproject and removed few warnings...
jeandet -
r1485:4f6ae2f1ca26
parent child
Show More
@@ -1,45 +1,46
1 1 shiboken2 = find_program('shiboken2')
2 2 qmake = find_program('qmake-qt5','qmake')
3 3
4 4 pymod = import('python')
5 5 python3 = pymod.find_installation('python3', modules:['PySide2','shiboken2', 'shiboken2_generator'])
6 6
7 7 qt5_modules = ['QtCore','QtGui','QtWidgets']
8 8
9 9 qt_headers_path = run_command(qmake, '-query', 'QT_INSTALL_HEADERS').stdout().strip('\n')
10 10 generated_srcs = run_command(python3, 'src_list.py', 'meson').stdout().split(';')
11 11
12 12 modules_arg = '--modules=@0@'.format(','.join(qt5_modules))
13 13
14 14 shiboken2_build_flags = run_command(python3, 'shiboken-helper.py', '--includes', modules_arg).stdout().strip('\n').split(' ')
15 15 shiboken2_link_flags = run_command(python3, 'shiboken-helper.py', '--libs', modules_arg).stdout().strip('\n').split(' ')
16 16 shiboken2_typesystem = run_command(python3, 'shiboken-helper.py', '--typesystem').stdout().strip('\n')
17 17
18 18 sciqlop_bindings_incs = shiboken2_build_flags + [
19 19 '-I'+meson.current_source_dir()+'/../../gui/include',
20 20 '-I'+meson.current_source_dir()+'/../../core/include',
21 21 '-I'+meson.current_source_dir()+'/../../subprojects/TimeSeries/include',
22 '-I'+meson.current_source_dir()+'/../../subprojects/cpp_utils/include',
22 23 '-I'+python3.get_path('include'),
23 24 '-I'+qt_headers_path
24 25 ]
25 26
26 27 foreach mod:qt5_modules
27 28 sciqlop_bindings_incs += ['-I'+qt_headers_path+'/'+mod]
28 29 endforeach
29 30
30 31
31 32 sciqlop_bindings_src = files('bindings.h', 'PyDataProvider.h', 'numpy_wrappers.h', 'numpy_wrappers.cpp')
32 33
33 34 subdir('SciQLopBindings')
34 35
35 36 shiboken_dep = declare_dependency(compile_args: shiboken2_build_flags, link_args: shiboken2_link_flags)
36 37
37 38 sciqlop_bindings = python3.extension_module('SciQLopBindings',sciqlop_bindings_src,shiboken2_generator_out,
38 dependencies : [sciqlop_app_dep, python3.dependency(), shiboken_dep],
39 dependencies : [sciqlop_app_dep, python3.dependency(), shiboken_dep, cpp_utils_dep],
39 40 )
40 41
41 42
42 43 configure_file(input:'main.py', output:'main.py', copy:true)
43 44 configure_file(input:'TestPlugin.py', output:'TestPlugin.py', copy:true)
44 45
45 46 executable('sciqlop', 'main.cpp', dependencies :python3.dependency())
@@ -1,261 +1,265
1 1 #ifndef NUMPY_WRAPPERS_H
2 2 #define NUMPY_WRAPPERS_H
3 3 #include <Data/ScalarTimeSerie.h>
4 4 #include <Data/VectorTimeSerie.h>
5 5 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
6 6 #if defined(slots) && (defined(__GNUC__) || defined(_MSC_VER) || defined(__clang__))
7 7 #pragma push_macro("slots")
8 8 #undef slots
9 9 extern "C"
10 10 {
11 11 /*
12 12 * Python 2 uses the "register" keyword, which is deprecated in C++ 11
13 13 * and forbidden in C++17.
14 14 */
15 15 #if defined(__clang__)
16 16 #pragma clang diagnostic push
17 17 #pragma clang diagnostic ignored "-Wdeprecated-register"
18 18 #endif
19 19
20 20 #include <Python.h>
21 21 #include <numpy/arrayobject.h>
22 22
23 23 #if defined(__clang__)
24 24 #pragma clang diagnostic pop
25 25 #endif
26 26 }
27 27 #else
28 28 #include <Python.h>
29 29 #include <numpy/arrayobject.h>
30 30 #endif
31 31 #include <assert.h>
32 32
33 33 #include <map>
34 #include <warnings.h>
34 35
35 36 inline int init_numpy()
36 37 {
38 DISABLE_WARNING_PUSH
39 DISABLE_WARNING_CONVERSION_NULL
37 40 import_array(); // PyError if not successful
41 DISABLE_WARNING_POP
38 42 return 0;
39 43 }
40 44 const static int numpy_initialized = init_numpy();
41 45 template <typename dest_type = PyObject>
42 46 struct PyObjectWrapper
43 47 {
44 48 private:
45 49 PyObject* _py_obj = nullptr;
46 50 void inc_refcount() { Py_XINCREF(_py_obj); }
47 51 void dec_refcount()
48 52 {
49 53 Py_XDECREF(_py_obj);
50 54 _py_obj = nullptr;
51 55 }
52 56
53 57 public:
54 58 PyObjectWrapper() : _py_obj { nullptr } {}
55 59 PyObjectWrapper(const PyObjectWrapper& other) : _py_obj { other._py_obj } { inc_refcount(); }
56 60 PyObjectWrapper(PyObjectWrapper&& other) : _py_obj { other._py_obj } { inc_refcount(); }
57 61 explicit PyObjectWrapper(PyObject* obj) : _py_obj { obj } { inc_refcount(); }
58 62 ~PyObjectWrapper() { dec_refcount(); }
59 63 PyObjectWrapper& operator=(PyObjectWrapper&& other)
60 64 {
61 65 dec_refcount();
62 66 this->_py_obj = other._py_obj;
63 67 inc_refcount();
64 68 return *this;
65 69 }
66 70 PyObjectWrapper& operator=(const PyObjectWrapper& other)
67 71 {
68 72 dec_refcount();
69 73 this->_py_obj = other._py_obj;
70 74 inc_refcount();
71 75 return *this;
72 76 }
73 77
74 78 PyObject* py_object() { return _py_obj; }
75 79 inline dest_type* get() { return reinterpret_cast<dest_type*>(_py_obj); }
76 80 inline bool is_null() { return _py_obj == nullptr; }
77 81 };
78 82
79 83 struct NpArray_view
80 84 {
81 85 private:
82 86 PyObjectWrapper<PyArrayObject> _py_obj;
83 87 NpArray_view(const NpArray_view&& other) = delete;
84 88
85 89 public:
86 90 static bool isNpArray(PyObject* obj)
87 91 {
88 92 auto arr = reinterpret_cast<PyArrayObject*>(obj);
89 93 auto is_c_aray = obj && PyArray_Check(arr) && PyArray_ISCARRAY(arr);
90 94 return is_c_aray;
91 95 }
92 96 NpArray_view() : _py_obj { nullptr } {}
93 97 NpArray_view(const NpArray_view& other) : _py_obj { other._py_obj } {}
94 98 NpArray_view(NpArray_view&& other) : _py_obj { other._py_obj } {}
95 99 explicit NpArray_view(PyObject* obj) : _py_obj { obj }
96 100 {
97 101 assert(isNpArray(obj));
98 102 assert(PyArray_ISFLOAT(_py_obj.get()));
99 103 }
100 104
101 105 NpArray_view& operator=(const NpArray_view& other)
102 106 {
103 107 this->_py_obj = other._py_obj;
104 108 return *this;
105 109 }
106 110
107 111 NpArray_view& operator=(NpArray_view&& other)
108 112 {
109 113 this->_py_obj = other._py_obj;
110 114 return *this;
111 115 }
112 116
113 117 std::vector<std::size_t> shape()
114 118 {
115 119 std::vector<std::size_t> shape;
116 120 if (!_py_obj.is_null())
117 121 {
118 122 if (int ndim = PyArray_NDIM(_py_obj.get()); ndim > 0)
119 123 {
120 124 if (ndim < 10)
121 125 {
122 126 shape.resize(ndim);
123 127 std::copy_n(PyArray_SHAPE(_py_obj.get()), ndim, std::begin(shape));
124 128 }
125 129 }
126 130 }
127 131 return shape;
128 132 }
129 133
130 134 std::size_t ndim()
131 135 {
132 136 if (!_py_obj.is_null())
133 137 {
134 138 return static_cast<std::size_t>(PyArray_NDIM(_py_obj.get()));
135 139 }
136 140 return 0;
137 141 }
138 142
139 143 std::size_t size(std::size_t index = 0)
140 144 {
141 145 if (!_py_obj.is_null())
142 146 {
143 147 if (index < static_cast<std::size_t>(PyArray_NDIM(_py_obj.get())))
144 148 {
145 149 return PyArray_SHAPE(_py_obj.get())[index];
146 150 }
147 151 }
148 152 return 0;
149 153 }
150 154
151 155 std::size_t flat_size()
152 156 {
153 157 auto s = this->shape();
154 158 return std::accumulate(
155 159 std::cbegin(s), std::cend(s), 1, [](const auto& a, const auto& b) { return a * b; });
156 160 }
157 161
158 162 double data(std::size_t pos)
159 163 {
160 164 if (!_py_obj.is_null())
161 165 {
162 166 return reinterpret_cast<double*>(PyArray_DATA(_py_obj.get()))[pos];
163 167 }
164 168 return nan("NAN");
165 169 }
166 170
167 171 std::vector<double> to_std_vect()
168 172 {
169 173 assert(!this->_py_obj.is_null());
170 174 auto sz = flat_size();
171 175 std::vector<double> v(sz);
172 176 auto d_ptr = reinterpret_cast<double*>(PyArray_DATA(_py_obj.get()));
173 177 std::copy(d_ptr, d_ptr + sz, std::begin(v));
174 178 return v;
175 179 }
176 180
177 181 std::vector<VectorTimeSerie::raw_value_type> to_std_vect_vect()
178 182 {
179 183 auto sz = size(0);
180 184 std::vector<VectorTimeSerie::raw_value_type> v(sz);
181 185 if (sz)
182 186 {
183 187 assert(ndim() == 2);
184 188 assert(size(1) == 3);
185 189 auto d_ptr
186 190 = reinterpret_cast<VectorTimeSerie::raw_value_type*>(PyArray_DATA(_py_obj.get()));
187 191 std::copy(d_ptr, d_ptr + sz, std::begin(v));
188 192 }
189 193 return v;
190 194 }
191 195
192 196 PyObject* py_object() { return _py_obj.py_object(); }
193 197 };
194 198
195 199 struct NpArray
196 200 {
197 201 std::vector<std::size_t> shape;
198 202 std::vector<double> data;
199 203 static bool isNpArray(PyObject* obj) { return NpArray_view::isNpArray(obj); }
200 204 NpArray() = default;
201 205 explicit NpArray(PyObject* obj)
202 206 {
203 207 if (obj)
204 208 {
205 209 NpArray_view view { obj };
206 210 shape = view.shape();
207 211 data = view.to_std_vect();
208 212 }
209 213 }
210 214
211 215 inline std::size_t ndim() { return shape.size(); }
212 216
213 217 std::size_t size(std::size_t index = 0)
214 218 {
215 219 if (index < shape.size())
216 220 return shape[index];
217 221 return 0;
218 222 }
219 223
220 224 std::size_t flat_size()
221 225 {
222 226 return std::accumulate(std::cbegin(shape), std::cend(shape), 1,
223 227 [](const auto& a, const auto& b) { return a * b; });
224 228 }
225 229
226 230 // TODO temporary hack should find a way to avoid this copy
227 231 std::vector<VectorTimeSerie::raw_value_type> to_std_vect_vect()
228 232 {
229 233 auto sz = size(0);
230 234 std::vector<VectorTimeSerie::raw_value_type> v(sz);
231 235 if (sz)
232 236 {
233 237 assert(ndim() == 2);
234 238 assert(size(1) == 3);
235 239 auto d_ptr = reinterpret_cast<VectorTimeSerie::raw_value_type*>(data.data());
236 240 std::copy(d_ptr, d_ptr + sz, std::begin(v));
237 241 }
238 242 return v;
239 243 }
240 244
241 245 // TODO maybe ;)
242 246 PyObject* py_object() { return nullptr; }
243 247 };
244 248
245 249 inline int test_np_array(NpArray& arr)
246 250 {
247 251 auto shape = arr.shape;
248 252 std::cout << "len(shape)=" << shape.size() << std::endl;
249 253 std::for_each(std::cbegin(shape), std::cend(shape), [](auto sz) {
250 254 static int i = 0;
251 255 std::cout << "shape[" << i++ << "]=" << sz << std::endl;
252 256 });
253 257 auto flatsize = std::accumulate(std::cbegin(shape), std::cend(shape), 0);
254 258 for (auto i = 0; i < flatsize; i++)
255 259 {
256 260 std::cout << "data[" << i << "]=" << arr.data[i] << std::endl;
257 261 }
258 262 return 1;
259 263 }
260 264
261 265 #endif //#ifndef NUMPY_WRAPPERS_H
@@ -1,120 +1,118
1 1 #ifndef SCIQLOP_SQPAPPLICATION_H
2 2 #define SCIQLOP_SQPAPPLICATION_H
3 3
4 4 #include "SqpApplication.h"
5 5
6 6 #include <QAction>
7 7 #include <QApplication>
8 8 #include <QLoggingCategory>
9 9 #include <QMenuBar>
10 10 #include <QProxyStyle>
11 11 #include <QStyleOption>
12 12 #include <QWidget>
13 13 #include <QWidgetAction>
14 14
15 15 #include <Common/spimpl.h>
16 16
17 17 Q_DECLARE_LOGGING_CATEGORY(LOG_SqpApplication)
18 18
19 19 #if defined(sqpApp)
20 20 #undef sqpApp
21 21 #endif
22 22 #define sqpApp (static_cast<SqpApplication*>(QCoreApplication::instance()))
23 23
24 24 class DataSourceController;
25 25 class NetworkController;
26 26 class TimeController;
27 27 class VariableController;
28 28 class VariableController2;
29 29 class VariableModel2;
30 30 class DragDropGuiController;
31 31 class ActionsGuiController;
32 32 class CatalogueController;
33 33
34 34 /* stolen from here https://forum.qt.io/topic/90403/show-tooltip-immediatly/6 */
35 35 class MyProxyStyle : public QProxyStyle
36 36 {
37 37 public:
38 38 using QProxyStyle::QProxyStyle;
39 39
40 40 int styleHint(StyleHint hint, const QStyleOption* option = nullptr,
41 41 const QWidget* widget = nullptr, QStyleHintReturn* returnData = nullptr) const override
42 42 {
43 if (widget)
44 auto cname = widget->metaObject()->className();
45 43 if (hint == QStyle::SH_ToolButton_PopupDelay && widget
46 44 /*&& widget->inherits(QWidgetAction::staticMetaObject.className())*/)
47 45 {
48 46 return 0;
49 47 }
50 48
51 49 return QProxyStyle::styleHint(hint, option, widget, returnData);
52 50 }
53 51 };
54 52
55 53 /**
56 54 * @brief The SqpApplication class aims to make the link between SciQlop
57 55 * and its plugins. This is the intermediate class that SciQlop has to use
58 56 * in the way to connect a data source. Please first use load method to initialize
59 57 * a plugin specified by its metadata name (JSON plugin source) then others specifics
60 58 * method will be able to access it.
61 59 * You can load a data source driver plugin then create a data source.
62 60 */
63 61
64 62 class SqpApplication : public QApplication
65 63 {
66 64 Q_OBJECT
67 65 public:
68 66 explicit SqpApplication(int& argc, char** argv);
69 67 ~SqpApplication() override;
70 68 void initialize();
71 69
72 70 /// Accessors for the differents sciqlop controllers
73 71 DataSourceController& dataSourceController() noexcept;
74 72 NetworkController& networkController() noexcept;
75 73 TimeController& timeController() noexcept;
76 74 VariableController2& variableController() noexcept;
77 75 std::shared_ptr<VariableController2> variableControllerOwner() noexcept;
78 76 CatalogueController& catalogueController() noexcept;
79 77
80 78 /// Accessors for the differents sciqlop helpers, these helpers classes are like controllers but
81 79 /// doesn't live in a thread and access gui
82 80 DragDropGuiController& dragDropGuiController() noexcept;
83 81 ActionsGuiController& actionsGuiController() noexcept;
84 82
85 83 enum class PlotsInteractionMode
86 84 {
87 85 None,
88 86 ZoomBox,
89 87 DragAndDrop,
90 88 SelectionZones
91 89 };
92 90
93 91 enum class PlotsCursorMode
94 92 {
95 93 NoCursor,
96 94 Vertical,
97 95 Temporal,
98 96 Horizontal,
99 97 Cross
100 98 };
101 99
102 100 PlotsInteractionMode plotsInteractionMode() const;
103 101 void setPlotsInteractionMode(PlotsInteractionMode mode);
104 102
105 103 PlotsCursorMode plotsCursorMode() const;
106 104 void setPlotsCursorMode(PlotsCursorMode mode);
107 105
108 106 private:
109 107 class SqpApplicationPrivate;
110 108 spimpl::unique_impl_ptr<SqpApplicationPrivate> impl;
111 109 };
112 110
113 111 inline SqpApplication* SqpApplication_ctor()
114 112 {
115 113 static int argc;
116 114 static char** argv;
117 115 return new SqpApplication(argc, argv);
118 116 }
119 117
120 118 #endif // SCIQLOP_SQPAPPLICATION_H
@@ -1,85 +1,86
1 1 #include <QMainWindow>
2 2 #include <QObject>
3 3 #include <QScreen>
4 4 #include <QString>
5 5 #include <QWheelEvent>
6 6 #include <QtTest>
7 7 #include <cstdlib>
8 8
9 9
10 10 #include <Common/cpp_utils.h>
11 11 #include <SqpApplication.h>
12 12
13 13 #include <GUITestUtils.h>
14 14
15 15 #include <Catalogue/CatalogueController.h>
16 16 #include <Catalogue2/browser.h>
17 17
18 18 template <int EventsCount = 1000>
19 19 auto build_CatalogueBrowser_test()
20 20 {
21 21 sqpApp->catalogueController().add("test");
22 22 sqpApp->catalogueController().add("stuff");
23 23 sqpApp->catalogueController().add("default");
24 24 sqpApp->catalogueController().add("new catalogue", "default");
25 25 auto catalogue = sqpApp->catalogueController().add("new catalogue2", "default");
26 26 for (auto _ : std::array<char, EventsCount>())
27 27 {
28 (void)_;
28 29 static int i = 0;
29 30 auto event = CatalogueController::make_event_ptr();
30 31 event->name = std::string("Event ") + std::to_string(i++);
31 32 event->tags = { "tag1", "tag2" };
32 33 event->products = { CatalogueController::Event_t::Product_t {
33 34 std::string("Product2") + std::to_string(rand() % 30),
34 35 static_cast<double>(1532357932 + rand() % 100),
35 36 static_cast<double>(1532358932 + rand() % 100) },
36 37 CatalogueController::Event_t::Product_t {
37 38 std::string("Product2") + std::to_string(rand() % 30),
38 39 static_cast<double>(1532357932 + rand() % 200),
39 40 static_cast<double>(1532358932 + rand() % 200) },
40 41 CatalogueController::Event_t::Product_t {
41 42 std::string("Product2") + std::to_string(rand() % 30),
42 43 static_cast<double>(1532357932 + rand() % 70),
43 44 static_cast<double>(1532358932 + rand() % 70) } };
44 45 catalogue->add(event);
45 46 }
46 47 return std::make_unique<CataloguesBrowser>();
47 48 }
48 49
49 50 class A_CatalogueBrowser : public QObject
50 51 {
51 52 Q_OBJECT
52 53 public:
53 54 explicit A_CatalogueBrowser(QObject* parent = Q_NULLPTR) : QObject(parent) {}
54 55
55 56 private slots:
56 57 void can_sort_events()
57 58 {
58 59 auto w = build_CatalogueBrowser_test();
59 60 QVERIFY(prepare_gui_test(w.get()));
60 61 // GET_CHILD_WIDGET_FOR_GUI_TESTS((*w.get()),,,)
61 62 for (int i = 0; i < 1000000; i++)
62 63 {
63 64 QThread::usleep(100);
64 65 QCoreApplication::processEvents();
65 66 }
66 67 }
67 68 };
68 69
69 70 QT_BEGIN_NAMESPACE
70 71 QTEST_ADD_GPU_BLACKLIST_SUPPORT_DEFS
71 72 QT_END_NAMESPACE
72 73 int main(int argc, char* argv[])
73 74 {
74 75 Q_INIT_RESOURCE(sqpguiresources);
75 76
76 77 SqpApplication app { argc, argv };
77 78 app.setAttribute(Qt::AA_Use96Dpi, true);
78 79 QTEST_DISABLE_KEYPAD_NAVIGATION;
79 80 QTEST_ADD_GPU_BLACKLIST_SUPPORT;
80 81 A_CatalogueBrowser tc;
81 82 QTEST_SET_MAIN_SOURCE_PATH;
82 83 return QTest::qExec(&tc, argc, argv);
83 84 }
84 85
85 86 #include "main.moc"
@@ -1,52 +1,54
1 1 project('SciQLOP', 'cpp',default_options : ['cpp_std=c++17'], meson_version:'>=0.51.0')
2 2 add_global_arguments('-DSCIQLOP_VERSION="1.1.0"', language : 'cpp')
3 3
4 4 qt5 = import('qt5')
5 5 qt5core = dependency('qt5', modules : 'Core')
6 6 qt5widgets = dependency('qt5', modules : 'Widgets')
7 7 qt5gui = dependency('qt5', modules : 'Gui')
8 8 qt5svg = dependency('qt5', modules : 'Svg')
9 9 qt5xml = dependency('qt5', modules : 'Xml')
10 10 qt5network = dependency('qt5', modules : 'Network')
11 11 qt5printsupport = dependency('qt5', modules : 'PrintSupport')
12 12 qt5Concurrent = dependency('qt5', modules : 'Concurrent')
13 13 qt5test = dependency('qt5', modules : 'Test')
14 14
15 cpp_utils_dep = dependency('cpp_utils', fallback:['cpp_utils','cpp_utils_dep'])
16
15 17 moc = find_program('moc-qt5','moc')
16 18 rcc = find_program('rcc-qt5','rcc')
17 19
18 20 if build_machine.system()=='darwin'
19 21 add_global_link_arguments('-headerpad_max_install_names', language : 'cpp')
20 22 install_data('build_cfg/mac/sciqlopLOGO.icns', install_dir : 'Contents/Resources')
21 23 install_data('build_cfg/mac/Info.plist', install_dir : 'Contents')
22 24 meson.add_install_script('build_cfg/mac/install_script.sh')
23 25 elif host_machine.system()=='windows'
24 26 meson.add_install_script('build_cfg/windows/install_script.sh')
25 27 elif host_machine.system()=='linux'
26 28 install_data('app/resources/sciqlopLOGO.svg', install_dir : 'share/icons/hicolor/scalable/')
27 29 install_data('app/resources/SciQLOP.desktop', install_dir : 'share/applications')
28 30 install_data('app/resources/SciQLOP.appdata.xml', install_dir : 'share/metainfo')
29 31 endif
30 32
31 33 # Sets AMDA server that will be used during execution.
32 34 # Available values are:
33 35 # - "default": default AMDA server
34 36 # - "amdatest": AMDA test server
35 37 # - "hybrid": use both the default server and the test server (the server used is relative to each product, according to its "server" property in the JSON file)
36 38 # - "localhost": use local AMDA server
37 39 # Any other value will lead to the use of the default server
38 40 add_project_arguments('-DSCIQLOP_AMDA_SERVER="hybrid"', language : 'cpp')
39 41
40 42 subdir('core')
41 43 subdir('gui')
42 44 subdir('plugins')
43 45 subdir('app')
44 46
45 47 cppcheck = find_program('cppcheck', required : false)
46 48
47 49 if cppcheck.found()
48 50 run_target('cppcheck',
49 51 command : [cppcheck, '--enable=all',
50 52 '--project=' + join_paths(meson.build_root(), 'compile_commands.json')]
51 53 )
52 54 endif
General Comments 0
You need to be logged in to leave comments. Login now