diff --git a/Plugins/org.mitk.gui.qt.cli/files.cmake b/Plugins/org.mitk.gui.qt.cli/files.cmake index 65dee90e7e..30935b9fc2 100644 --- a/Plugins/org.mitk.gui.qt.cli/files.cmake +++ b/Plugins/org.mitk.gui.qt.cli/files.cmake @@ -1,66 +1,66 @@ set(SRC_CPP_FILES QmitkCmdLineModuleMenuComboBox.cpp - QmitkCmdLineModuleProgressWidget.cpp ) set(INTERNAL_CPP_FILES QmitkDataStorageComboBoxWithSelectNone.cpp QmitkDirectoryListWidget.cpp QmitkFileListWidget.cpp QmitkCmdLineModuleGui.cpp QmitkCmdLineModuleFactoryGui.cpp QmitkUiLoader.cpp org_mitk_gui_qt_cli_Activator.cpp CommandLineModulesViewConstants.cpp CommandLineModulesViewControls.cpp CommandLineModulesPreferencesPage.cpp CommandLineModulesView.cpp + QmitkCmdLineModuleProgressWidget.cpp ) set(UI_FILES - src/QmitkCmdLineModuleProgressWidget.ui src/internal/QmitkPathListWidget.ui src/internal/CommandLineModulesViewControls.ui + src/internal/QmitkCmdLineModuleProgressWidget.ui ) set(MOC_H_FILES src/QmitkCmdLineModuleMenuComboBox.h - src/QmitkCmdLineModuleProgressWidget.h src/internal/QmitkDataStorageComboBoxWithSelectNone.h src/internal/QmitkDirectoryListWidget.h src/internal/QmitkFileListWidget.h src/internal/QmitkCmdLineModuleGui.h src/internal/QmitkUiLoader.h src/internal/org_mitk_gui_qt_cli_Activator.h src/internal/CommandLineModulesViewControls.h src/internal/CommandLineModulesPreferencesPage.h src/internal/CommandLineModulesView.h + src/internal/QmitkCmdLineModuleProgressWidget.h ) # list of resource files which can be used by the plug-in # system without loading the plug-ins shared library, # for example the icon used in the menu and tabs for the # plug-in views in the workbench set(CACHED_RESOURCE_FILES resources/icon.xpm resources/run.png resources/stop.png plugin.xml ) # list of Qt .qrc files which contain additional resources # specific to this plugin set(QRC_FILES resources/CommandLineModulesResources.qrc ) set(CPP_FILES ) foreach(file ${SRC_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/${file}) endforeach(file ${SRC_CPP_FILES}) foreach(file ${INTERNAL_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/internal/${file}) endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesView.cpp b/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesView.cpp index dbdb58b26e..3f496cffdb 100644 --- a/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesView.cpp +++ b/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesView.cpp @@ -1,380 +1,318 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) University College London (UCL). All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include #include // Qmitk #include "CommandLineModulesView.h" #include "CommandLineModulesViewConstants.h" #include "CommandLineModulesViewControls.h" #include "CommandLineModulesPreferencesPage.h" #include "QmitkCmdLineModuleFactoryGui.h" +#include "QmitkCmdLineModuleProgressWidget.h" // Qt #include #include #include -#include -#include +#include +#include +#include // CTK #include #include #include #include #include #include #include //----------------------------------------------------------------------------- CommandLineModulesView::CommandLineModulesView() : m_Controls(NULL) , m_Parent(NULL) +, m_Layout(NULL) , m_ModuleManager(NULL) , m_ModuleBackend(NULL) -, m_ModuleFactory(NULL) , m_DirectoryWatcher(NULL) , m_TemporaryDirectoryName("") , m_DebugOutput(false) { } //----------------------------------------------------------------------------- CommandLineModulesView::~CommandLineModulesView() { if (m_ModuleManager != NULL) { delete m_ModuleManager; } if (m_ModuleBackend != NULL) { delete m_ModuleBackend; } - if (m_ModuleFactory != NULL) + if (m_DirectoryWatcher != NULL) { - delete m_ModuleFactory; + delete m_DirectoryWatcher; } - if (m_DirectoryWatcher != NULL) + if (m_Layout != NULL) { - delete m_DirectoryWatcher; + delete m_Layout; } } //----------------------------------------------------------------------------- void CommandLineModulesView::SetFocus() { this->m_Controls->m_ComboBox->setFocus(); } //----------------------------------------------------------------------------- void CommandLineModulesView::CreateQtPartControl( QWidget *parent ) { if (!m_Controls) { - m_MapTabToModuleInstance.clear(); - // We create CommandLineModulesViewControls, which derives from the Qt generated class. m_Controls = new CommandLineModulesViewControls(parent); + // Create a layout to contain a display of QmitkCmdLineModuleProgressWidget. + m_Layout = new QVBoxLayout(m_Controls->m_GeneratedGuiWidget); + m_Layout->setContentsMargins(0,0,0,0); + m_Layout->setSpacing(0); + // This must be done independent of other preferences, as we need it before // we create the ctkCmdLineModuleManager to initialise the Cache. this->RetrieveAndStoreTemporaryDirectoryPreferenceValues(); - // Create the command line module infrastructure. + // Start to create the command line module infrastructure. m_ModuleBackend = new ctkCmdLineModuleBackendLocalProcess(); - m_ModuleFactory = new QmitkCmdLineModuleFactoryGui(this->GetDataStorage()); m_ModuleManager = new ctkCmdLineModuleManager(ctkCmdLineModuleManager::STRICT_VALIDATION, m_TemporaryDirectoryName); + // Set the main object, the ctkCmdLineModuleManager onto all the objects that need it. m_Controls->m_ComboBox->SetManager(m_ModuleManager); m_DirectoryWatcher = new ctkCmdLineModuleDirectoryWatcher(m_ModuleManager); - m_ModuleManager->registerBackend(m_ModuleBackend); // Setup the remaining preferences. this->RetrieveAndStorePreferenceValues(); // Connect signals to slots after we have set up GUI. - connect(this->m_Controls->m_RunButton, SIGNAL(pressed()), this, SLOT(OnRunPauseButtonPressed())); + connect(this->m_Controls->m_RunButton, SIGNAL(pressed()), this, SLOT(OnRunButtonPressed())); connect(this->m_Controls->m_RestoreDefaults, SIGNAL(pressed()), this, SLOT(OnRestoreButtonPressed())); connect(this->m_Controls->m_ComboBox, SIGNAL(actionChanged(QAction*)), this, SLOT(OnActionChanged(QAction*))); } } //----------------------------------------------------------------------------- berry::IBerryPreferences::Pointer CommandLineModulesView::RetrievePreferences() { berry::IPreferencesService::Pointer prefService = berry::Platform::GetServiceRegistry() .GetServiceById(berry::IPreferencesService::ID); assert( prefService ); std::string id = "/" + CommandLineModulesViewConstants::VIEW_ID; berry::IBerryPreferences::Pointer prefs = (prefService->GetSystemPreferences()->Node(id)) .Cast(); assert( prefs ); return prefs; } //----------------------------------------------------------------------------- void CommandLineModulesView::RetrieveAndStoreTemporaryDirectoryPreferenceValues() { berry::IBerryPreferences::Pointer prefs = this->RetrievePreferences(); QString fallbackTmpDir = QDir::tempPath(); m_TemporaryDirectoryName = QString::fromStdString( prefs->Get(CommandLineModulesViewConstants::TEMPORARY_DIRECTORY_NODE_NAME, fallbackTmpDir.toStdString())); } //----------------------------------------------------------------------------- void CommandLineModulesView::RetrieveAndStorePreferenceValues() { berry::IBerryPreferences::Pointer prefs = this->RetrievePreferences(); // Get the flag for debug output, useful when parsing all the XML. m_DebugOutput = prefs->GetBool(CommandLineModulesViewConstants::DEBUG_OUTPUT_NODE_NAME, false); m_DirectoryWatcher->setDebug(m_DebugOutput); bool loadApplicationDir = prefs->GetBool(CommandLineModulesViewConstants::LOAD_FROM_APPLICATION_DIR, false); bool loadHomeDir = prefs->GetBool(CommandLineModulesViewConstants::LOAD_FROM_HOME_DIR, false); bool loadCurrentDir = prefs->GetBool(CommandLineModulesViewConstants::LOAD_FROM_CURRENT_DIR, false); bool loadAutoLoadDir = prefs->GetBool(CommandLineModulesViewConstants::LOAD_FROM_AUTO_LOAD_DIR, false); // Get some default application paths. // Here we can use the preferences to set up the builder, ctkCmdLineModuleDefaultPathBuilder builder; builder.setLoadFromApplicationDir(loadApplicationDir); builder.setLoadFromHomeDir(loadHomeDir); builder.setLoadFromCurrentDir(loadCurrentDir); builder.setLoadFromCtkModuleLoadPath(loadAutoLoadDir); // and then we ask the builder to set up the paths. QStringList defaultPaths = builder.build(); // We get additional directory paths from preferences. QString pathString = QString::fromStdString(prefs->Get(CommandLineModulesViewConstants::MODULE_DIRECTORIES_NODE_NAME, "")); QStringList additionalPaths = pathString.split(";", QString::SkipEmptyParts); // Combine the sets of directory paths. QStringList totalPaths; totalPaths << defaultPaths; totalPaths << additionalPaths; QString additionalModulesString = QString::fromStdString(prefs->Get(CommandLineModulesViewConstants::MODULE_FILES_NODE_NAME, "")); QStringList additionalModules = additionalModulesString.split(";", QString::SkipEmptyParts); // OnPreferencesChanged can be called for each preference in a dialog box, so // when you hit "OK", it is called repeatedly, whereas we want to only call these only once. if (this->m_DirectoryWatcher->directories() != totalPaths) { m_DirectoryWatcher->setDirectories(totalPaths); } if (this->m_DirectoryWatcher->additionalModules() != additionalModules) { m_DirectoryWatcher->setAdditionalModules(additionalModules); } } //----------------------------------------------------------------------------- void CommandLineModulesView::OnPreferencesChanged(const berry::IBerryPreferences* /*prefs*/) { this->RetrieveAndStoreTemporaryDirectoryPreferenceValues(); this->RetrieveAndStorePreferenceValues(); } //----------------------------------------------------------------------------- -void CommandLineModulesView::AddModuleTab(const ctkCmdLineModuleReference& moduleRef) +ctkCmdLineModuleReference CommandLineModulesView::GetReferenceByFullName(QString fullName) { - // We don't want to repeatedly create new tabs. If the moduleRef points to - // an existing tab, make that tab the current tab. - for (int i = 0; i < m_Controls->m_TabWidget->count(); i++) - { - if (m_Controls->m_TabWidget->tabText(i) == moduleRef.description().title()) - { - m_Controls->m_TabWidget->setCurrentIndex(i); - return; - } - } - - // Otherwise, create a new tab. - ctkCmdLineModuleFrontend* moduleInstance = m_ModuleFactory->create(moduleRef); - if (!moduleInstance) return; - - // Build up the GUI layout programmatically (manually). - - QTabWidget *documentationTabWidget = new QTabWidget(); - documentationTabWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); - - QWidget *aboutWidget = new QWidget(); - QWidget *helpWidget = new QWidget(); - - QTextBrowser *aboutBrowser = new QTextBrowser(aboutWidget); - aboutBrowser->setReadOnly(true); - aboutBrowser->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); - - QTextBrowser *helpBrowser = new QTextBrowser(helpWidget); - helpBrowser->setReadOnly(true); - helpBrowser->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); - - QHBoxLayout *aboutLayout = new QHBoxLayout(aboutWidget); - aboutLayout->addWidget(aboutBrowser); - aboutLayout->setContentsMargins(0,0,0,0); - aboutLayout->setSpacing(0); - - QHBoxLayout *helpLayout = new QHBoxLayout(helpWidget); - helpLayout->addWidget(helpBrowser); - helpLayout->setContentsMargins(0,0,0,0); - helpLayout->setSpacing(0); - - documentationTabWidget->addTab(aboutWidget, "About"); - documentationTabWidget->addTab(helpWidget, "Help"); - - QObject* guiHandle = moduleInstance->guiHandle(); - QWidget* generatedGuiWidgets = qobject_cast(guiHandle); - - QWidget *topLevelWidget = new QWidget(); - QGridLayout *topLevelLayout = new QGridLayout(topLevelWidget); - - topLevelLayout->setContentsMargins(0,0,0,0); - topLevelLayout->setSpacing(0); - topLevelLayout->addWidget(documentationTabWidget, 0, 0); - topLevelLayout->setRowStretch(0, 1); - topLevelLayout->addWidget(generatedGuiWidgets, 1, 0); - topLevelLayout->setRowStretch(1, 10); - - ctkCmdLineModuleDescription description = moduleRef.description(); - - QString helpString = ""; - - if (!description.title().isEmpty()) - { - QString titleHtml = "

" + description.title() + "

"; - helpString += titleHtml; - } + ctkCmdLineModuleReference result; - if (!description.description().isEmpty()) - { - QString descriptionHtml = "

" + description.description() + "

"; - helpString += descriptionHtml; - } + QList references = this->m_ModuleManager->moduleReferences(); - if (!description.documentationURL().isEmpty()) + ctkCmdLineModuleReference ref; + foreach(ref, references) { - QString docUrlHtml = "

For more information please see the online documentation.

"; - helpString += docUrlHtml; + QString name = ref.description().category() + "." + ref.description().title(); + if (name == fullName) + { + result = ref; + } } - QString aboutString = ""; - - if (!description.title().isEmpty()) - { - QString titleHtml = "

" + description.title() + "

"; - aboutString += titleHtml; - } + return result; +} - if (!description.contributor().isEmpty()) - { - QString contributorHtml = "

Contributed By

" + description.contributor() + "

"; - aboutString += contributorHtml; - } - if (!description.license().isEmpty()) - { - QString licenseHtml = "

License

" + description.license() + "

"; - aboutString += licenseHtml; - } +//----------------------------------------------------------------------------- +QmitkCmdLineModuleProgressWidget* CommandLineModulesView::GetWidget(const int& indexNumber) +{ + QmitkCmdLineModuleProgressWidget *result = NULL; - if (!description.acknowledgements().isEmpty()) + QLayoutItem *layoutItem = m_Layout->itemAt(indexNumber); + if (layoutItem != NULL) { - QString acknowledgementsHtml = "

Acknowledgements

" + description.acknowledgements() + "

"; - aboutString += acknowledgementsHtml; + QWidgetItem *widgetItem = dynamic_cast(layoutItem); + if (widgetItem != NULL) + { + result = dynamic_cast(widgetItem->widget()); + } } - helpBrowser->clear(); - helpBrowser->setHtml(helpString); - aboutBrowser->clear(); - aboutBrowser->setHtml(aboutString); - - int tabIndex = m_Controls->m_TabWidget->addTab(topLevelWidget, moduleRef.description().title()); - m_Controls->m_TabWidget->setCurrentIndex(tabIndex); - m_MapTabToModuleInstance[tabIndex] = moduleInstance; - + return result; } //----------------------------------------------------------------------------- -ctkCmdLineModuleReference CommandLineModulesView::GetReferenceByIdentifier(QString identifier) +void CommandLineModulesView::OnActionChanged(QAction* action) { - ctkCmdLineModuleReference result; - - QList references = this->m_ModuleManager->moduleReferences(); + QString fullName = action->objectName(); + ctkCmdLineModuleReference ref = this->GetReferenceByFullName(fullName); - ctkCmdLineModuleReference ref; - foreach(ref, references) + if (ref) { - if (ref.description().title() == identifier) + QmitkCmdLineModuleProgressWidget *widget = this->GetWidget(0); + if (widget == NULL + || widget->IsStarted()) { - result = ref; + // Create new widget. + QmitkCmdLineModuleProgressWidget* newWidget = new QmitkCmdLineModuleProgressWidget(m_Controls->m_GeneratedGuiWidget); + + // Configure new widget. + newWidget->SetTemporaryDirectory(this->m_TemporaryDirectoryName); + newWidget->SetDataStorage(this->GetDataStorage()); + newWidget->SetManager(this->m_ModuleManager); + newWidget->SetModule(ref); + + // Add new widget to the top (nearest top of screen) of layout. + m_Layout->insertWidget(0, newWidget); + } + else + { + // If the first widget has not even started, we can simply replace the GUI, + // with the correct GUI for the newly selected command line module. + + // Note: At the moment, I'm getting 3 signals instead of 1 ??? + if (widget->GetFullName() != fullName) + { + widget->SetModule(ref); + } } } - - return result; } //----------------------------------------------------------------------------- void CommandLineModulesView::OnRestoreButtonPressed() { - ctkCmdLineModuleFrontend* moduleInstance = m_MapTabToModuleInstance[m_Controls->m_TabWidget->currentIndex()]; - if (!moduleInstance) + QmitkCmdLineModuleProgressWidget *widget = this->GetWidget(0); + if (widget != NULL && !widget->IsStarted()) { - qWarning() << "Invalid module instance"; - return; + widget->Reset(); } - moduleInstance->resetValues(); } //----------------------------------------------------------------------------- -void CommandLineModulesView::OnActionChanged(QAction* action) +void CommandLineModulesView::OnRunButtonPressed() { - ctkCmdLineModuleReference ref = this->GetReferenceByIdentifier(action->text()); - if (ref) + QmitkCmdLineModuleProgressWidget *widget = this->GetWidget(0); + if (widget != NULL && !widget->IsStarted()) { - this->AddModuleTab(ref); + widget->Run(); } } - - diff --git a/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesView.h b/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesView.h index c62144076a..c92d134d65 100644 --- a/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesView.h +++ b/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesView.h @@ -1,174 +1,176 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) University College London (UCL). All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef CommandLineModulesView_h #define CommandLineModulesView_h #include #include #include #include #include #include -class QmitkCmdLineModuleFactoryGui; class ctkCmdLineModuleManager; -class ctkCmdLineModuleFrontend; class ctkCmdLineModuleBackendLocalProcess; class ctkCmdLineModuleDirectoryWatcher; -class ctkCmdLineModuleFutureWatcher; class CommandLineModulesViewControls; +class QmitkCmdLineModuleProgressWidget; class QAction; +class QVBoxLayout; namespace berry { class IBerryPreferences; } /*! * \class CommandLineModulesView * \brief Provides basic GUI interface to the CTK command line modules. * \author Matt Clarkson (m.clarkson@ucl.ac.uk) * \ingroup org_mitk_gui_qt_cli_internal * \sa QmitkAbstractView */ class CommandLineModulesView : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: CommandLineModulesView(); virtual ~CommandLineModulesView(); /** * \brief Main method, called by framework to create the GUI at the right time. * \param parent The parent QWidget, as this class itself is not a QWidget subclass. */ virtual void CreateQtPartControl(QWidget *parent); /** * \brief Called by the framework to indicate that the preferences have changed. * \param prefs not used, as we call RetrievePreferenceValues(). */ void OnPreferencesChanged(const berry::IBerryPreferences* prefs); protected Q_SLOTS: /** * \brief Called when the ctkMenuComboBox has the menu selection changed, - * meaning that a new GUI page be created in another tab. + * and causes the corresponding GUI to be displayed. */ void OnActionChanged(QAction*); /** * \brief Slot that is called when the restore defaults button is pressed, - * to reset the current GUI form to the default values. + * to reset the current GUI form to the default values, if the XML specifies them. */ void OnRestoreButtonPressed(); + /** + * \brief Slot that is called when the Run button (green arrow) is pressed, + * to run the current module. + */ + void OnRunButtonPressed(); + protected: /** * \brief Called by framework to set the focus on the right widget * when this view has focus, so currently, thats the combo box. */ virtual void SetFocus(); private: /** * \brief Called on startup and by OnPreferencesChanged to load all * preferences except the temporary folder into member variables. */ void RetrieveAndStorePreferenceValues(); /** * \brief Called on startup and by OnPreferencesChanged to load the temporary folder * preference into member variable m_TemporaryDirectoryName. */ void RetrieveAndStoreTemporaryDirectoryPreferenceValues(); /** * \brief Called to get hold of the actual preferences node. */ berry::IBerryPreferences::Pointer RetrievePreferences(); /** - * \brief Search the internal datastructure (QHash) to find the reference that matches the identifier. - * \param identifier The identifier used in the front end combo box widget, currently title. - * \return ctkCmdLineModuleReference the reference corresponding to the identifier, or an invalid reference if non found. + * \brief Search all modules for the one matching the given identifier. + * \param fullName The "fullName" is the . from the XML. + * \return ctkCmdLineModuleReference the reference corresponding to the fullName, or an invalid reference if non found. */ - ctkCmdLineModuleReference GetReferenceByIdentifier(QString identifier); + ctkCmdLineModuleReference GetReferenceByFullName(QString fullName); /** - * \brief Adds a module to the views tabbed widget, creating a new tab each time. - * \param moduleRef A ctkCmdLineModuleReference. + * \brief Returns the QmitkCmdLineModuleProgressWidget from the layout. + * \param indexNumber the number of the widget in the layout, starting at zero. */ - void AddModuleTab(const ctkCmdLineModuleReference& moduleRef); + QmitkCmdLineModuleProgressWidget* GetWidget(const int& indexNumber); /** - * \brief The GUI controls contain a run/stop button, and a tabbed widget, and the GUI component - * for each command line module is added to the tabbed widget dynamically at run time. + * \brief The GUI controls contain a reset and run button, and a QWidget container, and the GUI component + * for each command line module is added to the QWidget dynamically at run time. */ CommandLineModulesViewControls *m_Controls; /** - * \brief We store the parent, passed in via CommandLineModulesView::CreateQtPartControl, as this class itself is not a QWidget. + * \brief We store the parent, passed in via CommandLineModulesView::CreateQtPartControl, + * as this class itself is not a QWidget. */ QWidget *m_Parent; + /** + * \brief We keep a local layout, and arrange a display of QmitkCmdLineModuleProgressWidget, + * where each QmitkCmdLineModuleProgressWidget represents a single running job. + */ + QVBoxLayout *m_Layout; + /** * \brief The manager is responsible for loading and instantiating command line modules. */ ctkCmdLineModuleManager *m_ModuleManager; /** * \brief We are using a back-end that runs locally installed command line programs. */ ctkCmdLineModuleBackendLocalProcess *m_ModuleBackend; - /** - * \brief The QmitkCmdLineModuleFactoryGui builds a gui for each plugin. - */ - QmitkCmdLineModuleFactoryGui *m_ModuleFactory; - /** * \brief The ctkCmdLineModuleDirectoryWatcher maintains the list of directories * we are using to load modules, to provide automatic updates. */ ctkCmdLineModuleDirectoryWatcher *m_DirectoryWatcher; - /** - * \brief We use this map to decide if we want to create more tabs or not. - */ - QHash<int, ctkCmdLineModuleFrontend*> m_MapTabToModuleInstance; - /** * \brief We store a temporary folder name, accessible via user preferences. */ QString m_TemporaryDirectoryName; /** * \brief Member variable, taken from preference page. */ bool m_DebugOutput; }; #endif // CommandLineModulesView_h diff --git a/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesViewControls.cpp b/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesViewControls.cpp index 2d27fb9e33..53b3589058 100644 --- a/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesViewControls.cpp +++ b/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesViewControls.cpp @@ -1,95 +1,34 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) University College London (UCL). All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "CommandLineModulesViewControls.h" #include <QIcon> #include <QSize> #include <QHBoxLayout> //----------------------------------------------------------------------------- CommandLineModulesViewControls::CommandLineModulesViewControls(QWidget *parent) { this->setupUi(parent); this->m_RunButton->setIcon(QIcon(":/CommandLineModulesResources/run.png")); this->m_RestoreDefaults->setIcon(QIcon(":/CommandLineModulesResources/undo.png")); - this->Initial(); } //----------------------------------------------------------------------------- CommandLineModulesViewControls::~CommandLineModulesViewControls() { } - - -//----------------------------------------------------------------------------- -void CommandLineModulesViewControls::Initial() -{ - this->m_RunButton->setIcon(QIcon(":/CommandLineModulesResources/run.png")); - this->m_RunButton->setToolTip("run application"); - this->m_RunButton->update(); - this->Enable(true); -} - - -//----------------------------------------------------------------------------- -void CommandLineModulesViewControls::Running() -{ - this->m_RunButton->setIcon(QIcon(":/CommandLineModulesResources/pause.png")); - this->m_RunButton->setToolTip("pause application"); - this->m_RunButton->update(); - this->Enable(false); -} - - -//----------------------------------------------------------------------------- -void CommandLineModulesViewControls::Cancel() -{ - this->Initial(); -} - - -//----------------------------------------------------------------------------- -void CommandLineModulesViewControls::Pause() -{ - this->m_RunButton->setIcon(QIcon(":/CommandLineModulesResources/run.png")); - this->m_RunButton->setToolTip("resume application"); - this->m_RunButton->update(); - this->Enable(false); -} - - -//----------------------------------------------------------------------------- -void CommandLineModulesViewControls::Resume() -{ - this->Running(); -} - - -//----------------------------------------------------------------------------- -void CommandLineModulesViewControls::Finished() -{ - this->Initial(); -} - - -//----------------------------------------------------------------------------- -void CommandLineModulesViewControls::Enable(bool enable) -{ - this->m_ComboBox->setEnabled(enable); - this->m_TabWidget->setEnabled(enable); - this->m_RestoreDefaults->setEnabled(enable); -} diff --git a/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesViewControls.h b/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesViewControls.h index fe7363708b..052fe45ff8 100644 --- a/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesViewControls.h +++ b/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesViewControls.h @@ -1,54 +1,46 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) University College London (UCL). All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef CommandLineModulesViewControls_h #define CommandLineModulesViewControls_h #include "ui_CommandLineModulesViewControls.h" class QHBoxLayout; /** * \class CommandLineModulesViewControls - * \brief Class derived from Ui_CommandLineModulesViewControls to provide programatic access to GUI. + * \brief Class derived from Ui_CommandLineModulesViewControls to provide access to GUI widgets. * \author Matt Clarkson (m.clarkson@ucl.ac.uk) * \ingroup org_mitk_gui_qt_cli_internal */ class CommandLineModulesViewControls : public QWidget, public Ui_CommandLineModulesViewControls { // this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) Q_OBJECT public: CommandLineModulesViewControls(QWidget *parent = 0); virtual ~CommandLineModulesViewControls(); - void Initial(); - void Running(); - void Cancel(); - void Pause(); - void Resume(); - void Finished(); - protected: private: - void Enable(bool enable); }; #endif // CommandLineModulesViewControls_h diff --git a/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesViewControls.ui b/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesViewControls.ui index 6a10289091..0f96d4e0b7 100644 --- a/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesViewControls.ui +++ b/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesViewControls.ui @@ -1,134 +1,129 @@ <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>CommandLineModulesViewControls</class> <widget class="QWidget" name="CommandLineModulesViewControls"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>678</width> <height>582</height> </rect> </property> <property name="minimumSize"> <size> <width>0</width> <height>0</height> </size> </property> <property name="windowTitle"> <string>QmitkTemplate</string> </property> <layout class="QVBoxLayout" name="verticalLayout"> <item> <layout class="QHBoxLayout" name="m_HorizontalLayout"> <item> <widget class="QLabel" name="m_ChooseLabel"> <property name="sizePolicy"> <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="toolTip"> <string/> </property> <property name="text"> <string>choose:</string> </property> </widget> </item> <item> <widget class="QmitkCmdLineModuleMenuComboBox" name="m_ComboBox" native="true"/> </item> <item> <widget class="QPushButton" name="m_RestoreDefaults"> <property name="sizePolicy"> <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="toolTip"> <string>restore default parameters</string> </property> <property name="text"> <string/> </property> </widget> </item> <item> <widget class="QPushButton" name="m_RunButton"> <property name="sizePolicy"> <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="toolTip"> <string>run the command line module</string> </property> <property name="text"> <string/> </property> </widget> </item> <item> <spacer name="m_HorizontalSpacer"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>40</width> <height>20</height> </size> </property> </spacer> </item> </layout> </item> <item> <widget class="QWidget" name="m_GeneratedGuiWidget" native="true"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <layout class="QHBoxLayout" name="horizontalLayout"> - <property name="spacing"> - <number>0</number> - </property> - <property name="margin"> - <number>0</number> - </property> - </layout> </widget> </item> <item> - <widget class="QTabWidget" name="m_TabWidget"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> </property> - </widget> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>250</height> + </size> + </property> + </spacer> </item> </layout> </widget> <layoutdefault spacing="6" margin="11"/> <customwidgets> <customwidget> <class>QmitkCmdLineModuleMenuComboBox</class> <extends>QWidget</extends> <header>QmitkCmdLineModuleMenuComboBox.h</header> <container>1</container> </customwidget> </customwidgets> <resources> <include location="../../resources/CommandLineModulesResources.qrc"/> </resources> <connections/> </ui> diff --git a/Plugins/org.mitk.gui.qt.cli/src/internal/QmitkCmdLineModuleProgressWidget.cpp b/Plugins/org.mitk.gui.qt.cli/src/internal/QmitkCmdLineModuleProgressWidget.cpp new file mode 100644 index 0000000000..7fca5825f7 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.cli/src/internal/QmitkCmdLineModuleProgressWidget.cpp @@ -0,0 +1,595 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) University College London (UCL). +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkCmdLineModuleProgressWidget.h" +#include "ui_QmitkCmdLineModuleProgressWidget.h" + +// Qt +#include <QFile> +#include <QVBoxLayout> +#include <QLayoutItem> +#include <QTextBrowser> + +// CTK +#include <ctkCmdLineModuleFuture.h> +#include <ctkCmdLineModuleManager.h> +#include <ctkCmdLineModuleFrontend.h> +#include <ctkCmdLineModuleDescription.h> +#include <ctkCmdLineModuleParameter.h> + +// MITK +#include <mitkIOUtil.h> +#include <mitkDataStorage.h> +#include <mitkDataNode.h> +#include <QmitkCommonFunctionality.h> +#include <QmitkCustomVariants.h> +#include "QmitkCmdLineModuleFactoryGui.h" + +//----------------------------------------------------------------------------- +QmitkCmdLineModuleProgressWidget::QmitkCmdLineModuleProgressWidget(QWidget *parent) + : QWidget(parent) +, m_ModuleManager(NULL) +, m_DataStorage(NULL) +, m_TemporaryDirectoryName("") +, m_UI(new Ui::QmitkCmdLineModuleProgressWidget) +, m_ModuleFrontEnd(NULL) +, m_FutureWatcher(NULL) +{ + m_UI->setupUi(this); + m_UI->m_RemoveButton->setIcon(QApplication::style()->standardIcon(QStyle::SP_TitleBarCloseButton)); + + m_Layout = new QVBoxLayout(); + m_UI->m_ParametersGroupBox->setLayout(m_Layout); + + qRegisterMetaType<mitk::DataNode::Pointer>(); + qRegisterMetaType<ctkCmdLineModuleReference>(); + + // Due to Qt bug 12152, we cannot listen to the "paused" signal because it is + // not emitted directly when the QFuture is paused. Instead, it is emitted after + // resuming the future, after the "resume" signal has been emitted... we use + // a polling approach instead. + m_PollPauseTimer.setInterval(300); + connect(&m_PollPauseTimer, SIGNAL(timeout()), SLOT(OnCheckModulePaused())); + + connect(m_UI->m_RemoveButton, SIGNAL(clicked()), this, SLOT(OnRemoveButtonClicked())); + + m_PollPauseTimer.start(); +} + + +//----------------------------------------------------------------------------- +QmitkCmdLineModuleProgressWidget::~QmitkCmdLineModuleProgressWidget() +{ + if (m_ModuleFrontEnd != NULL) + { + delete m_ModuleFrontEnd; + } + + this->ClearUpTemporaryFiles(); + + delete m_UI; +} + + +//----------------------------------------------------------------------------- +void QmitkCmdLineModuleProgressWidget::SetManager(ctkCmdLineModuleManager* manager) +{ + this->m_ModuleManager = manager; +} + + +//----------------------------------------------------------------------------- +void QmitkCmdLineModuleProgressWidget::SetDataStorage(mitk::DataStorage* dataStorage) +{ + this->m_DataStorage = dataStorage; +} + + +//----------------------------------------------------------------------------- +void QmitkCmdLineModuleProgressWidget::SetTemporaryDirectory(const QString& directoryName) +{ + this->m_TemporaryDirectoryName = directoryName; +} + + +//----------------------------------------------------------------------------- +QString QmitkCmdLineModuleProgressWidget::GetTitle() +{ + assert(m_ModuleFrontEnd); + + ctkCmdLineModuleReference reference = m_ModuleFrontEnd->moduleReference(); + ctkCmdLineModuleDescription description = reference.description(); + + return description.title(); +} + + +//----------------------------------------------------------------------------- +void QmitkCmdLineModuleProgressWidget::OnCheckModulePaused() +{ + if (!this->IsStarted()) + { + return; + } + + if (this->m_FutureWatcher->future().isPaused()) + { + if (!m_UI->m_PauseButton->isChecked()) + { + m_UI->m_PauseButton->setChecked(true); + } + } + else + { + if (m_UI->m_PauseButton->isChecked()) + { + m_UI->m_PauseButton->setChecked(false); + } + } +} + + +//----------------------------------------------------------------------------- +void QmitkCmdLineModuleProgressWidget::OnPauseButtonToggled(bool toggled) +{ + this->m_FutureWatcher->setPaused(toggled); + + if (toggled) + { + this->m_UI->m_ProgressTitle->setText(this->GetTitle() + ": paused"); + } + else + { + this->m_UI->m_ProgressTitle->setText(this->GetTitle() + ": resumed"); + } +} + + +//----------------------------------------------------------------------------- +void QmitkCmdLineModuleProgressWidget::OnRemoveButtonClicked() +{ + this->deleteLater(); +} + + +//----------------------------------------------------------------------------- +void QmitkCmdLineModuleProgressWidget::OnModuleStarted() +{ + this->m_UI->m_ProgressBar->setMaximum(0); + + QString message = "started."; + this->PublishMessage(message); +} + + +//----------------------------------------------------------------------------- +void QmitkCmdLineModuleProgressWidget::OnModuleCanceled() +{ + this->m_UI->m_PauseButton->setEnabled(false); + this->m_UI->m_PauseButton->setChecked(false); + this->m_UI->m_CancelButton->setEnabled(false); + this->m_UI->m_RemoveButton->setEnabled(true); + + this->m_UI->m_ParametersGroupBox->setCollapsed(true); + this->m_UI->m_ConsoleGroupBox->setCollapsed(true); + this->m_UI->m_ProgressTitle->setText(this->GetTitle() + ": cancelled"); +} + + +//----------------------------------------------------------------------------- +void QmitkCmdLineModuleProgressWidget::OnModuleFinished() +{ + QString message = "finishing."; + this->PublishMessage(message); + + this->m_UI->m_PauseButton->setEnabled(false); + this->m_UI->m_PauseButton->setChecked(false); + this->m_UI->m_CancelButton->setEnabled(false); + this->m_UI->m_RemoveButton->setEnabled(true); + this->m_UI->m_ProgressTitle->setText(this->GetTitle() + ": finished"); + + if (!this->m_FutureWatcher->isCanceled()) + { + this->LoadOutputData(); + this->ClearUpTemporaryFiles(); + } + + message = "finished."; + this->PublishMessage(message); +} + + +//----------------------------------------------------------------------------- +void QmitkCmdLineModuleProgressWidget::OnModuleResumed() +{ + this->m_UI->m_PauseButton->setChecked(false); +} + + +//----------------------------------------------------------------------------- +void QmitkCmdLineModuleProgressWidget::OnModuleProgressRangeChanged(int progressMin, int progressMax) +{ + this->m_UI->m_ProgressBar->setMinimum(progressMin); + this->m_UI->m_ProgressBar->setMaximum(progressMax); +} + + +//----------------------------------------------------------------------------- +void QmitkCmdLineModuleProgressWidget::OnModuleProgressTextChanged(const QString& progressText) +{ + this->m_UI->m_Console->appendPlainText(progressText); +} + + +//----------------------------------------------------------------------------- +void QmitkCmdLineModuleProgressWidget::OnModuleProgressValueChanged(int progressValue) +{ + this->m_UI->m_ProgressBar->setValue(progressValue); +} + + +//----------------------------------------------------------------------------- +void QmitkCmdLineModuleProgressWidget::PublishMessage(const QString& message) +{ + QString prefix = ""; // Can put additional prefix here if needed. + QString outputMessage = prefix + message; + + qDebug() << outputMessage; + this->m_UI->m_Console->appendPlainText(outputMessage); +} + + +//----------------------------------------------------------------------------- +void QmitkCmdLineModuleProgressWidget::ClearUpTemporaryFiles() +{ + QString message; + QString fileName; + + foreach (fileName, m_TemporaryFileNames) + { + QFile file(fileName); + if (file.exists()) + { + message = QObject::tr("removing %1").arg(fileName); + this->PublishMessage(message); + + bool success = file.remove(); + + message = QObject::tr("removed %1, successfully=%2").arg(fileName).arg(success); + this->PublishMessage(message); + } + } +} + + +//----------------------------------------------------------------------------- +void QmitkCmdLineModuleProgressWidget::LoadOutputData() +{ + assert(m_DataStorage); + + std::vector<std::string> fileNames; + + QString fileName; + foreach (fileName, m_OutputDataToLoad) + { + QString message = QObject::tr("loading %1").arg(fileName); + this->PublishMessage(message); + + fileNames.push_back(fileName.toStdString()); + } + + if (fileNames.size() > 0) + { + int numberLoaded = mitk::IOUtil::LoadFiles(fileNames, *(m_DataStorage)); + + QString message = QObject::tr("loaded %1 files").arg(numberLoaded); + this->PublishMessage(message); + } +} + + +//----------------------------------------------------------------------------- +void QmitkCmdLineModuleProgressWidget::SetModule(const ctkCmdLineModuleReference& reference) +{ + + assert(m_ModuleManager); + assert(m_DataStorage); + + // If a widget exists, remove it from the layout and delete. + QLayoutItem *item = m_Layout->itemAt(0); + if (item != NULL) + { + m_Layout->removeItem(item); + delete item; + } + + // Also make sure we delete the layout. + if (m_Layout != NULL) + { + delete m_Layout; + } + + // If the corresponding front end exists, destroy it. + if (m_ModuleFrontEnd != NULL) + { + delete m_ModuleFrontEnd; + } + + m_Layout = new QVBoxLayout(); + m_Layout->setContentsMargins(0,0,0,0); + m_Layout->setSpacing(0); + + m_UI->m_ParametersGroupBox->setLayout(m_Layout); + + // This method is called when the user selects a new module to display. + // Aim of this method is to create a default GUI, and attach it to this widget. + + QmitkCmdLineModuleFactoryGui factory(m_DataStorage); + m_ModuleFrontEnd = factory.create(reference); + + if (!m_ModuleFrontEnd) + { + qDebug() << "QmitkCmdLineModuleProgressWidget: Failed to SetModule() for " << reference.description().title(); + return; + } + + // Build up the GUI layout programmatically (manually). + + QTabWidget *documentationTabWidget = new QTabWidget(); + documentationTabWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + + QWidget *aboutWidget = new QWidget(); + QWidget *helpWidget = new QWidget(); + + QTextBrowser *aboutBrowser = new QTextBrowser(aboutWidget); + aboutBrowser->setReadOnly(true); + aboutBrowser->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + + QTextBrowser *helpBrowser = new QTextBrowser(helpWidget); + helpBrowser->setReadOnly(true); + helpBrowser->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + + QHBoxLayout *aboutLayout = new QHBoxLayout(aboutWidget); + aboutLayout->addWidget(aboutBrowser); + aboutLayout->setContentsMargins(0,0,0,0); + aboutLayout->setSpacing(0); + + QHBoxLayout *helpLayout = new QHBoxLayout(helpWidget); + helpLayout->addWidget(helpBrowser); + helpLayout->setContentsMargins(0,0,0,0); + helpLayout->setSpacing(0); + + documentationTabWidget->addTab(aboutWidget, "About"); + documentationTabWidget->addTab(helpWidget, "Help"); + + QObject* guiHandle = m_ModuleFrontEnd->guiHandle(); + QWidget* generatedGuiWidgets = qobject_cast<QWidget*>(guiHandle); + + QWidget *topLevelWidget = new QWidget(); + QGridLayout *topLevelLayout = new QGridLayout(topLevelWidget); + + topLevelLayout->setContentsMargins(0,0,0,0); + topLevelLayout->setSpacing(0); + topLevelLayout->addWidget(documentationTabWidget, 0, 0); + topLevelLayout->setRowStretch(0, 1); + topLevelLayout->addWidget(generatedGuiWidgets, 1, 0); + topLevelLayout->setRowStretch(1, 10); + + ctkCmdLineModuleDescription description = reference.description(); + + QString helpString = ""; + + if (!description.title().isEmpty()) + { + QString titleHtml = "<h1>" + description.title() + "</h1>"; + helpString += titleHtml; + } + + if (!description.description().isEmpty()) + { + QString descriptionHtml = "<p>" + description.description() + "</p>"; + helpString += descriptionHtml; + } + + if (!description.documentationURL().isEmpty()) + { + QString docUrlHtml = "<p>For more information please see <a href=\"" + description.documentationURL() \ + + "\">the online documentation</a>.</p>"; + helpString += docUrlHtml; + } + + QString aboutString = ""; + + if (!description.title().isEmpty()) + { + QString titleHtml = "<h1>" + description.title() + "</h1>"; + aboutString += titleHtml; + } + + if (!description.contributor().isEmpty()) + { + QString contributorHtml = "<h2>Contributed By</h2><p>" + description.contributor() + "</p>"; + aboutString += contributorHtml; + } + + if (!description.license().isEmpty()) + { + QString licenseHtml = "<h2>License</h2><p>" + description.license() + "</p>"; + aboutString += licenseHtml; + } + + if (!description.acknowledgements().isEmpty()) + { + QString acknowledgementsHtml = "<h2>Acknowledgements</h2><p>" + description.acknowledgements() + "</p>"; + aboutString += acknowledgementsHtml; + } + + helpBrowser->clear(); + helpBrowser->setHtml(helpString); + aboutBrowser->clear(); + aboutBrowser->setHtml(aboutString); + + // So, we put the new GUI into the layout. + m_Layout->insertWidget(0, topLevelWidget); + + // And configure a few other niceties. + m_UI->m_ProgressTitle->setText(description.title()); + m_UI->m_ConsoleGroupBox->setCollapsed(true); + m_UI->m_ParametersGroupBox->setCollapsed(false); +} + + +//----------------------------------------------------------------------------- +QString QmitkCmdLineModuleProgressWidget::GetFullName() const +{ + assert(m_ModuleFrontEnd); + + ctkCmdLineModuleDescription description = m_ModuleFrontEnd->moduleReference().description(); + QString fullName = description.category() + "." + description.title(); + + return fullName; +} + + +//----------------------------------------------------------------------------- +bool QmitkCmdLineModuleProgressWidget::IsStarted() const +{ + bool isStarted = false; + if (m_FutureWatcher != NULL && m_FutureWatcher->isStarted()) + { + isStarted = true; + } + return isStarted; +} + + +//----------------------------------------------------------------------------- +void QmitkCmdLineModuleProgressWidget::Reset() +{ + assert(m_ModuleFrontEnd); + + m_ModuleFrontEnd->resetValues(); +} + + +//----------------------------------------------------------------------------- +void QmitkCmdLineModuleProgressWidget::Run() +{ + assert(m_ModuleManager); + assert(m_ModuleFrontEnd); + + m_OutputDataToLoad.clear(); + + ctkCmdLineModuleReference reference = m_ModuleFrontEnd->moduleReference(); + ctkCmdLineModuleDescription description = reference.description(); + + QString message = "Saving image data to temporary storage..."; + this->PublishMessage(message); + + // Sanity check we have actually specified some input: + QString parameterName; + QList<ctkCmdLineModuleParameter> parameters; + + // For each input image, write a temporary file as a Nifti image, + // and then save the full path name back on the parameter. + parameters = m_ModuleFrontEnd->parameters("image", ctkCmdLineModuleFrontend::Input); + foreach (ctkCmdLineModuleParameter parameter, parameters) + { + parameterName = parameter.name(); + + QVariant tmp = m_ModuleFrontEnd->value(parameterName, ctkCmdLineModuleFrontend::UserRole); + mitk::DataNode::Pointer node = tmp.value<mitk::DataNode::Pointer>(); + + if (node.IsNotNull()) + { + mitk::Image* image = dynamic_cast<mitk::Image*>(node->GetData()); + if (image != NULL) + { + QString name = QString::fromStdString(node->GetName()); + int pid = QCoreApplication::applicationPid(); + int randomInt = qrand() % 1000000; + + QString fileName = m_TemporaryDirectoryName + "/" + name + QString::number(pid) + "." + QString::number(randomInt) + ".nii"; + + message = "Saving " + fileName; + this->PublishMessage(message); + + std::string tmpFN = CommonFunctionality::SaveImage(image, fileName.toStdString().c_str()); + QString temporaryStorageFileName = QString::fromStdString(tmpFN); + + m_TemporaryFileNames.push_back(temporaryStorageFileName); + m_ModuleFrontEnd->setValue(parameterName, temporaryStorageFileName); + + message = "Saved " + temporaryStorageFileName; + this->PublishMessage(message); + } // end if image + } // end if node + } // end foreach input image + + // For each output image or file, store the filename, so we can auto-load it once the process finishes. + parameters = m_ModuleFrontEnd->parameters("image", ctkCmdLineModuleFrontend::Output); + parameters << m_ModuleFrontEnd->parameters("file", ctkCmdLineModuleFrontend::Output); + + foreach (ctkCmdLineModuleParameter parameter, parameters) + { + parameterName = parameter.name(); + QString outputFileName = m_ModuleFrontEnd->value(parameterName).toString(); + + if (!outputFileName.isEmpty()) + { + m_OutputDataToLoad.push_back(outputFileName); + + message = "Command Line Module ... Registered " + outputFileName + " to auto load upon completion."; + this->PublishMessage(message); + } + } + + // Now we run stuff. + message = "starting."; + this->PublishMessage(message); + + if (m_FutureWatcher == NULL) + { + m_FutureWatcher = new ctkCmdLineModuleFutureWatcher(); + + connect(m_FutureWatcher, SIGNAL(started()), SLOT(OnModuleStarted())); + connect(m_FutureWatcher, SIGNAL(canceled()), SLOT(OnModuleCanceled())); + connect(m_FutureWatcher, SIGNAL(finished()), SLOT(OnModuleFinished())); + connect(m_FutureWatcher, SIGNAL(resumed()), SLOT(OnModuleResumed())); + connect(m_FutureWatcher, SIGNAL(progressRangeChanged(int,int)), SLOT(OnModuleProgressRangeChanged(int,int))); + connect(m_FutureWatcher, SIGNAL(progressTextChanged(QString)), SLOT(OnModuleProgressTextChanged(QString))); + connect(m_FutureWatcher, SIGNAL(progressValueChanged(int)), SLOT(OnModuleProgressValueChanged(int))); + + connect(m_UI->m_CancelButton, SIGNAL(clicked()), m_FutureWatcher, SLOT(cancel())); + connect(m_UI->m_PauseButton, SIGNAL(toggled(bool)), this, SLOT(OnPauseButtonToggled(bool))); + + } + ctkCmdLineModuleFuture future = m_ModuleManager->run(m_ModuleFrontEnd); + m_FutureWatcher->setFuture(future); + + m_UI->m_PauseButton->setEnabled(future.canPause()); + m_UI->m_CancelButton->setEnabled(future.canCancel()); + m_UI->m_RemoveButton->setEnabled(!future.isRunning()); + + // Configure some other niceties. + m_UI->m_ParametersGroupBox->setCollapsed(true); + m_UI->m_ConsoleGroupBox->setCollapsed(true); + + // Lock parameters, as once the module is running the user can't change them. + m_Layout->itemAt(0)->widget()->setEnabled(false); + + // Give some immediate indication that we are running. + m_UI->m_ProgressTitle->setText(description.title() + ": running"); +} diff --git a/Plugins/org.mitk.gui.qt.cli/src/internal/QmitkCmdLineModuleProgressWidget.h b/Plugins/org.mitk.gui.qt.cli/src/internal/QmitkCmdLineModuleProgressWidget.h new file mode 100644 index 0000000000..9d649a9de6 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.cli/src/internal/QmitkCmdLineModuleProgressWidget.h @@ -0,0 +1,201 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) University College London (UCL). +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QMITKCMDLINEMODULEPROGRESSWIDGET_H +#define QMITKCMDLINEMODULEPROGRESSWIDGET_H + +#include <QWidget> +#include <QTimer> +#include <ctkCmdLineModuleFutureWatcher.h> +#include <ctkCmdLineModuleReference.h> + +class ctkCmdLineModuleManager; +class ctkCmdLineModuleFrontend; +class ctkCmdLineModuleFuture; +class QmitkCmdLineModuleFactoryGui; +class QVBoxLayout; + +namespace Ui { +class QmitkCmdLineModuleProgressWidget; +} + +namespace mitk { +class DataStorage; +} + +/** + * \class QmitkCmdLineModuleProgressWidget + * \brief Based on ctkCmdLineModuleExplorerProgressWidget, implements a progress widget + * with console output, and space for storing the GUI widgets. + * \author Matt Clarkson (m.clarkson@ucl.ac.uk) + * \ingroup org_mitk_gui_qt_cli_internal + * \sa ctkCmdLineModuleExplorerProgressWidget + */ +class QmitkCmdLineModuleProgressWidget : public QWidget +{ + Q_OBJECT + +public: + + QmitkCmdLineModuleProgressWidget(QWidget *parent = 0); + ~QmitkCmdLineModuleProgressWidget(); + + /** + * \brief Sets the manager on this object, and must be called immediately + * after construction, before using the widget. + */ + void SetManager(ctkCmdLineModuleManager* manager); + + /** + * \brief Sets the DataStorage on this object, and must be called immediately + * after construction, before using the widget. + */ + void SetDataStorage(mitk::DataStorage* dataStorage); + + /** + * \brief Sets the Temporary Directory on this widget, and must be called + * immediately after construction, before using the widget. + */ + void SetTemporaryDirectory(const QString& directoryName); + + /** + * \brief Tells this widget, which module it is pertaining to, which is looked up via the ModuleManager. + * \param reference + */ + void SetModule(const ctkCmdLineModuleReference& reference); + + /** + * \brief Returns <category>.<title>, derived from the ctkCmdLineModuleReference and + * hence from the ctkCmdLineModuleDescription. + */ + QString GetFullName() const; + + /** + * \brief Called from CommandLineModulesView to see if this job has started or not, + * as it affects the decision on when to create new widgets. + */ + bool IsStarted() const; + + /** + * \brief Resets this widget to the default parameters specified in the + * command line modules XML file. + */ + void Reset(); + + /** + * \brief Runs the module that this widget is currently referring to. + */ + void Run(); + +Q_SIGNALS: + + // These signals so that container classes such as CommandLineModuleView + // can keep track of how many modules are running simultaneously. + + void started(); // emmitted when the module is started. + void finished(); // emmitted when the module is completely finished. + +private Q_SLOTS: + + void OnCheckModulePaused(); + + void OnPauseButtonToggled(bool toggled); + void OnRemoveButtonClicked(); + + void OnModuleStarted(); + void OnModuleCanceled(); + void OnModuleFinished(); + void OnModuleResumed(); + void OnModuleProgressRangeChanged(int progressMin, int progressMax); + void OnModuleProgressTextChanged(const QString& progressText); + void OnModuleProgressValueChanged(int progressValue); + +private: + + /** + * \brief Used to write output to the console widget, and also to qDebug(). + */ + void PublishMessage(const QString& message); + + /** + * \brief Destroys any images listed in m_TemporaryFileNames. + */ + void ClearUpTemporaryFiles(); + + /** + * \brief Loads any data listed in m_OutputDataToLoad into the m_DataStorage. + */ + void LoadOutputData(); + + /** + * \brief Utility method to look up the title from the description. + */ + QString GetTitle(); + + /** + * \brief This must be injected before the Widget is used. + */ + ctkCmdLineModuleManager *m_ModuleManager; + + /** + * \brief This must be injected before the Widget is used. + */ + mitk::DataStorage *m_DataStorage; + + /** + * \brief This must be injected before the Widget is used. + */ + QString m_TemporaryDirectoryName; + + /** + * \brief We instantiate the main widgets from this .ui file. + */ + Ui::QmitkCmdLineModuleProgressWidget *m_UI; + + /** + * \brief The m_ParametersGroupBox needs a layout. + */ + QVBoxLayout *m_Layout; + + /** + * \brief The ctkCmdLineModuleFrontend is created by the QmitkCmdLineModuleFactoryGui. + */ + ctkCmdLineModuleFrontend *m_ModuleFrontEnd; + + /** + * \brief Main object to keep track of a running command line module. + */ + ctkCmdLineModuleFutureWatcher *m_FutureWatcher; + + /** + * \brief Due to Qt bug 12152, we use a timer to correctly check for a paused module. + */ + QTimer m_PollPauseTimer; + + /** + * \brief We store a list of temporary file names that are saved to disk before + * launching a command line app, and then must be cleared up when the command line + * app successfully finishes. + */ + QStringList m_TemporaryFileNames; + + /** + * \brief We store a list of output images, so that on successful completion of + * the command line module, we automatically load the output data into the mitk::DataStorage. + */ + QStringList m_OutputDataToLoad; +}; + +#endif // QMITKCMDLINEMODULEPROGRESSWIDGET_H diff --git a/Plugins/org.mitk.gui.qt.cli/src/internal/QmitkCmdLineModuleProgressWidget.ui b/Plugins/org.mitk.gui.qt.cli/src/internal/QmitkCmdLineModuleProgressWidget.ui new file mode 100644 index 0000000000..387eaafb35 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.cli/src/internal/QmitkCmdLineModuleProgressWidget.ui @@ -0,0 +1,144 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>QmitkCmdLineModuleProgressWidget</class> + <widget class="QWidget" name="QmitkCmdLineModuleProgressWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>593</width> + <height>390</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QFrame" name="m_Frame"> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="m_ProgressTitle"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QProgressBar" name="m_ProgressBar"> + <property name="value"> + <number>0</number> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="m_PauseButton"> + <property name="text"> + <string>...</string> + </property> + <property name="icon"> + <iconset> + <normaloff>:/CommandLineModulesResources/pause.png</normaloff>:/CommandLineModulesResources/pause.png</iconset> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="autoRaise"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="m_CancelButton"> + <property name="text"> + <string>...</string> + </property> + <property name="icon"> + <iconset> + <normaloff>:/CommandLineModulesResources/stop.png</normaloff>:/CommandLineModulesResources/stop.png</iconset> + </property> + <property name="autoRaise"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="m_RemoveButton"> + <property name="text"> + <string>Remove</string> + </property> + <property name="autoRaise"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="ctkCollapsibleGroupBox" name="m_ParametersGroupBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Parameters</string> + </property> + </widget> + </item> + <item> + <widget class="ctkCollapsibleGroupBox" name="m_ConsoleGroupBox"> + <property name="title"> + <string>Console</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QPlainTextEdit" name="m_Console"/> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="m_VerticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>17</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>ctkCollapsibleGroupBox</class> + <extends>QGroupBox</extends> + <header>ctkCollapsibleGroupBox.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui>