Skip to content

Commit 46667ce

Browse files
authored
Merge pull request #24 from psavery/bnl-updates
Q2 Features
2 parents cf083b8 + 6d7f406 commit 46667ce

208 files changed

Lines changed: 8721 additions & 2618 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

tests/cxx/CMakeLists.txt

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ include_directories(SYSTEM
99
${PARAVIEW_INCLUDE_DIRS}
1010
${GTEST_INCLUDE_DIRS})
1111
include_directories(${PROJECT_SOURCE_DIR}/tomviz)
12+
include_directories(${PROJECT_SOURCE_DIR}/tomviz/modules)
13+
include_directories(${PROJECT_SOURCE_DIR}/tomviz/operators)
14+
include_directories(${PROJECT_SOURCE_DIR}/tomviz/animations)
15+
include_directories(${PROJECT_SOURCE_DIR}/tomviz/loguru)
1216
include_directories(${PROJECT_SOURCE_DIR}/tomviz/acquisition)
1317

1418
include(CheckIncludeFileCXX)
@@ -49,11 +53,16 @@ set(_pythonpath "${_pythonpath}${_separator}$ENV{PYTHONPATH}")
4953
# Add the test cases
5054
add_cxx_test(OperatorPython PYTHONPATH ${_pythonpath})
5155
add_cxx_test(Variant)
52-
56+
add_cxx_test(ScanID)
57+
add_cxx_test(Utilities)
58+
add_cxx_qtest(ModulePlot)
59+
add_cxx_qtest(Tvh5Data)
60+
add_cxx_qtest(InterfaceBuilder)
61+
add_cxx_qtest(PipelineExecution PYTHONPATH ${_pythonpath})
5362
add_cxx_qtest(DockerUtilities)
5463
add_cxx_qtest(AcquisitionClient PYTHONPATH "${CMAKE_SOURCE_DIR}/acquisition")
55-
add_cxx_qtest(PtychoWorkflow)
56-
add_cxx_qtest(PyXRFWorkflow)
64+
add_cxx_qtest(PtychoWorkflow PYTHONPATH ${_pythonpath})
65+
add_cxx_qtest(PyXRFWorkflow PYTHONPATH ${_pythonpath})
5766

5867
# Generate the executable
5968
create_test_executable(tomvizTests)

tests/cxx/CxxTests.cmake

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,13 @@ macro(add_cxx_qtest name)
1515
set(_one_value_args PYTHONPATH)
1616
cmake_parse_arguments(fn "" "" "${_one_value_args}" "" ${ARGN})
1717

18+
# Use a name-scoped variable to avoid clobbering the caller's _pythonpath.
19+
# CMake macros do not have their own scope, so a bare _pythonpath would
20+
# overwrite the identically-named variable in the calling CMakeLists.txt.
21+
set(_qtest_${name}_pythonpath "")
1822
if(fn_PYTHONPATH)
19-
set(_pythonpath "${fn_PYTHONPATH}")
20-
message("PYTHONPATH for ${name}: ${_pythonpath})")
23+
set(_qtest_${name}_pythonpath "${fn_PYTHONPATH}")
24+
message("PYTHONPATH for ${name}: ${_qtest_${name}_pythonpath})")
2125
endif()
2226

2327
set(_test_src ${name}Test.cxx)
@@ -31,13 +35,13 @@ macro(add_cxx_qtest name)
3135
set_target_properties(${_executable_name} PROPERTIES ENABLE_EXPORTS TRUE)
3236

3337
add_test(NAME "${name}" COMMAND ${_executable_name})
34-
if(_pythonpath)
38+
if(_qtest_${name}_pythonpath)
3539
if (WIN32)
36-
string(REPLACE "\\;" ";" "_pythonpath" "${_pythonpath}")
37-
string(REPLACE ";" "\\;" "_pythonpath" "${_pythonpath}")
40+
string(REPLACE "\\;" ";" "_qtest_${name}_pythonpath" "${_qtest_${name}_pythonpath}")
41+
string(REPLACE ";" "\\;" "_qtest_${name}_pythonpath" "${_qtest_${name}_pythonpath}")
3842
endif()
3943
set_tests_properties(${name}
40-
PROPERTIES ENVIRONMENT "PYTHONPATH=${_pythonpath}")
44+
PROPERTIES ENVIRONMENT "PYTHONPATH=${_qtest_${name}_pythonpath};TOMVIZ_APPLICATION=1")
4145
endif()
4246
endmacro()
4347

tests/cxx/InterfaceBuilderTest.cxx

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
/* This source file is part of the Tomviz project, https://tomviz.org/.
2+
It is released under the 3-Clause BSD License, see "LICENSE". */
3+
4+
#include <QCheckBox>
5+
#include <QComboBox>
6+
#include <QJsonArray>
7+
#include <QJsonDocument>
8+
#include <QJsonObject>
9+
#include <QLayout>
10+
#include <QMap>
11+
#include <QStandardItemModel>
12+
#include <QTest>
13+
#include <QVariant>
14+
#include <QWidget>
15+
16+
#include "InterfaceBuilder.h"
17+
18+
using namespace tomviz;
19+
20+
class InterfaceBuilderTest : public QObject
21+
{
22+
Q_OBJECT
23+
24+
private:
25+
InterfaceBuilder* builder;
26+
QWidget* parentWidget;
27+
28+
private slots:
29+
void init()
30+
{
31+
builder = new InterfaceBuilder(this);
32+
parentWidget = new QWidget();
33+
}
34+
35+
void cleanup()
36+
{
37+
delete parentWidget;
38+
parentWidget = nullptr;
39+
}
40+
41+
void selectScalarsWidgetCreated()
42+
{
43+
QString desc = R"({
44+
"name": "TestOp",
45+
"label": "Test Operator",
46+
"parameters": [
47+
{"name": "selected_scalars", "type": "select_scalars",
48+
"label": "Scalars"}
49+
]
50+
})";
51+
52+
builder->setJSONDescription(desc);
53+
QLayout* layout = builder->buildInterface();
54+
QVERIFY(layout != nullptr);
55+
56+
parentWidget->setLayout(layout);
57+
58+
auto* widget = parentWidget->findChild<QWidget*>("selected_scalars");
59+
QVERIFY(widget != nullptr);
60+
QCOMPARE(widget->property("type").toString(), QString("select_scalars"));
61+
}
62+
63+
void selectScalarsParameterValues()
64+
{
65+
QString desc = R"({
66+
"name": "TestOp",
67+
"label": "Test Operator",
68+
"parameters": [
69+
{"name": "selected_scalars", "type": "select_scalars",
70+
"label": "Scalars"}
71+
]
72+
})";
73+
74+
builder->setJSONDescription(desc);
75+
QLayout* layout = builder->buildInterface();
76+
QVERIFY(layout != nullptr);
77+
parentWidget->setLayout(layout);
78+
79+
// The combo box is empty because we have no DataSource.
80+
// Manually populate the model and check items to test parameterValues().
81+
auto* container =
82+
parentWidget->findChild<QWidget*>("selected_scalars");
83+
QVERIFY(container != nullptr);
84+
85+
auto* applyAllCB =
86+
container->findChild<QCheckBox*>("selected_scalars_apply_all");
87+
QVERIFY(applyAllCB != nullptr);
88+
89+
auto* combo =
90+
container->findChild<QComboBox*>("selected_scalars_combo");
91+
QVERIFY(combo != nullptr);
92+
93+
auto* model = qobject_cast<QStandardItemModel*>(combo->model());
94+
QVERIFY(model != nullptr);
95+
96+
// Add items and check them
97+
auto* itemA = new QStandardItem("scalar_a");
98+
itemA->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
99+
itemA->setData(Qt::Checked, Qt::CheckStateRole);
100+
model->appendRow(itemA);
101+
102+
auto* itemB = new QStandardItem("scalar_b");
103+
itemB->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
104+
itemB->setData(Qt::Checked, Qt::CheckStateRole);
105+
model->appendRow(itemB);
106+
107+
// Uncheck "Apply to all" so individual selections are used
108+
applyAllCB->setChecked(false);
109+
110+
auto result = InterfaceBuilder::parameterValues(parentWidget);
111+
QVERIFY(result.contains("selected_scalars"));
112+
113+
auto resultScalars = result["selected_scalars"].toList();
114+
QCOMPARE(resultScalars.size(), 2);
115+
QCOMPARE(resultScalars[0].toString(), QString("scalar_a"));
116+
QCOMPARE(resultScalars[1].toString(), QString("scalar_b"));
117+
}
118+
119+
void basicParameterTypes()
120+
{
121+
QString desc = R"({
122+
"name": "TestOp",
123+
"label": "Test Operator",
124+
"parameters": [
125+
{"name": "int_param", "type": "int", "label": "Int", "default": 5},
126+
{"name": "double_param", "type": "double", "label": "Double",
127+
"default": 1.5},
128+
{"name": "bool_param", "type": "bool", "label": "Bool", "default": true}
129+
]
130+
})";
131+
132+
builder->setJSONDescription(desc);
133+
QLayout* layout = builder->buildInterface();
134+
QVERIFY(layout != nullptr);
135+
136+
parentWidget->setLayout(layout);
137+
138+
auto result = InterfaceBuilder::parameterValues(parentWidget);
139+
QVERIFY(result.contains("int_param"));
140+
QVERIFY(result.contains("double_param"));
141+
QVERIFY(result.contains("bool_param"));
142+
143+
QCOMPARE(result["int_param"].toInt(), 5);
144+
QCOMPARE(result["double_param"].toDouble(), 1.5);
145+
QCOMPARE(result["bool_param"].toBool(), true);
146+
}
147+
148+
void enableIfVisibleIf()
149+
{
150+
QString desc = R"({
151+
"name": "TestOp",
152+
"label": "Test Operator",
153+
"parameters": [
154+
{"name": "toggle", "type": "bool", "label": "Toggle", "default": false},
155+
{"name": "enabled_dep", "type": "int", "label": "Enabled Dep",
156+
"default": 0, "enable_if": "toggle == true"},
157+
{"name": "visible_dep", "type": "int", "label": "Visible Dep",
158+
"default": 0, "visible_if": "toggle == true"}
159+
]
160+
})";
161+
162+
builder->setJSONDescription(desc);
163+
QLayout* layout = builder->buildInterface();
164+
QVERIFY(layout != nullptr);
165+
166+
parentWidget->setLayout(layout);
167+
// Must show the parent so isVisible() works on children --
168+
// Qt's isVisible() requires all ancestors to be visible.
169+
parentWidget->show();
170+
171+
auto* toggleCheckBox =
172+
parentWidget->findChild<QCheckBox*>("toggle");
173+
QVERIFY(toggleCheckBox != nullptr);
174+
175+
auto* enabledWidget = parentWidget->findChild<QWidget*>("enabled_dep");
176+
QVERIFY(enabledWidget != nullptr);
177+
178+
auto* visibleWidget = parentWidget->findChild<QWidget*>("visible_dep");
179+
QVERIFY(visibleWidget != nullptr);
180+
181+
// Toggle is false by default -- enabled_dep should be disabled,
182+
// visible_dep should be hidden
183+
QVERIFY(!enabledWidget->isEnabled());
184+
QVERIFY(!visibleWidget->isVisible());
185+
186+
// Toggle on -- both should become active
187+
toggleCheckBox->setChecked(true);
188+
QVERIFY(enabledWidget->isEnabled());
189+
QVERIFY(visibleWidget->isVisible());
190+
191+
// Toggle back off -- both should revert
192+
toggleCheckBox->setChecked(false);
193+
QVERIFY(!enabledWidget->isEnabled());
194+
QVERIFY(!visibleWidget->isVisible());
195+
}
196+
};
197+
198+
QTEST_MAIN(InterfaceBuilderTest)
199+
#include "InterfaceBuilderTest.moc"

0 commit comments

Comments
 (0)