Skip to content

Commit 13eb1bc

Browse files
authored
Road to removing qtassistant (documentation) --> C Changes required for Python HelpWindow implementation (ornl-next) (#39016)
* C-Based-Changes-for-Python-Help-Window * Revert this change to docs/CMakeLists.txt * Update PythonHelpBridge.h * Update PythonHelpBridge.cpp * Update PythonHelpWindow.h * Update PythonHelpWindow.cpp * Updates to support changes in python structure * Last updates to enable functionality * Requested updates and test * Fix to imports in start.py * Fix small Cmake change * Update to fix segmentation issue on close * Remove comment
1 parent f4abfa0 commit 13eb1bc

File tree

10 files changed

+312
-3
lines changed

10 files changed

+312
-3
lines changed

buildconfig/CMake/CommonSetup.cmake

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ endif()
1919
option(ENABLE_OPENGL "Enable OpenGLbased rendering" ON)
2020
option(ENABLE_OPENCASCADE "Enable OpenCascade-based 3D visualisation" ON)
2121
option(USE_PYTHON_DYNAMIC_LIB "Dynamic link python libs" ON)
22+
option(ENABLE_QTASSISTANT "If enabled, add a target to build the qthelp documentation for qtassistant" ON)
2223

2324
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
2425
make_directory(${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Testing)

qt/applications/workbench/workbench/app/start.py

+4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
# Find Qt plugins for development builds on some platforms
2222
plugins.setup_library_paths()
2323

24+
# This import is needed for new PythonHelpWindow implementation,
25+
# these imports are needed before starting the application
26+
from qtpy.QtWebEngineWidgets import QWebEngineView, QWebEngineSettings # noqa: F401, E402
27+
2428
from qtpy.QtGui import QIcon, QSurfaceFormat # noqa: E402
2529
from qtpy.QtWidgets import QApplication # noqa: E402
2630
from qtpy.QtCore import QCoreApplication, Qt # noqa: E402

qt/python/mantidqt/mantidqt/widgets/helpwindow/helpwindowbridge.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def show_help_page(relative_url, local_docs=None, online_base_url="https://docs.
2626
_presenter.showHelpPage(relative_url)
2727

2828

29-
def main(cmdargs=None):
29+
def main(cmdargs=sys.argv):
3030
"""
3131
Run this script standalone to test the Python-based Help Window.
3232
"""

qt/widgets/common/CMakeLists.txt

+15-1
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,11 @@ set(SRC_FILES
159159
src/Python/QHashToDict.cpp
160160
)
161161

162+
if(NOT ENABLE_QTASSISTANT)
163+
list(APPEND SRC_FILES src/PythonHelpBridge.cpp)
164+
list(APPEND SRC_FILES src/PythonHelpWindow.cpp)
165+
endif()
166+
162167
set(QT5_MOC_FILES
163168
inc/MantidQtWidgets/Common/AddWorkspaceDialog.h
164169
inc/MantidQtWidgets/Common/AddWorkspaceMultiDialog.h
@@ -262,6 +267,11 @@ set(QT5_MOC_FILES
262267
inc/MantidQtWidgets/Common/QtPropertyBrowser/WorkspaceEditorFactory.h
263268
)
264269

270+
if(NOT ENABLE_QTASSISTANT)
271+
list(APPEND QT5_MOC_FILES inc/MantidQtWidgets/Common/PythonHelpBridge.h)
272+
list(APPEND QT5_MOC_FILES inc/MantidQtWidgets/Common/PythonHelpWindow.h)
273+
endif()
274+
265275
# Include files aren't required, but this makes them appear in Visual Studio
266276
set(QT5_INC_FILES
267277
${QT5_MOC_FILES}
@@ -637,7 +647,7 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
637647
endif()
638648

639649
# Add option to the compiler to register MantidHelpWindow
640-
if(DOCS_QTHELP)
650+
if(ENABLE_QTASSISTANT)
641651
add_definitions(-DDOCS_QTHELP)
642652
endif()
643653

@@ -740,6 +750,10 @@ set(TEST_FILES
740750
test/WorkspacePresenter/WorkspacePresenterTest.h
741751
)
742752

753+
if(NOT ENABLE_QTASSISTANT)
754+
list(APPEND TEST_FILES test/PythonHelpWindowTest.h)
755+
endif()
756+
743757
set(CXXTEST_EXTRA_HEADER_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/test/WidgetsCommonTestInitialization.h)
744758

745759
set(QT5_TEST_FILES

qt/widgets/common/inc/MantidQtWidgets/Common/InterfaceManager.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,6 @@ class EXPORT_OPT_MANTIDQT_COMMON InterfaceManager {
138138
namespace { \
139139
Mantid::Kernel::RegistrationHelper \
140140
register_helpviewer(((MantidQt::API::InterfaceManager::registerHelpWindowFactory( \
141-
new Mantid::Kernel::Instantiator<TYPE, MantidHelpInterface>())), \
141+
new Mantid::Kernel::Instantiator<TYPE, MantidQt::API::MantidHelpInterface>())), \
142142
0)); \
143143
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Mantid Repository : https://github.com/mantidproject/mantid
2+
//
3+
// Copyright &copy; 2013 ISIS Rutherford Appleton Laboratory UKRI,
4+
// NScD Oak Ridge National Laboratory, European Spallation Source,
5+
// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6+
// SPDX - License - Identifier: GPL - 3.0 +
7+
#pragma once
8+
9+
#include "MantidQtWidgets/Common/DllOption.h"
10+
#include <string>
11+
12+
namespace MantidQt {
13+
namespace MantidWidgets {
14+
15+
class EXPORT_OPT_MANTIDQT_COMMON PythonHelpBridge {
16+
public:
17+
PythonHelpBridge();
18+
void showHelpPage(const std::string &relative_url);
19+
};
20+
21+
} // namespace MantidWidgets
22+
} // namespace MantidQt
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Mantid Repository : https://github.com/mantidproject/mantid
2+
//
3+
// Copyright &copy; 2013 ISIS Rutherford Appleton Laboratory UKRI,
4+
// NScD Oak Ridge National Laboratory, European Spallation Source,
5+
// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6+
// SPDX - License - Identifier: GPL - 3.0 +
7+
#pragma once
8+
9+
#include "MantidQtWidgets/Common/DllOption.h"
10+
#include "MantidQtWidgets/Common/MantidHelpInterface.h"
11+
#include <QString>
12+
#include <QUrl>
13+
#include <string>
14+
15+
namespace MantidQt {
16+
namespace MantidWidgets {
17+
18+
class EXPORT_OPT_MANTIDQT_COMMON PythonHelpWindow : public MantidQt::API::MantidHelpInterface {
19+
public:
20+
PythonHelpWindow();
21+
void showPage(const std::string &url = std::string()) override;
22+
void showPage(const QString &url) override;
23+
void showPage(const QUrl &url) override;
24+
void showAlgorithm(const std::string &name = std::string(), const int version = -1) override;
25+
void showAlgorithm(const QString &name, const int version = -1) override;
26+
void showConcept(const std::string &name) override;
27+
void showConcept(const QString &name) override;
28+
void showFitFunction(const std::string &name = std::string()) override;
29+
void showFitFunction(const QString &name) override;
30+
void showCustomInterface(const std::string &name = std::string(), const std::string &area = std::string(),
31+
const std::string &section = std::string()) override;
32+
void showCustomInterface(const QString &name, const QString &area = QString(),
33+
const QString &section = QString()) override;
34+
void shutdown() override;
35+
};
36+
37+
} // namespace MantidWidgets
38+
} // namespace MantidQt
+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Mantid Repository : https://github.com/mantidproject/mantid
2+
//
3+
// Copyright &copy; 2018 ISIS Rutherford Appleton Laboratory UKRI,
4+
// NScD Oak Ridge National Laboratory, European Spallation Source,
5+
// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6+
// SPDX - License - Identifier: GPL - 3.0 +
7+
#include "MantidQtWidgets/Common/PythonHelpBridge.h"
8+
#include <Python.h>
9+
#include <boost/python.hpp>
10+
#include <boost/python/str.hpp>
11+
#include <stdexcept>
12+
13+
namespace {
14+
const std::string MOD_NAME("mantidqt.widgets.helpwindow.helpwindowbridge");
15+
boost::python::object getHelpWindowModule() {
16+
boost::python::object mod = boost::python::import(boost::python::str(MOD_NAME));
17+
return mod;
18+
}
19+
} // namespace
20+
21+
namespace MantidQt {
22+
namespace MantidWidgets {
23+
24+
PythonHelpBridge::PythonHelpBridge() {}
25+
26+
void PythonHelpBridge::showHelpPage(const std::string &relative_url) {
27+
PyGILState_STATE gstate = PyGILState_Ensure();
28+
try {
29+
auto module = getHelpWindowModule();
30+
module.attr("show_help_page")(relative_url);
31+
} catch (boost::python::error_already_set &) {
32+
PyErr_Print();
33+
PyGILState_Release(gstate);
34+
throw std::runtime_error("Error calling show_help_page in Python.");
35+
}
36+
PyGILState_Release(gstate);
37+
}
38+
} // namespace MantidWidgets
39+
} // namespace MantidQt
+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Mantid Repository : https://github.com/mantidproject/mantid
2+
//
3+
// Copyright &copy; 2013 ISIS Rutherford Appleton Laboratory UKRI,
4+
// NScD Oak Ridge National Laboratory, European Spallation Source,
5+
// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6+
// SPDX - License - Identifier: GPL - 3.0 +
7+
#include "MantidQtWidgets/Common/PythonHelpWindow.h"
8+
#include "MantidKernel/RegistrationHelper.h"
9+
#include "MantidQtWidgets/Common/InterfaceManager.h"
10+
#include "MantidQtWidgets/Common/PythonHelpBridge.h"
11+
#include <QString>
12+
#include <string>
13+
14+
namespace MantidQt {
15+
namespace MantidWidgets {
16+
17+
#ifndef DOCS_QTHELP
18+
REGISTER_HELPWINDOW(PythonHelpWindow)
19+
#endif
20+
21+
PythonHelpWindow::PythonHelpWindow() : MantidQt::API::MantidHelpInterface() {}
22+
23+
void PythonHelpWindow::showPage(const std::string &url) {
24+
PythonHelpBridge bridge;
25+
bridge.showHelpPage(url.empty() ? "index.html" : url);
26+
}
27+
28+
void PythonHelpWindow::showPage(const QString &url) {
29+
PythonHelpBridge bridge;
30+
std::string page = url.isEmpty() ? "index.html" : url.toStdString();
31+
bridge.showHelpPage(page);
32+
}
33+
34+
void PythonHelpWindow::showPage(const QUrl &url) {
35+
PythonHelpBridge bridge;
36+
std::string page = url.isEmpty() ? "index.html" : url.toString().toStdString();
37+
bridge.showHelpPage(page);
38+
}
39+
40+
void PythonHelpWindow::showAlgorithm(const std::string &name, const int version) {
41+
QString page = "algorithms/" + QString::fromStdString(name);
42+
if (!name.empty() && version > 0)
43+
page += "-v" + QString::number(version) + ".html";
44+
else if (!name.empty())
45+
page += ".html";
46+
else
47+
page = "algorithms/index.html";
48+
showPage(page);
49+
}
50+
51+
void PythonHelpWindow::showAlgorithm(const QString &name, const int version) {
52+
std::string n = name.toStdString();
53+
showAlgorithm(n, version);
54+
}
55+
56+
void PythonHelpWindow::showConcept(const std::string &name) {
57+
QString page = name.empty() ? "concepts/index.html" : "concepts/" + QString::fromStdString(name) + ".html";
58+
showPage(page);
59+
}
60+
61+
void PythonHelpWindow::showConcept(const QString &name) {
62+
std::string n = name.toStdString();
63+
showConcept(n);
64+
}
65+
66+
void PythonHelpWindow::showFitFunction(const std::string &name) {
67+
QString page = name.empty() ? "fitting/fitfunctions/index.html"
68+
: "fitting/fitfunctions/" + QString::fromStdString(name) + ".html";
69+
showPage(page);
70+
}
71+
72+
void PythonHelpWindow::showFitFunction(const QString &name) {
73+
std::string n = name.toStdString();
74+
showFitFunction(n);
75+
}
76+
77+
void PythonHelpWindow::showCustomInterface(const std::string &name, const std::string &area,
78+
const std::string &section) {
79+
QString areaPath = area.empty() ? "" : QString::fromStdString(area) + "/";
80+
QString page = "interfaces/" + areaPath + (name.empty() ? "index.html" : QString::fromStdString(name) + ".html");
81+
if (!section.empty())
82+
page += "#" + QString::fromStdString(section);
83+
showPage(page);
84+
}
85+
86+
void PythonHelpWindow::showCustomInterface(const QString &name, const QString &area, const QString &section) {
87+
std::string n = name.toStdString();
88+
std::string a = area.toStdString();
89+
std::string s = section.toStdString();
90+
showCustomInterface(n, a, s);
91+
}
92+
93+
void PythonHelpWindow::shutdown() {}
94+
95+
} // namespace MantidWidgets
96+
} // namespace MantidQt
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// Mantid Repository : https://github.com/mantidproject/mantid
2+
//
3+
// Copyright &copy; 2018 ISIS Rutherford Appleton Laboratory UKRI,
4+
// NScD Oak Ridge National Laboratory, European Spallation Source,
5+
// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6+
// SPDX - License - Identifier: GPL - 3.0 +
7+
#pragma once
8+
9+
#include <cxxtest/TestSuite.h>
10+
#include <gmock/gmock.h>
11+
12+
#include <QString>
13+
#include <QUrl>
14+
15+
#include "MantidQtWidgets/Common/PythonHelpBridge.h"
16+
#include "MantidQtWidgets/Common/PythonHelpWindow.h"
17+
18+
#include "MantidKernel/WarningSuppressions.h"
19+
GNU_DIAG_OFF_SUGGEST_OVERRIDE
20+
21+
using namespace MantidQt::API;
22+
using namespace MantidQt::MantidWidgets;
23+
using namespace testing;
24+
25+
GNU_DIAG_ON_SUGGEST_OVERRIDE
26+
27+
class PythonHelpWindowTest : public CxxTest::TestSuite {
28+
public:
29+
void setUp() override {}
30+
31+
void tearDown() override {}
32+
33+
// 1) Test the constructor doesn't throw and creates a valid object
34+
void testConstructorDoesNotThrow() { TS_ASSERT_THROWS_NOTHING(PythonHelpWindow helpWin); }
35+
36+
// 2) Test showPage(std::string) with an empty string
37+
void testShowPageWithEmptyString() {
38+
PythonHelpWindow helpWin;
39+
TS_ASSERT_THROWS_NOTHING(helpWin.showPage(std::string{}));
40+
}
41+
42+
// 3) Test showPage(std::string) with a non-empty string
43+
void testShowPageWithNonEmptyString() {
44+
PythonHelpWindow helpWin;
45+
TS_ASSERT_THROWS_NOTHING(helpWin.showPage("custom_page.html"));
46+
}
47+
48+
// 4) Test showPage(QString) with an empty string
49+
void testShowPage_QString_Empty() {
50+
PythonHelpWindow helpWin;
51+
TS_ASSERT_THROWS_NOTHING(helpWin.showPage(QString()));
52+
}
53+
54+
// 5) Test showPage(QUrl) with an empty URL
55+
void testShowPage_QUrl_Empty() {
56+
PythonHelpWindow helpWin;
57+
TS_ASSERT_THROWS_NOTHING(helpWin.showPage(QUrl()));
58+
}
59+
60+
// 6) Test showAlgorithm(std::string) with empty name and version
61+
void testShowAlgorithm_NoName() {
62+
PythonHelpWindow helpWin;
63+
TS_ASSERT_THROWS_NOTHING(helpWin.showAlgorithm("", -1));
64+
}
65+
66+
// 7) Test showAlgorithm(std::string) with valid name and version
67+
void testShowAlgorithm_NameAndVersion() {
68+
PythonHelpWindow helpWin;
69+
TS_ASSERT_THROWS_NOTHING(helpWin.showAlgorithm("Load", 2));
70+
}
71+
72+
// 8) Test showConcept(std::string) with empty name
73+
void testShowConceptEmpty() {
74+
PythonHelpWindow helpWin;
75+
TS_ASSERT_THROWS_NOTHING(helpWin.showConcept(""));
76+
}
77+
78+
// 9) Test showFitFunction(std::string) with a name
79+
void testShowFitFunctionName() {
80+
PythonHelpWindow helpWin;
81+
TS_ASSERT_THROWS_NOTHING(helpWin.showFitFunction("GaussPeak"));
82+
}
83+
84+
// 10) Test showCustomInterface(std::string) with name, area, section
85+
void testShowCustomInterface() {
86+
PythonHelpWindow helpWin;
87+
TS_ASSERT_THROWS_NOTHING(helpWin.showCustomInterface("Reflectometry", "ISISReflectometry", "Usage"));
88+
}
89+
90+
// 11) Test the shutdown method (currently a no-op)
91+
void testShutdownDoesNotThrow() {
92+
PythonHelpWindow helpWin;
93+
TS_ASSERT_THROWS_NOTHING(helpWin.shutdown());
94+
}
95+
};

0 commit comments

Comments
 (0)