Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Road to removing qtassistant (documentation) --> C Changes required for Python HelpWindow implementation (ornl-next) #39016

Merged
Merged
1 change: 1 addition & 0 deletions buildconfig/CMake/CommonSetup.cmake
Original file line number Diff line number Diff line change
@@ -19,6 +19,7 @@ endif()
option(ENABLE_OPENGL "Enable OpenGLbased rendering" ON)
option(ENABLE_OPENCASCADE "Enable OpenCascade-based 3D visualisation" ON)
option(USE_PYTHON_DYNAMIC_LIB "Dynamic link python libs" ON)
option(ENABLE_QTASSISTANT "If enabled, add a target to build the qthelp documentation for qtassistant" ON)

add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
make_directory(${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Testing)
4 changes: 4 additions & 0 deletions qt/applications/workbench/workbench/app/start.py
Original file line number Diff line number Diff line change
@@ -21,6 +21,10 @@
# Find Qt plugins for development builds on some platforms
plugins.setup_library_paths()

# This import is needed for new PythonHelpWindow implementation,
# these imports are needed before starting the application
from qtpy.QtWebEngineWidgets import QWebEngineView, QWebEngineSettings # noqa: F401, E402

from qtpy.QtGui import QIcon, QSurfaceFormat # noqa: E402
from qtpy.QtWidgets import QApplication # noqa: E402
from qtpy.QtCore import QCoreApplication, Qt # noqa: E402
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@ def show_help_page(relative_url, local_docs=None, online_base_url="https://docs.
_presenter.showHelpPage(relative_url)


def main(cmdargs=None):
def main(cmdargs=sys.argv):
"""
Run this script standalone to test the Python-based Help Window.
"""
16 changes: 15 additions & 1 deletion qt/widgets/common/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -159,6 +159,11 @@ set(SRC_FILES
src/Python/QHashToDict.cpp
)

if(NOT ENABLE_QTASSISTANT)
list(APPEND SRC_FILES src/PythonHelpBridge.cpp)
list(APPEND SRC_FILES src/PythonHelpWindow.cpp)
endif()

set(QT5_MOC_FILES
inc/MantidQtWidgets/Common/AddWorkspaceDialog.h
inc/MantidQtWidgets/Common/AddWorkspaceMultiDialog.h
@@ -262,6 +267,11 @@ set(QT5_MOC_FILES
inc/MantidQtWidgets/Common/QtPropertyBrowser/WorkspaceEditorFactory.h
)

if(NOT ENABLE_QTASSISTANT)
list(APPEND QT5_MOC_FILES inc/MantidQtWidgets/Common/PythonHelpBridge.h)
list(APPEND QT5_MOC_FILES inc/MantidQtWidgets/Common/PythonHelpWindow.h)
endif()

# Include files aren't required, but this makes them appear in Visual Studio
set(QT5_INC_FILES
${QT5_MOC_FILES}
@@ -637,7 +647,7 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
endif()

# Add option to the compiler to register MantidHelpWindow
if(DOCS_QTHELP)
if(ENABLE_QTASSISTANT)
add_definitions(-DDOCS_QTHELP)
endif()

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

if(NOT ENABLE_QTASSISTANT)
list(APPEND TEST_FILES test/PythonHelpWindowTest.h)
endif()

set(CXXTEST_EXTRA_HEADER_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/test/WidgetsCommonTestInitialization.h)

set(QT5_TEST_FILES
Original file line number Diff line number Diff line change
@@ -138,6 +138,6 @@ class EXPORT_OPT_MANTIDQT_COMMON InterfaceManager {
namespace { \
Mantid::Kernel::RegistrationHelper \
register_helpviewer(((MantidQt::API::InterfaceManager::registerHelpWindowFactory( \
new Mantid::Kernel::Instantiator<TYPE, MantidHelpInterface>())), \
new Mantid::Kernel::Instantiator<TYPE, MantidQt::API::MantidHelpInterface>())), \
0)); \
}
22 changes: 22 additions & 0 deletions qt/widgets/common/inc/MantidQtWidgets/Common/PythonHelpBridge.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright &copy; 2013 ISIS Rutherford Appleton Laboratory UKRI,
// NScD Oak Ridge National Laboratory, European Spallation Source,
// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
// SPDX - License - Identifier: GPL - 3.0 +
#pragma once

#include "MantidQtWidgets/Common/DllOption.h"
#include <string>

namespace MantidQt {
namespace MantidWidgets {

class EXPORT_OPT_MANTIDQT_COMMON PythonHelpBridge {
public:
PythonHelpBridge();
void showHelpPage(const std::string &relative_url);
};

} // namespace MantidWidgets
} // namespace MantidQt
38 changes: 38 additions & 0 deletions qt/widgets/common/inc/MantidQtWidgets/Common/PythonHelpWindow.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright &copy; 2013 ISIS Rutherford Appleton Laboratory UKRI,
// NScD Oak Ridge National Laboratory, European Spallation Source,
// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
// SPDX - License - Identifier: GPL - 3.0 +
#pragma once

#include "MantidQtWidgets/Common/DllOption.h"
#include "MantidQtWidgets/Common/MantidHelpInterface.h"
#include <QString>
#include <QUrl>
#include <string>

namespace MantidQt {
namespace MantidWidgets {

class EXPORT_OPT_MANTIDQT_COMMON PythonHelpWindow : public MantidQt::API::MantidHelpInterface {
public:
PythonHelpWindow();
void showPage(const std::string &url = std::string()) override;
void showPage(const QString &url) override;
void showPage(const QUrl &url) override;
void showAlgorithm(const std::string &name = std::string(), const int version = -1) override;
void showAlgorithm(const QString &name, const int version = -1) override;
void showConcept(const std::string &name) override;
void showConcept(const QString &name) override;
void showFitFunction(const std::string &name = std::string()) override;
void showFitFunction(const QString &name) override;
void showCustomInterface(const std::string &name = std::string(), const std::string &area = std::string(),
const std::string &section = std::string()) override;
void showCustomInterface(const QString &name, const QString &area = QString(),
const QString &section = QString()) override;
void shutdown() override;
};

} // namespace MantidWidgets
} // namespace MantidQt
39 changes: 39 additions & 0 deletions qt/widgets/common/src/PythonHelpBridge.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright &copy; 2018 ISIS Rutherford Appleton Laboratory UKRI,
// NScD Oak Ridge National Laboratory, European Spallation Source,
// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
// SPDX - License - Identifier: GPL - 3.0 +
#include "MantidQtWidgets/Common/PythonHelpBridge.h"
#include <Python.h>
#include <boost/python.hpp>
#include <boost/python/str.hpp>
#include <stdexcept>

namespace {
const std::string MOD_NAME("mantidqt.widgets.helpwindow.helpwindowbridge");
boost::python::object getHelpWindowModule() {
boost::python::object mod = boost::python::import(boost::python::str(MOD_NAME));
return mod;
}
} // namespace

namespace MantidQt {
namespace MantidWidgets {

PythonHelpBridge::PythonHelpBridge() {}

void PythonHelpBridge::showHelpPage(const std::string &relative_url) {
PyGILState_STATE gstate = PyGILState_Ensure();
try {
auto module = getHelpWindowModule();
module.attr("show_help_page")(relative_url);
} catch (boost::python::error_already_set &) {
PyErr_Print();
PyGILState_Release(gstate);
throw std::runtime_error("Error calling show_help_page in Python.");
}
PyGILState_Release(gstate);
}
} // namespace MantidWidgets
} // namespace MantidQt
96 changes: 96 additions & 0 deletions qt/widgets/common/src/PythonHelpWindow.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright &copy; 2013 ISIS Rutherford Appleton Laboratory UKRI,
// NScD Oak Ridge National Laboratory, European Spallation Source,
// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
// SPDX - License - Identifier: GPL - 3.0 +
#include "MantidQtWidgets/Common/PythonHelpWindow.h"
#include "MantidKernel/RegistrationHelper.h"
#include "MantidQtWidgets/Common/InterfaceManager.h"
#include "MantidQtWidgets/Common/PythonHelpBridge.h"
#include <QString>
#include <string>

namespace MantidQt {
namespace MantidWidgets {

#ifndef DOCS_QTHELP
REGISTER_HELPWINDOW(PythonHelpWindow)
#endif

PythonHelpWindow::PythonHelpWindow() : MantidQt::API::MantidHelpInterface() {}

void PythonHelpWindow::showPage(const std::string &url) {
PythonHelpBridge bridge;
bridge.showHelpPage(url.empty() ? "index.html" : url);
}

void PythonHelpWindow::showPage(const QString &url) {
PythonHelpBridge bridge;
std::string page = url.isEmpty() ? "index.html" : url.toStdString();
bridge.showHelpPage(page);
}

void PythonHelpWindow::showPage(const QUrl &url) {
PythonHelpBridge bridge;
std::string page = url.isEmpty() ? "index.html" : url.toString().toStdString();
bridge.showHelpPage(page);
}

void PythonHelpWindow::showAlgorithm(const std::string &name, const int version) {
QString page = "algorithms/" + QString::fromStdString(name);
if (!name.empty() && version > 0)
page += "-v" + QString::number(version) + ".html";
else if (!name.empty())
page += ".html";
else
page = "algorithms/index.html";
showPage(page);
}

void PythonHelpWindow::showAlgorithm(const QString &name, const int version) {
std::string n = name.toStdString();
showAlgorithm(n, version);
}

void PythonHelpWindow::showConcept(const std::string &name) {
QString page = name.empty() ? "concepts/index.html" : "concepts/" + QString::fromStdString(name) + ".html";
showPage(page);
}

void PythonHelpWindow::showConcept(const QString &name) {
std::string n = name.toStdString();
showConcept(n);
}

void PythonHelpWindow::showFitFunction(const std::string &name) {
QString page = name.empty() ? "fitting/fitfunctions/index.html"
: "fitting/fitfunctions/" + QString::fromStdString(name) + ".html";
showPage(page);
}

void PythonHelpWindow::showFitFunction(const QString &name) {
std::string n = name.toStdString();
showFitFunction(n);
}

void PythonHelpWindow::showCustomInterface(const std::string &name, const std::string &area,
const std::string &section) {
QString areaPath = area.empty() ? "" : QString::fromStdString(area) + "/";
QString page = "interfaces/" + areaPath + (name.empty() ? "index.html" : QString::fromStdString(name) + ".html");
if (!section.empty())
page += "#" + QString::fromStdString(section);
showPage(page);
}

void PythonHelpWindow::showCustomInterface(const QString &name, const QString &area, const QString &section) {
std::string n = name.toStdString();
std::string a = area.toStdString();
std::string s = section.toStdString();
showCustomInterface(n, a, s);
}

void PythonHelpWindow::shutdown() {}

} // namespace MantidWidgets
} // namespace MantidQt
95 changes: 95 additions & 0 deletions qt/widgets/common/test/PythonHelpWindowTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright &copy; 2018 ISIS Rutherford Appleton Laboratory UKRI,
// NScD Oak Ridge National Laboratory, European Spallation Source,
// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
// SPDX - License - Identifier: GPL - 3.0 +
#pragma once

#include <cxxtest/TestSuite.h>
#include <gmock/gmock.h>

#include <QString>
#include <QUrl>

#include "MantidQtWidgets/Common/PythonHelpBridge.h"
#include "MantidQtWidgets/Common/PythonHelpWindow.h"

#include "MantidKernel/WarningSuppressions.h"
GNU_DIAG_OFF_SUGGEST_OVERRIDE

using namespace MantidQt::API;
using namespace MantidQt::MantidWidgets;
using namespace testing;

GNU_DIAG_ON_SUGGEST_OVERRIDE

class PythonHelpWindowTest : public CxxTest::TestSuite {
public:
void setUp() override {}

void tearDown() override {}

// 1) Test the constructor doesn't throw and creates a valid object
void testConstructorDoesNotThrow() { TS_ASSERT_THROWS_NOTHING(PythonHelpWindow helpWin); }

// 2) Test showPage(std::string) with an empty string
void testShowPageWithEmptyString() {
PythonHelpWindow helpWin;
TS_ASSERT_THROWS_NOTHING(helpWin.showPage(std::string{}));
}

// 3) Test showPage(std::string) with a non-empty string
void testShowPageWithNonEmptyString() {
PythonHelpWindow helpWin;
TS_ASSERT_THROWS_NOTHING(helpWin.showPage("custom_page.html"));
}

// 4) Test showPage(QString) with an empty string
void testShowPage_QString_Empty() {
PythonHelpWindow helpWin;
TS_ASSERT_THROWS_NOTHING(helpWin.showPage(QString()));
}

// 5) Test showPage(QUrl) with an empty URL
void testShowPage_QUrl_Empty() {
PythonHelpWindow helpWin;
TS_ASSERT_THROWS_NOTHING(helpWin.showPage(QUrl()));
}

// 6) Test showAlgorithm(std::string) with empty name and version
void testShowAlgorithm_NoName() {
PythonHelpWindow helpWin;
TS_ASSERT_THROWS_NOTHING(helpWin.showAlgorithm("", -1));
}

// 7) Test showAlgorithm(std::string) with valid name and version
void testShowAlgorithm_NameAndVersion() {
PythonHelpWindow helpWin;
TS_ASSERT_THROWS_NOTHING(helpWin.showAlgorithm("Load", 2));
}

// 8) Test showConcept(std::string) with empty name
void testShowConceptEmpty() {
PythonHelpWindow helpWin;
TS_ASSERT_THROWS_NOTHING(helpWin.showConcept(""));
}

// 9) Test showFitFunction(std::string) with a name
void testShowFitFunctionName() {
PythonHelpWindow helpWin;
TS_ASSERT_THROWS_NOTHING(helpWin.showFitFunction("GaussPeak"));
}

// 10) Test showCustomInterface(std::string) with name, area, section
void testShowCustomInterface() {
PythonHelpWindow helpWin;
TS_ASSERT_THROWS_NOTHING(helpWin.showCustomInterface("Reflectometry", "ISISReflectometry", "Usage"));
}

// 11) Test the shutdown method (currently a no-op)
void testShutdownDoesNotThrow() {
PythonHelpWindow helpWin;
TS_ASSERT_THROWS_NOTHING(helpWin.shutdown());
}
};