diff --git a/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesPreferencesPage.cpp b/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesPreferencesPage.cpp index fc0bb89003..1255a035e6 100644 --- a/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesPreferencesPage.cpp +++ b/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesPreferencesPage.cpp @@ -1,194 +1,203 @@ /*=================================================================== 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 "CommandLineModulesPreferencesPage.h" #include "CommandLineModulesViewConstants.h" #include #include #include #include #include #include #include #include #include #include #include #include "QmitkDirectoryListWidget.h" #include "QmitkFileListWidget.h" //----------------------------------------------------------------------------- CommandLineModulesPreferencesPage::CommandLineModulesPreferencesPage() : m_MainControl(0) +, m_OutputDirectory(0) , m_TemporaryDirectory(0) , m_ModulesDirectories(0) , m_ModulesFiles(0) , m_LoadFromHomeDir(0) , m_LoadFromCurrentDir(0) , m_LoadFromApplicationDir(0) , m_LoadFromAutoLoadPathDir(0) , m_ValidationMode(0) , m_MaximumNumberProcesses(0) , m_CLIPreferencesNode(0) { } //----------------------------------------------------------------------------- CommandLineModulesPreferencesPage::~CommandLineModulesPreferencesPage() { } //----------------------------------------------------------------------------- void CommandLineModulesPreferencesPage::Init(berry::IWorkbench::Pointer ) { } //----------------------------------------------------------------------------- void CommandLineModulesPreferencesPage::CreateQtControl(QWidget* parent) { berry::IPreferencesService::Pointer prefService = berry::Platform::GetServiceRegistry() .GetServiceById(berry::IPreferencesService::ID); std::string id = "/" + CommandLineModulesViewConstants::VIEW_ID; m_CLIPreferencesNode = prefService->GetSystemPreferences()->Node(id); m_MainControl = new QWidget(parent); m_TemporaryDirectory = new ctkDirectoryButton(m_MainControl); m_TemporaryDirectory->setCaption("Select a directory for temporary files ... "); + m_OutputDirectory = new ctkDirectoryButton(m_MainControl); + m_OutputDirectory->setCaption("Select a default directory for output files ... "); + m_ModulesDirectories = new QmitkDirectoryListWidget(m_MainControl); m_ModulesDirectories->m_Label->setText("Select directories to scan:"); m_ModulesFiles = new QmitkFileListWidget(m_MainControl); m_ModulesFiles->m_Label->setText("Select additional executables:"); m_DebugOutput = new QCheckBox(m_MainControl); m_LoadFromApplicationDir = new QCheckBox(m_MainControl); m_LoadFromAutoLoadPathDir = new QCheckBox(m_MainControl); m_LoadFromHomeDir = new QCheckBox(m_MainControl); m_LoadFromCurrentDir = new QCheckBox(m_MainControl); m_ValidationMode = new QComboBox(m_MainControl); m_ValidationMode->addItem("strict", ctkCmdLineModuleManager::STRICT_VALIDATION); m_ValidationMode->addItem("none", ctkCmdLineModuleManager::SKIP_VALIDATION); m_ValidationMode->addItem("weak", ctkCmdLineModuleManager::WEAK_VALIDATION); m_ValidationMode->setCurrentIndex(0); m_MaximumNumberProcesses = new QSpinBox(m_MainControl); m_MaximumNumberProcesses->setMinimum(1); m_MaximumNumberProcesses->setMaximum(1000000); QFormLayout *formLayout = new QFormLayout; formLayout->addRow("show debug output:", m_DebugOutput); formLayout->addRow("XML validation mode:", m_ValidationMode); formLayout->addRow("max. concurrent processes:", m_MaximumNumberProcesses); formLayout->addRow("scan home directory:", m_LoadFromHomeDir); formLayout->addRow("scan current directory:", m_LoadFromCurrentDir); formLayout->addRow("scan installation directory:", m_LoadFromApplicationDir); formLayout->addRow("scan CTK_MODULE_LOAD_PATH:", m_LoadFromAutoLoadPathDir); formLayout->addRow("additional module directories:", m_ModulesDirectories); formLayout->addRow("additional modules:", m_ModulesFiles); formLayout->addRow("temporary directory:", m_TemporaryDirectory); + formLayout->addRow("default output directory:", m_OutputDirectory); m_MainControl->setLayout(formLayout); this->Update(); } //----------------------------------------------------------------------------- QWidget* CommandLineModulesPreferencesPage::GetQtControl() const { return m_MainControl; } //----------------------------------------------------------------------------- std::string CommandLineModulesPreferencesPage::ConvertToStdString(const QStringList& list) { std::string output; for (int i = 0; i < list.count(); i++) { QString path = list[i] + ";"; output += path.toStdString(); } return output; } //----------------------------------------------------------------------------- bool CommandLineModulesPreferencesPage::PerformOk() { m_CLIPreferencesNode->Put(CommandLineModulesViewConstants::TEMPORARY_DIRECTORY_NODE_NAME, m_TemporaryDirectory->directory().toStdString()); + m_CLIPreferencesNode->Put(CommandLineModulesViewConstants::OUTPUT_DIRECTORY_NODE_NAME, m_OutputDirectory->directory().toStdString()); m_CLIPreferencesNode->PutBool(CommandLineModulesViewConstants::DEBUG_OUTPUT_NODE_NAME, m_DebugOutput->isChecked()); m_CLIPreferencesNode->PutBool(CommandLineModulesViewConstants::LOAD_FROM_APPLICATION_DIR, m_LoadFromApplicationDir->isChecked()); m_CLIPreferencesNode->PutBool(CommandLineModulesViewConstants::LOAD_FROM_HOME_DIR, m_LoadFromHomeDir->isChecked()); m_CLIPreferencesNode->PutBool(CommandLineModulesViewConstants::LOAD_FROM_CURRENT_DIR, m_LoadFromCurrentDir->isChecked()); m_CLIPreferencesNode->PutBool(CommandLineModulesViewConstants::LOAD_FROM_AUTO_LOAD_DIR, m_LoadFromAutoLoadPathDir->isChecked()); std::string paths = this->ConvertToStdString(m_ModulesDirectories->directories()); m_CLIPreferencesNode->Put(CommandLineModulesViewConstants::MODULE_DIRECTORIES_NODE_NAME, paths); std::string modules = this->ConvertToStdString(m_ModulesFiles->files()); m_CLIPreferencesNode->Put(CommandLineModulesViewConstants::MODULE_FILES_NODE_NAME, modules); int currentValidationMode = m_CLIPreferencesNode->GetInt(CommandLineModulesViewConstants::XML_VALIDATION_MODE, 0); if (currentValidationMode != m_ValidationMode->currentIndex()) { QMessageBox msgBox; msgBox.setText("Changing the XML validation mode will require a restart of the application."); msgBox.exec(); } m_CLIPreferencesNode->PutInt(CommandLineModulesViewConstants::XML_VALIDATION_MODE, m_ValidationMode->currentIndex()); m_CLIPreferencesNode->PutInt(CommandLineModulesViewConstants::MAX_CONCURRENT, m_MaximumNumberProcesses->value()); return true; } //----------------------------------------------------------------------------- void CommandLineModulesPreferencesPage::PerformCancel() { } //----------------------------------------------------------------------------- void CommandLineModulesPreferencesPage::Update() { QString fallbackTmpDir = QDir::tempPath(); m_TemporaryDirectory->setDirectory(QString::fromStdString(m_CLIPreferencesNode->Get(CommandLineModulesViewConstants::TEMPORARY_DIRECTORY_NODE_NAME, fallbackTmpDir.toStdString()))); + QString fallbackOutputDir = QDir::homePath(); + m_OutputDirectory->setDirectory(QString::fromStdString(m_CLIPreferencesNode->Get(CommandLineModulesViewConstants::OUTPUT_DIRECTORY_NODE_NAME, fallbackOutputDir.toStdString()))); + m_DebugOutput->setChecked(m_CLIPreferencesNode->GetBool(CommandLineModulesViewConstants::DEBUG_OUTPUT_NODE_NAME, false)); m_LoadFromApplicationDir->setChecked(m_CLIPreferencesNode->GetBool(CommandLineModulesViewConstants::LOAD_FROM_APPLICATION_DIR, false)); m_LoadFromHomeDir->setChecked(m_CLIPreferencesNode->GetBool(CommandLineModulesViewConstants::LOAD_FROM_HOME_DIR, false)); m_LoadFromCurrentDir->setChecked(m_CLIPreferencesNode->GetBool(CommandLineModulesViewConstants::LOAD_FROM_CURRENT_DIR, false)); m_LoadFromAutoLoadPathDir->setChecked(m_CLIPreferencesNode->GetBool(CommandLineModulesViewConstants::LOAD_FROM_AUTO_LOAD_DIR, false)); QString paths = QString::fromStdString(m_CLIPreferencesNode->Get(CommandLineModulesViewConstants::MODULE_DIRECTORIES_NODE_NAME, "")); QStringList directoryList = paths.split(";", QString::SkipEmptyParts); m_ModulesDirectories->setDirectories(directoryList); QString files = QString::fromStdString(m_CLIPreferencesNode->Get(CommandLineModulesViewConstants::MODULE_FILES_NODE_NAME, "")); QStringList fileList = files.split(";", QString::SkipEmptyParts); m_ModulesFiles->setFiles(fileList); m_ValidationMode->setCurrentIndex(m_CLIPreferencesNode->GetInt(CommandLineModulesViewConstants::XML_VALIDATION_MODE, 0)); m_MaximumNumberProcesses->setValue(m_CLIPreferencesNode->GetInt(CommandLineModulesViewConstants::MAX_CONCURRENT, 4)); } diff --git a/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesPreferencesPage.h b/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesPreferencesPage.h index 8f930f77e0..f8f5fc2af2 100644 --- a/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesPreferencesPage.h +++ b/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesPreferencesPage.h @@ -1,102 +1,103 @@ /*=================================================================== 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 COMMANDLINEMODULESPREFERENCESPAGE_H #define COMMANDLINEMODULESPREFERENCESPAGE_H #include "berryIQtPreferencePage.h" #include "berryIPreferences.h" #include class QWidget; class QCheckBox; class QComboBox; class QSpinBox; class QmitkDirectoryListWidget; class QmitkFileListWidget; class ctkDirectoryButton; /** * \class CommandLineModulesPreferencesPage * \brief Preference page for CommandLineModulesView * \author Matt Clarkson (m.clarkson@ucl.ac.uk) * \ingroup org_mitk_gui_qt_cli_internal */ class CommandLineModulesPreferencesPage : public QObject, public berry::IQtPreferencePage { Q_OBJECT Q_INTERFACES(berry::IPreferencePage) public: CommandLineModulesPreferencesPage(); ~CommandLineModulesPreferencesPage(); /** * \brief Called by framework to initialise this preference page, but currently does nothing. * \param workbench The workbench. */ void Init(berry::IWorkbench::Pointer workbench); /** * \brief Called by framework to create the GUI, and connect signals and slots. * \param widget The Qt widget that acts as parent to all GUI components, as this class itself is not derived from QWidget. */ void CreateQtControl(QWidget* widget); /** * \brief Required by framework to get hold of the GUI. * \return QWidget* the top most QWidget for the GUI. */ QWidget* GetQtControl() const; /** * \see IPreferencePage::PerformOk */ virtual bool PerformOk(); /** * \see IPreferencePage::PerformCancel */ virtual void PerformCancel(); /** * \see IPreferencePage::Update */ virtual void Update(); public slots: protected: QWidget *m_MainControl; QCheckBox *m_DebugOutput; + ctkDirectoryButton *m_OutputDirectory; ctkDirectoryButton *m_TemporaryDirectory; QmitkDirectoryListWidget *m_ModulesDirectories; QmitkFileListWidget *m_ModulesFiles; QCheckBox *m_LoadFromHomeDir; QCheckBox *m_LoadFromCurrentDir; QCheckBox *m_LoadFromApplicationDir; QCheckBox *m_LoadFromAutoLoadPathDir; QComboBox *m_ValidationMode; QSpinBox *m_MaximumNumberProcesses; berry::IPreferences::Pointer m_CLIPreferencesNode; private: std::string ConvertToStdString(const QStringList& list); }; #endif // COMMANDLINEMODULESPREFERENCESPAGE_H 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 31e8c70630..cf28a49a27 100644 --- a/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesView.cpp +++ b/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesView.cpp @@ -1,432 +1,467 @@ /*=================================================================== 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 "QmitkCmdLineModuleGui.h" #include "QmitkCmdLineModuleProgressWidget.h" // Qt #include #include #include #include #include #include #include // CTK #include #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_DirectoryWatcher(NULL) , m_TemporaryDirectoryName("") , m_MaximumConcurrentProcesses(4) , m_CurrentlyRunningProcesses(0) , m_DebugOutput(false) { } //----------------------------------------------------------------------------- CommandLineModulesView::~CommandLineModulesView() { if (m_ModuleManager != NULL) { delete m_ModuleManager; } if (m_ModuleBackend != NULL) { delete m_ModuleBackend; } if (m_DirectoryWatcher != NULL) { delete m_DirectoryWatcher; } if (m_Layout != NULL) { delete m_Layout; } for (int i = 0; i < m_ListOfModules.size(); i++) { delete m_ListOfModules[i]; } } //----------------------------------------------------------------------------- void CommandLineModulesView::SetFocus() { this->m_Controls->m_ComboBox->setFocus(); } //----------------------------------------------------------------------------- void CommandLineModulesView::CreateQtPartControl( QWidget *parent ) { m_Parent = parent; if (!m_Controls) { // 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_RunningWidgets); 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(); this->RetrieveAndStoreValidationMode(); // Start to create the command line module infrastructure. m_ModuleBackend = new ctkCmdLineModuleBackendLocalProcess(); m_ModuleManager = new ctkCmdLineModuleManager(m_ValidationMode, 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(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*))); connect(this->m_Controls->m_TabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(OnTabCloseRequested(int))); this->UpdateRunButtonEnabledStatus(); } } //----------------------------------------------------------------------------- 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::RetrieveAndStoreValidationMode() { berry::IBerryPreferences::Pointer prefs = this->RetrievePreferences(); int value = prefs->GetInt(CommandLineModulesViewConstants::XML_VALIDATION_MODE, 0); if (value == 0) { m_ValidationMode = ctkCmdLineModuleManager::STRICT_VALIDATION; } else if (value == 1) { m_ValidationMode = ctkCmdLineModuleManager::SKIP_VALIDATION; } else { m_ValidationMode = ctkCmdLineModuleManager::WEAK_VALIDATION; } } //----------------------------------------------------------------------------- void CommandLineModulesView::RetrieveAndStorePreferenceValues() { berry::IBerryPreferences::Pointer prefs = this->RetrievePreferences(); + QString fallbackHomeDir = QDir::homePath(); + m_OutputDirectoryName = QString::fromStdString( + prefs->Get(CommandLineModulesViewConstants::OUTPUT_DIRECTORY_NODE_NAME, fallbackHomeDir.toStdString())); + m_MaximumConcurrentProcesses = prefs->GetInt(CommandLineModulesViewConstants::MAX_CONCURRENT, 4); // 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->RetrieveAndStoreValidationMode(); this->RetrieveAndStorePreferenceValues(); } //----------------------------------------------------------------------------- ctkCmdLineModuleReference CommandLineModulesView::GetReferenceByFullName(QString fullName) { ctkCmdLineModuleReference result; QList references = this->m_ModuleManager->moduleReferences(); ctkCmdLineModuleReference ref; foreach(ref, references) { QString name = ref.description().categoryDotTitle(); if (name == fullName) { result = ref; } } return result; } //----------------------------------------------------------------------------- void CommandLineModulesView::OnActionChanged(QAction* action) { QString fullName = action->objectName(); ctkCmdLineModuleReference ref = this->GetReferenceByFullName(fullName); // ref should never be invalid, as the menu was generated from each ctkCmdLineModuleReference. // But just to be sure ... if invalid, don't do anything. if (ref) { // Check if we already have the reference. int tabIndex = -1; for (int i = 0; i < m_ListOfModules.size(); i++) { ctkCmdLineModuleReference tabsReference = m_ListOfModules[i]->moduleReference(); if (ref.location() == tabsReference.location()) { tabIndex = i; break; } } // i.e. we found a matching tab, so just switch to it. if (tabIndex != -1) { m_Controls->m_TabWidget->setCurrentIndex(tabIndex); } else // i.e. we did not find a matching tab { // In this case, we need to create a new tab, and give // it a GUI for the user to setup the parameters with. QmitkCmdLineModuleFactoryGui factory(this->GetDataStorage()); ctkCmdLineModuleFrontend *frontEnd = factory.create(ref); QmitkCmdLineModuleGui *theGui = dynamic_cast(frontEnd); // Add to list and tab wigdget m_ListOfModules.push_back(frontEnd); int tabIndex = m_Controls->m_TabWidget->addTab(theGui->getGui(), ref.description().title()); m_Controls->m_TabWidget->setTabToolTip(tabIndex, ref.description().title() + ":" + ref.xmlValidationErrorString()); + + // Here lies a small caveat. + // + // The XML may specify a default output file name. + // However, this will probably have no file path, so we should probably add one. + // Otherwise you will likely be trying to write in the application installation folder + // eg. C:/Program Files (Windows) or /Applications/ (Mac) + // + // Also, we may find that 3rd party apps crash when they can't write. + // So lets plan for the worst and hope for the best :-) + + QString parameterName; + QList parameters; + parameters = frontEnd->parameters("image", ctkCmdLineModuleFrontend::Output); + parameters << frontEnd->parameters("file", ctkCmdLineModuleFrontend::Output); + parameters << frontEnd->parameters("geometry", ctkCmdLineModuleFrontend::Output); + foreach (ctkCmdLineModuleParameter parameter, parameters) + { + parameterName = parameter.name(); + QString outputFileName = frontEnd->value(parameterName, ctkCmdLineModuleFrontend::DisplayRole).toString(); + QFileInfo outputFileInfo(outputFileName); + + if (outputFileInfo.absoluteFilePath() != outputFileName) + { + QDir defaultOutputDir(m_OutputDirectoryName); + QFileInfo replacementFileInfo(defaultOutputDir, outputFileName); + frontEnd->setValue(parameterName, replacementFileInfo.absoluteFilePath(), ctkCmdLineModuleFrontend::DisplayRole); + } + } } } } //----------------------------------------------------------------------------- void CommandLineModulesView::OnTabCloseRequested(int tabNumber) { ctkCmdLineModuleFrontend *frontEnd = m_ListOfModules[tabNumber]; m_Controls->m_TabWidget->removeTab(tabNumber); m_ListOfModules.removeAt(tabNumber); delete frontEnd; } //----------------------------------------------------------------------------- void CommandLineModulesView::AskUserToSelectAModule() const { QMessageBox msgBox; msgBox.setText("Please select a module!"); msgBox.setIcon(QMessageBox::Warning); msgBox.exec(); } //----------------------------------------------------------------------------- void CommandLineModulesView::OnRestoreButtonPressed() { int tabNumber = m_Controls->m_TabWidget->currentIndex(); if (tabNumber >= 0) { ctkCmdLineModuleFrontend *frontEnd = m_ListOfModules[tabNumber]; frontEnd->resetValues(); } else { this->AskUserToSelectAModule(); } } //----------------------------------------------------------------------------- void CommandLineModulesView::OnRunButtonPressed() { int tabNumber = m_Controls->m_TabWidget->currentIndex(); if (tabNumber >= 0) { // 1. Create a new QmitkCmdLineModuleProgressWidget to represent the running widget. QmitkCmdLineModuleProgressWidget *widget = new QmitkCmdLineModuleProgressWidget(m_Controls->m_RunningWidgets); widget->SetDataStorage(this->GetDataStorage()); widget->SetManager(m_ModuleManager); widget->SetTemporaryDirectory(m_TemporaryDirectoryName); + widget->SetOutputDirectory(m_OutputDirectoryName); // 2. Create a new front end. QmitkCmdLineModuleFactoryGui factory(this->GetDataStorage()); ctkCmdLineModuleFrontend *frontEndOnCurrentTab = m_ListOfModules[tabNumber]; QmitkCmdLineModuleGui *frontEndGuiOnCurrentTab = dynamic_cast(frontEndOnCurrentTab); ctkCmdLineModuleReference currentTabFrontendReferences = frontEndGuiOnCurrentTab->moduleReference(); ctkCmdLineModuleFrontend *newFrontEnd = factory.create(currentTabFrontendReferences); QmitkCmdLineModuleGui *newFrontEndGui = dynamic_cast(newFrontEnd); widget->SetFrontend(newFrontEndGui); m_Layout->insertWidget(0, widget); // 3. Copy parameters. This MUST come after widget->SetFrontEnd newFrontEndGui->copyParameters(*frontEndGuiOnCurrentTab); newFrontEndGui->setParameterContainerEnabled(false); // 4. Connect widget signals to here, to count how many jobs running. connect(widget, SIGNAL(started()), this, SLOT(OnJobStarted())); connect(widget, SIGNAL(finished()), this, SLOT(OnJobFinished())); // 5. GO. widget->Run(); } else { this->AskUserToSelectAModule(); } } //----------------------------------------------------------------------------- void CommandLineModulesView::UpdateRunButtonEnabledStatus() { if (m_CurrentlyRunningProcesses >= m_MaximumConcurrentProcesses) { m_Controls->m_RunButton->setEnabled(false); } else { m_Controls->m_RunButton->setEnabled(true); } } //----------------------------------------------------------------------------- void CommandLineModulesView::OnJobStarted() { m_CurrentlyRunningProcesses++; this->UpdateRunButtonEnabledStatus(); } //----------------------------------------------------------------------------- void CommandLineModulesView::OnJobFinished() { m_CurrentlyRunningProcesses--; this->UpdateRunButtonEnabledStatus(); } 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 bc97082e6a..ee9e4d055b 100644 --- a/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesView.h +++ b/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesView.h @@ -1,220 +1,226 @@ /*=================================================================== 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 #include class ctkCmdLineModuleBackendLocalProcess; class ctkCmdLineModuleDirectoryWatcher; 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, * 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, if the XML specifies defaults. */ void OnRestoreButtonPressed(); /** * \brief Slot that is called when the Run button 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 ctkMenuCombo box. */ virtual void SetFocus(); private slots: /** * \brief Called when the user clicks to close a tab, and removes the front end from m_ListOfModules */ void OnTabCloseRequested(int tabNumber); /** * \brief Called from QmitkCmdLineModuleProgressWidget to indicate a job has started. */ void OnJobStarted(); /** * \brief Called from QmitkCmdLineModuleProgressWidget to indicate a job has finished. */ void OnJobFinished(); 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 on startup and by OnPreferencesChanged to set the validation mode, but will require a restart. */ void RetrieveAndStoreValidationMode(); /** * \brief Called to get hold of the actual preferences node. */ berry::IBerryPreferences::Pointer RetrievePreferences(); /** * \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 GetReferenceByFullName(QString fullName); /** * \brief Raises a message box asking the user to select a module first. */ void AskUserToSelectAModule() const; /** * \brief Enables or Disables the Run Button. */ void UpdateRunButtonEnabledStatus(); /** * \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. */ 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 ctkCmdLineModuleDirectoryWatcher maintains the list of directories * we are using to load modules, to provide automatic updates. */ ctkCmdLineModuleDirectoryWatcher *m_DirectoryWatcher; /** * \brief We store a temporary folder name, accessible via user preferences. */ QString m_TemporaryDirectoryName; + /** + * \brief We store an output folder name, accessible via user preferences for when + * the file specified in a default output path is not within a writable directory. + */ + QString m_OutputDirectoryName; + /** * \brief We store the validation mode, accessisble via user preferences. */ ctkCmdLineModuleManager::ValidationMode m_ValidationMode; /** * \brief We store the maximum number of concurrent processes, and disable the run button accordingly. */ int m_MaximumConcurrentProcesses; /** * \brief Counts the number of currently running processes. */ int m_CurrentlyRunningProcesses; /** * \brief Member variable, taken from preference page. */ bool m_DebugOutput; /** * \brief We keep a list of front ends to match the m_TabWidget. */ QList<ctkCmdLineModuleFrontend*> m_ListOfModules; }; #endif // CommandLineModulesView_h diff --git a/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesViewConstants.cpp b/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesViewConstants.cpp index 6eb516d861..9fd1c89b34 100644 --- a/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesViewConstants.cpp +++ b/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesViewConstants.cpp @@ -1,28 +1,29 @@ /*=================================================================== 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 "CommandLineModulesViewConstants.h" const std::string CommandLineModulesViewConstants::VIEW_ID = "org.mitk.gui.qt.cli"; const std::string CommandLineModulesViewConstants::TEMPORARY_DIRECTORY_NODE_NAME = "temporary directory"; +const std::string CommandLineModulesViewConstants::OUTPUT_DIRECTORY_NODE_NAME = "output directory"; const std::string CommandLineModulesViewConstants::MODULE_DIRECTORIES_NODE_NAME = "module directories"; const std::string CommandLineModulesViewConstants::MODULE_FILES_NODE_NAME = "module files"; const std::string CommandLineModulesViewConstants::DEBUG_OUTPUT_NODE_NAME = "debug output"; const std::string CommandLineModulesViewConstants::LOAD_FROM_APPLICATION_DIR = "load from application dir"; const std::string CommandLineModulesViewConstants::LOAD_FROM_HOME_DIR = "load from home dir"; const std::string CommandLineModulesViewConstants::LOAD_FROM_CURRENT_DIR = "load from current dir"; const std::string CommandLineModulesViewConstants::LOAD_FROM_AUTO_LOAD_DIR = "load from auto-load dir"; const std::string CommandLineModulesViewConstants::XML_VALIDATION_MODE = "xml validation mode"; const std::string CommandLineModulesViewConstants::MAX_CONCURRENT = "max concurrent processes"; diff --git a/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesViewConstants.h b/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesViewConstants.h index af1821d52f..d7ccec6969 100644 --- a/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesViewConstants.h +++ b/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesViewConstants.h @@ -1,91 +1,96 @@ /*=================================================================== 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 CommandLineModulesViewConstants_h #define CommandLineModulesViewConstants_h #include <QString> #include <string> /** * \class CommandLineModulesViewConstants * \brief Structure to define a namespace for constants used privately within this view. * \author Matt Clarkson (m.clarkson@ucl.ac.uk) * \ingroup org_mitk_gui_qt_cli_internal */ struct CommandLineModulesViewConstants { /** * \brief The name of the preferences node containing the temporary directory. */ static const std::string TEMPORARY_DIRECTORY_NODE_NAME; + /** + * \brief The name of the preferences node containing the output directory. + */ + static const std::string OUTPUT_DIRECTORY_NODE_NAME; + /** * \brief The name of the preferences node containing the list of directories to scan. */ static const std::string MODULE_DIRECTORIES_NODE_NAME; /** * \brief The name of the preferences node containing the additional files to add to the module list. */ static const std::string MODULE_FILES_NODE_NAME; /** * \brief The name of the preferences node containing whether we are producing debug output. */ static const std::string DEBUG_OUTPUT_NODE_NAME; /** * \brief The name of the preferences node containing a boolean describing whether * we are loading modules from the application directory. */ static const std::string LOAD_FROM_APPLICATION_DIR; /** * \brief The name of the preferences node containing a boolean describing whether * we are loading modules from the users home directory. */ static const std::string LOAD_FROM_HOME_DIR; /** * \brief The name of the preferences node containing a boolean describing whether * we are loading modules from the applications current working directory. */ static const std::string LOAD_FROM_CURRENT_DIR; /** * \brief The name of the preferences node containing a boolean describing whether * we are loading modules from the directory specified in CTK_MODULE_LOAD_PATH. */ static const std::string LOAD_FROM_AUTO_LOAD_DIR; /** * \brief The name of the preferences node containing the validation mode. */ static const std::string XML_VALIDATION_MODE; /** * \brief The name of the preferences node containing the maximum number of concurrent processes. */ static const std::string MAX_CONCURRENT; /** * \brief The View ID = org.mitk.gui.qt.cli, and should match that in plugin.xml. */ static const std::string VIEW_ID; }; #endif // CommandLineModulesViewConstants_h diff --git a/Plugins/org.mitk.gui.qt.cli/src/internal/QmitkCmdLineModuleGui.cpp b/Plugins/org.mitk.gui.qt.cli/src/internal/QmitkCmdLineModuleGui.cpp index 29d61b2fdd..367d83497f 100644 --- a/Plugins/org.mitk.gui.qt.cli/src/internal/QmitkCmdLineModuleGui.cpp +++ b/Plugins/org.mitk.gui.qt.cli/src/internal/QmitkCmdLineModuleGui.cpp @@ -1,273 +1,274 @@ /*=================================================================== 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 "QmitkCmdLineModuleGui.h" #include "QmitkUiLoader.h" #include <QVariant> #include <QIODevice> #include <QFile> #include <QScopedPointer> #include <QWidget> #include <QTextBrowser> #include <QVBoxLayout> #include <QmitkCustomVariants.h> #include <ctkCmdLineModuleXslTransform.h> #include <ctkCmdLineModuleParameter.h> #include <ctkCmdLineModuleDescription.h> #include <ctkCollapsibleGroupBox.h> #include "mitkDataStorage.h" //----------------------------------------------------------------------------- struct QmitkCmdLineModuleGuiPrivate { QmitkCmdLineModuleGuiPrivate(const mitk::DataStorage* dataStorage) : m_DataStorage(dataStorage), m_Loader(NULL), m_Transform(NULL), m_TopLevelWidget(NULL) { } const mitk::DataStorage* m_DataStorage; mutable QScopedPointer<QUiLoader> m_Loader; mutable QScopedPointer<ctkCmdLineModuleXslTransform> m_Transform; mutable QScopedPointer<QWidget> m_TopLevelWidget; }; //----------------------------------------------------------------------------- QmitkCmdLineModuleGui::QmitkCmdLineModuleGui(const mitk::DataStorage* dataStorage, const ctkCmdLineModuleReference& moduleRef) : ctkCmdLineModuleFrontendQtGui(moduleRef) , d(new QmitkCmdLineModuleGuiPrivate(dataStorage)) { qRegisterMetaType<mitk::DataNode::Pointer>(); } //----------------------------------------------------------------------------- QmitkCmdLineModuleGui::~QmitkCmdLineModuleGui() { } //----------------------------------------------------------------------------- QUiLoader* QmitkCmdLineModuleGui::uiLoader() const { // Here we are creating a QUiLoader locally, so when this method // is called, it overrides the one in the base class, so the base // class one is never constructed, and this one is constructed as // a replacement. if (d->m_Loader == NULL) { d->m_Loader.reset(new QmitkUiLoader(d->m_DataStorage)); } return d->m_Loader.data(); } //----------------------------------------------------------------------------- ctkCmdLineModuleXslTransform* QmitkCmdLineModuleGui::xslTransform() const { // This is a virtual getter, overriding the one in the base class. // However, we want to use the transform in the base class, and just append to it. // So we call the base class one, modify it by adding some stuff, and then return // the pointer to the one in the base class. ctkCmdLineModuleXslTransform *transform = ctkCmdLineModuleFrontendQtGui::xslTransform(); if (transform != NULL) { transform->bindVariable("imageInputWidget", QVariant(QString("QmitkDataStorageComboBoxWithSelectNone"))); transform->bindVariable("imageInputValueProperty", "currentValue"); + transform->bindVariable("imageInputSetProperty", ""); // Don't need this, as we are connected to DataStorage. } return transform; } //----------------------------------------------------------------------------- QVariant QmitkCmdLineModuleGui::value(const QString ¶meter, int role) const { if (role == UserRole) { ctkCmdLineModuleParameter param = this->moduleReference().description().parameter(parameter); if (param.channel() == "input" && param.tag() == "image") { return this->customValue(parameter, "SelectedNode"); } return QVariant(); } return ctkCmdLineModuleFrontendQtGui::value(parameter, role); } //----------------------------------------------------------------------------- void QmitkCmdLineModuleGui::setValue(const QString& parameter, const QVariant& value, int role) { if (role == UserRole) { ctkCmdLineModuleParameter param = this->moduleReference().description().parameter(parameter); if (param.channel() == "input" && param.tag() == "image") { this->setCustomValue(parameter, value, "SelectedNode"); } else { ctkCmdLineModuleFrontendQtGui::setValue(parameter, value, role); } } else { ctkCmdLineModuleFrontendQtGui::setValue(parameter, value, role); } } //----------------------------------------------------------------------------- QWidget* QmitkCmdLineModuleGui::getGui() { if (!d->m_TopLevelWidget) { // Construct additional widgets to contain full GUI. QWidget *aboutBoxContainerWidget = new QWidget(); ctkCollapsibleGroupBox *aboutBox = new ctkCollapsibleGroupBox(aboutBoxContainerWidget); aboutBox->setTitle("About"); QTextBrowser *aboutBrowser = new QTextBrowser(aboutBox); aboutBrowser->setReadOnly(true); aboutBrowser->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); aboutBrowser->setOpenExternalLinks(true); aboutBrowser->setOpenLinks(true); QVBoxLayout *aboutLayout = new QVBoxLayout(aboutBox); aboutLayout->addWidget(aboutBrowser); QVBoxLayout *aboutBoxContainerWidgetLayout = new QVBoxLayout(aboutBoxContainerWidget); aboutBoxContainerWidgetLayout->addWidget(aboutBox); QWidget *helpBoxContainerWidget = new QWidget(); ctkCollapsibleGroupBox *helpBox = new ctkCollapsibleGroupBox(); helpBox->setTitle("Help"); QTextBrowser *helpBrowser = new QTextBrowser(helpBox); helpBrowser->setReadOnly(true); helpBrowser->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); helpBrowser->setOpenExternalLinks(true); helpBrowser->setOpenLinks(true); QVBoxLayout *helpLayout = new QVBoxLayout(helpBox); helpLayout->addWidget(helpBrowser); QVBoxLayout *helpBoxContainerWidgetLayout = new QVBoxLayout(helpBoxContainerWidget); helpBoxContainerWidgetLayout->addWidget(helpBox); QObject* guiHandle = this->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(aboutBoxContainerWidget, 0, 0); topLevelLayout->addWidget(helpBoxContainerWidget, 1, 0); topLevelLayout->addWidget(generatedGuiWidgets, 2, 0); ctkCmdLineModuleDescription description = this->moduleReference().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() + "\">" + description.documentationURL() + "</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); helpBox->setCollapsed(true); aboutBrowser->clear(); aboutBrowser->setHtml(aboutString); aboutBox->setCollapsed(true); d->m_TopLevelWidget.reset(topLevelWidget); } return d->m_TopLevelWidget.data(); } //----------------------------------------------------------------------------- void QmitkCmdLineModuleGui::copyParameters(QmitkCmdLineModuleGui& another) { // This copies "display" parameter types. // See ctkCmdLineModuleFrontend::DisplayRole this->setValues(another.values()); // For custom types, we must manually copy the values. // In our case, we copy image types manually, to pass across the mitk::DataNode pointer. QList<ctkCmdLineModuleParameter> parameters = another.parameters("image", ctkCmdLineModuleFrontend::Input); foreach (ctkCmdLineModuleParameter parameter, parameters) { QString parameterName = parameter.name(); QVariant tmp = another.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) { this->setValue(parameterName, tmp, ctkCmdLineModuleFrontend::UserRole); } } } } diff --git a/Plugins/org.mitk.gui.qt.cli/src/internal/QmitkCmdLineModuleProgressWidget.cpp b/Plugins/org.mitk.gui.qt.cli/src/internal/QmitkCmdLineModuleProgressWidget.cpp index b8667b7a57..cb6dd79e02 100644 --- a/Plugins/org.mitk.gui.qt.cli/src/internal/QmitkCmdLineModuleProgressWidget.cpp +++ b/Plugins/org.mitk.gui.qt.cli/src/internal/QmitkCmdLineModuleProgressWidget.cpp @@ -1,513 +1,564 @@ /*=================================================================== 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 <QFileInfo> +#include <QDir> +#include <QMessageBox> #include <QVBoxLayout> #include <QLayoutItem> #include <QTextBrowser> #include <QByteArray> +#include <QApplication> // CTK #include <ctkCmdLineModuleFuture.h> #include <ctkCmdLineModuleFutureWatcher.h> #include <ctkCmdLineModuleManager.h> #include <ctkCmdLineModuleFrontend.h> #include <ctkCmdLineModuleDescription.h> #include <ctkCmdLineModuleParameter.h> #include <ctkCollapsibleGroupBox.h> // MITK #include <mitkIOUtil.h> #include <mitkDataStorage.h> #include <mitkDataNode.h> #include <QmitkCommonFunctionality.h> #include <QmitkCustomVariants.h> #include "QmitkCmdLineModuleGui.h" //----------------------------------------------------------------------------- QmitkCmdLineModuleProgressWidget::QmitkCmdLineModuleProgressWidget(QWidget *parent) : QWidget(parent) , m_ModuleManager(NULL) , m_DataStorage(NULL) , m_TemporaryDirectoryName("") , m_UI(new Ui::QmitkCmdLineModuleProgressWidget) , m_Layout(NULL) , 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_Layout->setContentsMargins(0,0,0,0); m_Layout->setSpacing(0); m_UI->m_ParametersGroupBox->setLayout(m_Layout); qRegisterMetaType<mitk::DataNode::Pointer>(); qRegisterMetaType<ctkCmdLineModuleReference>(); connect(m_UI->m_RemoveButton, SIGNAL(clicked()), this, SLOT(OnRemoveButtonClicked())); // 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. connect(&m_PollPauseTimer, SIGNAL(timeout()), SLOT(OnCheckModulePaused())); m_PollPauseTimer.setInterval(300); 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; } +//----------------------------------------------------------------------------- +void QmitkCmdLineModuleProgressWidget::SetOutputDirectory(const QString& directoryName) +{ + this->m_OutputDirectoryName = directoryName; +} + + //----------------------------------------------------------------------------- QString QmitkCmdLineModuleProgressWidget::GetTitle() { assert(m_ModuleFrontEnd); ctkCmdLineModuleReference reference = m_ModuleFrontEnd->moduleReference(); ctkCmdLineModuleDescription description = reference.description(); return description.title(); } //----------------------------------------------------------------------------- QString QmitkCmdLineModuleProgressWidget::GetFullName() const { assert(m_ModuleFrontEnd); ctkCmdLineModuleReference reference = m_ModuleFrontEnd->moduleReference(); ctkCmdLineModuleDescription description = reference.description(); return description.categoryDotTitle(); } //----------------------------------------------------------------------------- bool QmitkCmdLineModuleProgressWidget::IsStarted() const { bool isStarted = false; if (m_FutureWatcher != NULL && m_FutureWatcher->isStarted()) { isStarted = true; } return isStarted; } //----------------------------------------------------------------------------- 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); emit started(); } //----------------------------------------------------------------------------- void QmitkCmdLineModuleProgressWidget::OnModuleCanceled() { QString message = "cancelling."; 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_ParametersGroupBox->setCollapsed(true); this->m_UI->m_ConsoleGroupBox->setCollapsed(true); this->m_UI->m_ProgressTitle->setText(this->GetTitle() + ": cancelled"); message = "cancelled."; this->PublishMessage(message); } //----------------------------------------------------------------------------- void QmitkCmdLineModuleProgressWidget::OnModuleFinished() { 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); if (!this->m_FutureWatcher->isCanceled()) { QString message = "finishing."; this->PublishMessage(message); // If no incremental results from stdout, try getting hold of the whole buffer and printing it. if (m_OutputCount == 0) { message = "Output channel is:"; this->PublishMessage(message); this->PublishByteArray(this->m_FutureWatcher->readAllOutputData()); } // If no incremental results from stderr, try getting hold of the whole buffer and printing it. if (m_ErrorCount == 0) { message = "Error channel is:"; this->PublishMessage(message); this->PublishByteArray(this->m_FutureWatcher->readAllErrorData()); } this->m_UI->m_ProgressTitle->setText(this->GetTitle() + ": finished"); this->LoadOutputData(); this->ClearUpTemporaryFiles(); message = "finished."; this->PublishMessage(message); } emit finished(); } //----------------------------------------------------------------------------- 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::OnOutputDataReady() { m_OutputCount++; this->PublishByteArray(this->m_FutureWatcher->readPendingOutputData()); } //----------------------------------------------------------------------------- void QmitkCmdLineModuleProgressWidget::OnErrorDataReady() { m_ErrorCount++; this->PublishByteArray(this->m_FutureWatcher->readPendingErrorData()); } //----------------------------------------------------------------------------- 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::PublishByteArray(const QByteArray& array) { QString message = array.data(); this->PublishMessage(message); } //----------------------------------------------------------------------------- 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::SetFrontend(QmitkCmdLineModuleGui* frontEnd) { assert(frontEnd); assert(m_ModuleManager); assert(m_DataStorage); // We are assuming that this method is ONLY EVER CALLED ONCE. assert(!m_ModuleFrontEnd); // Assign the frontEnd to the member variable. m_ModuleFrontEnd = frontEnd; // We put the new GUI into the layout. m_Layout->insertWidget(0, m_ModuleFrontEnd->getGui()); // And configure a few other niceties. m_UI->m_ProgressTitle->setText(this->GetTitle()); m_UI->m_ConsoleGroupBox->setCollapsed(true); // We basically call SetFrontend then Run m_UI->m_ParametersGroupBox->setCollapsed(true); // so in practice the user will only want the progress bar. } //----------------------------------------------------------------------------- void QmitkCmdLineModuleProgressWidget::Run() { assert(m_ModuleManager); assert(m_DataStorage); assert(m_ModuleFrontEnd); m_OutputDataToLoad.clear(); + QString parameterName; + QString message; + QList<ctkCmdLineModuleParameter> parameters; + ctkCmdLineModuleReference reference = m_ModuleFrontEnd->moduleReference(); ctkCmdLineModuleDescription description = reference.description(); - QString message = "Saving image data to temporary storage..."; - this->PublishMessage(message); + // Check we have valid output. If at all possible, they should be somewhere writable. - // Sanity check we have actually specified some input: - QString parameterName; - QList<ctkCmdLineModuleParameter> parameters; + parameters = m_ModuleFrontEnd->parameters("image", ctkCmdLineModuleFrontend::Output); + parameters << m_ModuleFrontEnd->parameters("file", ctkCmdLineModuleFrontend::Output); + parameters << m_ModuleFrontEnd->parameters("geometry", ctkCmdLineModuleFrontend::Output); + + foreach (ctkCmdLineModuleParameter parameter, parameters) + { + parameterName = parameter.name(); + QString outputFileName = m_ModuleFrontEnd->value(parameterName, ctkCmdLineModuleFrontend::DisplayRole).toString(); + + // Try to make sure we are not running in the application installation folder, + // as more likely than not, it should not have write access, and you certainly + // don't want users output files dumped there. + // + // eg. C:/Program Files (Windows), /Applications (Mac), /usr/local (Linux) etc. + + QFileInfo outputFileInfo(outputFileName); + + QString applicationDir = QApplication::applicationDirPath(); + QString outputDir = outputFileInfo.dir().absolutePath(); + + if (applicationDir == outputDir) + { + qDebug() << "QmitkCmdLineModuleProgressWidget::Run(), output folder = application folder, so will swap to defaultOutputDir, specified in CLI module preferences"; + + QFileInfo newOutputFileInfo(m_OutputDirectoryName, outputFileInfo.fileName()); + QString newOutputFileAbsolutePath = newOutputFileInfo.absoluteFilePath(); + + qDebug() << "QmitkCmdLineModuleProgressWidget::Run(), swapping " << outputFileName << " to " << newOutputFileAbsolutePath; + + QMessageBox msgBox; + msgBox.setText("The output directory is the same as the application installation directory"); + msgBox.setInformativeText(tr("Output file:\n%1\n\nwill be swapped to\n%2").arg(outputFileName).arg(newOutputFileAbsolutePath)); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setIcon(QMessageBox::Warning); + msgBox.exec(); + + m_ModuleFrontEnd->setValue(parameterName, newOutputFileAbsolutePath, ctkCmdLineModuleFrontend::DisplayRole); + } + } + + // For each output image or file, store the filename, so we can auto-load it once the process finishes. + foreach (ctkCmdLineModuleParameter parameter, parameters) + { + parameterName = parameter.name(); + QString outputFileName = m_ModuleFrontEnd->value(parameterName, ctkCmdLineModuleFrontend::DisplayRole).toString(); - // For each input image, write a temporary file as a Nifti image, + if (!outputFileName.isEmpty()) + { + m_OutputDataToLoad.push_back(outputFileName); + + message = "Registered " + outputFileName + " to auto load upon completion."; + this->PublishMessage(message); + } + } + + // For each input image, write a temporary file as a Nifti image (TODO - iterate through list of file formats). // and then save the full path name back on the parameter. + + message = "Saving image data to temporary storage..."; + this->PublishMessage(message); + 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, ctkCmdLineModuleFrontend::DisplayRole).toString(); - - if (!outputFileName.isEmpty()) - { - m_OutputDataToLoad.push_back(outputFileName); - - message = "Registered " + outputFileName + " to auto load upon completion."; - this->PublishMessage(message); - } - } - m_OutputCount = 0; m_ErrorCount = 0; // 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_FutureWatcher, SIGNAL(outputDataReady()), SLOT(OnOutputDataReady())); connect(m_FutureWatcher, SIGNAL(errorDataReady()), SLOT(OnErrorDataReady())); 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()); // 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 index 800df91be1..30c7f1668f 100644 --- a/Plugins/org.mitk.gui.qt.cli/src/internal/QmitkCmdLineModuleProgressWidget.h +++ b/Plugins/org.mitk.gui.qt.cli/src/internal/QmitkCmdLineModuleProgressWidget.h @@ -1,209 +1,220 @@ /*=================================================================== 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> class QVBoxLayout; class QmitkCmdLineModuleGui; class ctkCmdLineModuleManager; class ctkCmdLineModuleFutureWatcher; 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); virtual ~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 Sets the Output Directory on this widget, and must be called + * immediately after construction, before using the widget. + */ + void SetOutputDirectory(const QString& directoryName); + /** * \brief Tells this widget, which module frontend it is running * \param frontEnd our QmitkCmdLineModuleGui class derived from ctkCmdLineModuleFrontend */ void SetFrontend(QmitkCmdLineModuleGui* frontEnd); /** * \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); void OnOutputDataReady(); void OnErrorDataReady(); private: /** * \brief Simply returns true if this widget is considered as having been started. */ bool IsStarted() const; /** * \brief Used to write output to the console widget, and also to qDebug(). */ void PublishMessage(const QString& message); /** * \brief Used to write output to the console widget, and also to qDebug(). */ void PublishByteArray(const QByteArray& array); /** * \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 Returns <category>.<title>, derived from the ctkCmdLineModuleReference and * hence from the ctkCmdLineModuleDescription. */ QString GetFullName() const; /** * \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 This must be injected before the Widget is used. + */ + QString m_OutputDirectoryName; + /** * \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 QmitkCmdLineModuleGui is created by the QmitkCmdLineModuleFactoryGui outside * of this class and injected into this class before being run. */ QmitkCmdLineModuleGui *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; /** * \brief We track how many times the OnOutputDataReady is called. */ int m_OutputCount; /** * \brief We track how many times the OnErrorDataReady is called. */ int m_ErrorCount; }; #endif // QMITKCMDLINEMODULEPROGRESSWIDGET_H