1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
/*****************************************************************************
* $CAMITK_LICENCE_BEGIN$
*
* CamiTK - Computer Assisted Medical Intervention ToolKit
* (c) 2001-2025 Univ. Grenoble Alpes, CNRS, Grenoble INP - UGA, TIMC, 38000 Grenoble, France
*
* Visit http://camitk.imag.fr for more information
*
* This file is part of CamiTK.
*
* CamiTK is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* CamiTK is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with CamiTK. If not, see <http://www.gnu.org/licenses/>.
*
* $CAMITK_LICENCE_END$
****************************************************************************/
#ifdef PYTHON_BINDING
#include "PythonHotPlugAction.h"
#include "PythonHotPlugActionExtension.h"
#include "ActionWidget.h"
#include "Application.h"
#include "Log.h"
#include <TransformEngine.h>
#include <VariantDataModel.h>
namespace camitk {
// ------------------- Constructor -------------------
PythonHotPlugAction::PythonHotPlugAction(PythonHotPlugActionExtension* extension, const VariantDataModel& data) : HotPlugAction(extension, data) {
pythonExtension = extension;
TransformEngine transformEngine;
QJsonObject dataObject = data.getValue().toJsonObject();
// determine python script name and other values
pythonName = transformEngine.transformToString("$lowerSnakeCase(name)$", dataObject);
noGui = (dataObject["gui"].toString() == "No GUI");
}
// ------------------- init -------------------
bool PythonHotPlugAction::init() {
// call the init() function in python
PythonHotPlugActionExtension::PythonCallStatus status = pythonExtension->callPython(this, "init");
// Returns true when either everything went well or the init() method is missing in the python script
return (status == PythonHotPlugActionExtension::PythonCallStatus::SUCCESS
|| status == PythonHotPlugActionExtension::PythonCallStatus::MISSING_FUNCTION);
}
// ------------------- getPythonName -------------------
QString PythonHotPlugAction::getPythonName() {
return pythonName;
}
// ------------------- getWidget -------------------
QWidget* PythonHotPlugAction::getWidget() {
if (noGui) {
// this won't generate an error when the parameterChanged() method is missing in the python script (only an info message)
pythonExtension->callPython(this, "targetDefined");
return nullptr;
}
// Get UI, then call targetDefined
if (actionWidget == nullptr) {
// create default widget
QWidget* defaultWidget = Action::getWidget();
return defaultWidget;
}
else {
// this won't generate an error when the parameterChanged() method is missing in the python script (only an info message)
pythonExtension->callPython(this, "targetDefined");
ActionWidget* defaultActionWidget = dynamic_cast<ActionWidget*>(actionWidget);
if (defaultActionWidget != nullptr) {
// this is a default action widget, make sure the widget has updated targets
defaultActionWidget->update();
}
return actionWidget;
}
}
// ------------------- apply -------------------
Action::ApplyStatus PythonHotPlugAction::apply() {
// set waiting cursor
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
// call python and check the results
PythonHotPlugActionExtension::PythonCallStatus status = pythonExtension->callPython(this, "process");
Action::ApplyStatus applyStatus;
if (status == PythonHotPlugActionExtension::PythonCallStatus::SUCCESS) {
applyStatus = Action::SUCCESS;
}
else {
// process() method is missing or something went wrong
applyStatus = Action::ERROR;
// callPython will only use INFO level for these two errors,
// but in this specific case, the user should know → send a warning
if (status == PythonHotPlugActionExtension::PythonCallStatus::NOT_A_FUNCTION) {
CAMITK_ERROR_ALT("Error during call to method process() of action '" + getName() + "': " + "Python script '" + getPythonName() + ".py" + "' has symbol 'process' but it is not a function. Expecting 'def process(self:camitk.Action):'");
}
else {
if (status == PythonHotPlugActionExtension::PythonCallStatus::MISSING_FUNCTION) {
CAMITK_ERROR_ALT("Error during call to method process() of action '" + getName() + "': " + "Python script '" + getPythonName() + ".py" + "' missing function 'process(self)'. Expecting 'def process(self:camitk.Action):'");
}
}
}
// restore normal cursor
QApplication::restoreOverrideCursor();
return applyStatus;
}
// ---------------------- parameterChangedEvent ----------------------------
void PythonHotPlugAction::parameterChangedEvent(QString parameterName) {
// this won't generate an error when the parameterChanged() method is missing in the python script (only an info message)
pythonExtension->callPython(this, "parameterChanged", parameterName);
}
} // namespace camitk
#endif // PYTHON_BINDING
|