diff --git a/Plugins/org.mitk.gui.qt.cli/CMakeLists.txt b/Plugins/org.mitk.gui.qt.cli/CMakeLists.txt index ab01ca4dd0..a6ba14fe29 100644 --- a/Plugins/org.mitk.gui.qt.cli/CMakeLists.txt +++ b/Plugins/org.mitk.gui.qt.cli/CMakeLists.txt @@ -1,10 +1,10 @@ project(org_mitk_gui_qt_cli) set(QT_USE_QTUITOOLS 1) include(${QT_USE_FILE}) MACRO_CREATE_MITK_CTK_PLUGIN( EXPORT_DIRECTIVE CLI_EXPORT - EXPORTED_INCLUDE_SUFFIXES src + EXPORTED_INCLUDE_SUFFIXES src MODULE_DEPENDENCIES CTK QmitkExt ) diff --git a/Plugins/org.mitk.gui.qt.cli/files.cmake b/Plugins/org.mitk.gui.qt.cli/files.cmake index d66fd3652e..366c26fccd 100644 --- a/Plugins/org.mitk.gui.qt.cli/files.cmake +++ b/Plugins/org.mitk.gui.qt.cli/files.cmake @@ -1,65 +1,63 @@ set(SRC_CPP_FILES - + QmitkCmdLineModuleMenuComboBox.cpp ) set(INTERNAL_CPP_FILES - ctkCmdLineModuleMenuFactoryQtGui.cpp - ctkCmdLineModuleMenuComboBox.cpp 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 ) set(UI_FILES src/internal/QmitkPathListWidget.ui src/internal/CommandLineModulesViewControls.ui ) set(MOC_H_FILES - src/internal/ctkCmdLineModuleMenuComboBox.h + src/QmitkCmdLineModuleMenuComboBox.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 ) # 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/QmitkCmdLineModuleMenuComboBox.cpp b/Plugins/org.mitk.gui.qt.cli/src/QmitkCmdLineModuleMenuComboBox.cpp new file mode 100644 index 0000000000..8a413f8ffc --- /dev/null +++ b/Plugins/org.mitk.gui.qt.cli/src/QmitkCmdLineModuleMenuComboBox.cpp @@ -0,0 +1,186 @@ +/*=================================================================== + +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 "QmitkCmdLineModuleMenuComboBox.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +QmitkCmdLineModuleMenuComboBox::QmitkCmdLineModuleMenuComboBox(QWidget* parent) +: ctkMenuComboBox(parent) +, m_ModuleManager(NULL) +{ +} + + +// ------------------------------------------------------------------------- +QmitkCmdLineModuleMenuComboBox::~QmitkCmdLineModuleMenuComboBox() +{ + +} + + +// ------------------------------------------------------------------------- +void QmitkCmdLineModuleMenuComboBox::SetManager(ctkCmdLineModuleManager* manager) +{ + if (m_ModuleManager != NULL) + { + QObject::disconnect(manager, 0, this, 0); + } + + m_ModuleManager = manager; + + connect(m_ModuleManager, SIGNAL(moduleRegistered(const ctkCmdLineModuleReference&)), this, SLOT(OnModuleRegistered(const ctkCmdLineModuleReference&))); + connect(m_ModuleManager, SIGNAL(moduleUnregistered(const ctkCmdLineModuleReference&)), this, SLOT(OnModuleUnRegistered(const ctkCmdLineModuleReference&))); +} + + +// ------------------------------------------------------------------------- +ctkCmdLineModuleManager* QmitkCmdLineModuleMenuComboBox::GetManager() const +{ + return m_ModuleManager; +} + + +// ------------------------------------------------------------------------- +void QmitkCmdLineModuleMenuComboBox::OnModuleRegistered(const ctkCmdLineModuleReference& ref) +{ + this->RebuildMenu(); +} + + +// ------------------------------------------------------------------------- +void QmitkCmdLineModuleMenuComboBox::OnModuleUnRegistered(const ctkCmdLineModuleReference& ref) +{ + this->RebuildMenu(); +} + + +// ------------------------------------------------------------------------- +void QmitkCmdLineModuleMenuComboBox::AddName( + QList< QHash* >& listOfHashMaps, + const int& depth, + const QString& name, + QMenu* menu + ) +{ + if (depth >= listOfHashMaps.size()) + { + int need = depth - listOfHashMaps.size(); + for (int i = 0; i <= need; i++) + { + QHash *newHashMap = new QHash(); + listOfHashMaps.push_back(newHashMap); + } + } + listOfHashMaps[depth]->insert(name, menu); +} + + +// ------------------------------------------------------------------------- +void QmitkCmdLineModuleMenuComboBox::RebuildMenu() +{ + if (m_ModuleManager == NULL) + { + qDebug() << "QmitkCmdLineModuleMenuComboBox::RebuildMenu(): Module Manager is NULL? Surely a bug?"; + return; + } + + // Can't see another way to get a nested menu, without rebuilding the whole thing each time. + // :-( + + QMenu *menu = new QMenu(); + QStringList listOfModules; + + QList references = m_ModuleManager->moduleReferences(); + + // Get full names + for (int i = 0; i < references.size(); i++) + { + ctkCmdLineModuleReference reference = references[i]; + ctkCmdLineModuleDescription description = reference.description(); + QString title = description.title(); + QString category = description.category(); + QString fullName = category + "." + title; + listOfModules << fullName; + } + + // Sort list, so menu comes out in some sort of nice order. + listOfModules.sort(); + + qDebug() << "QmitkCmdLineModuleMenuComboBox::RebuildMenu, listOfModules=" << listOfModules; + + // Temporary data structure to enable connecting menus together. + QList< QHash* > list; + + // Iterate through all modules. + foreach (QString fullName, listOfModules) + { + // Pointer to keep track of where we are in the menu tree. + QMenu *currentMenu = menu; + + // Get individual parts, as they correspond to menu levels. + QStringList nameParts = fullName.split(".", QString::SkipEmptyParts); + + // Iterate over each part, building up either a QMenu or QAction. + for (int i = 0; i < nameParts.size(); i++) + { + QString part = nameParts[i]; + + if (i != nameParts.size() - 1) + { + // Need to add a menu/submenu, not an action. + if (list.size() <= i || list[i] == NULL || !list[i]->contains(part)) + { + QMenu *newMenu = new QMenu(part); + currentMenu->addMenu(newMenu); + currentMenu = newMenu; + + // Add this newMenu pointer to temporary datastructure, + // so we know we have already created it. + this->AddName(list, i, part, newMenu); + } + else + { + currentMenu = list[i]->value(part); + } + } + else + { + // Leaf node, just add the action. + currentMenu->addAction(part); + } + } + } + + // Clearup termporary data structure + for (int i = 0; i < list.size(); i++) + { + delete list[i]; + } + + // Set the constructed menu on the base class combo box. + this->setMenu(menu); +} + diff --git a/Plugins/org.mitk.gui.qt.cli/src/QmitkCmdLineModuleMenuComboBox.h b/Plugins/org.mitk.gui.qt.cli/src/QmitkCmdLineModuleMenuComboBox.h new file mode 100644 index 0000000000..75dd05055f --- /dev/null +++ b/Plugins/org.mitk.gui.qt.cli/src/QmitkCmdLineModuleMenuComboBox.h @@ -0,0 +1,66 @@ +/*=================================================================== + +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 QMITKCMDLINEMODULEMENUCOMBOBOX_H +#define QMITKCMDLINEMODULEMENUCOMBOBOX_H + +#include +#include +#include +#include +#include + +/** + * \class QmitkCmdLineModuleMenuComboBox + * \brief Subclass of ctkMenuComboBox to listen to ctkCmdLineModuleManager + * moduleRegistered and moduleUnregistered signals, and update the menu accordingly. + * \ingroup org_mitk_gui_qt_cli_internal + */ +class QmitkCmdLineModuleMenuComboBox : public ctkMenuComboBox { + + Q_OBJECT + +public: + + QmitkCmdLineModuleMenuComboBox(QWidget* parent = 0); + virtual ~QmitkCmdLineModuleMenuComboBox(); + + /** + * \brief Inject the module manager, so that this widget can + * still easily be used via widget promotion in Qt Designer, + * as it will maintain the default constructor. + */ + void SetManager(ctkCmdLineModuleManager* manager); + + /** + * \brief Returns the ctkCmdLineModuleManager. + */ + ctkCmdLineModuleManager* GetManager() const; + +private slots: + + void OnModuleRegistered(const ctkCmdLineModuleReference&); + void OnModuleUnRegistered(const ctkCmdLineModuleReference&); + +private: + + void RebuildMenu(); + void AddName(QList< QHash* >& listOfHashMaps, const int& depth, const QString& name, QMenu* menu); + + ctkCmdLineModuleManager* m_ModuleManager; +}; + +#endif QMITKCMDLINEMODULEMENUCOMBOBOX_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 bb5f2f8bf7..a85c50c72c 100644 --- a/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesView.cpp +++ b/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesView.cpp @@ -1,734 +1,713 @@ /*=================================================================== 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 "QmitkDataStorageComboBox.h" #include "QmitkCommonFunctionality.h" #include "QmitkCustomVariants.h" // Qt #include #include #include #include #include // CTK -#include "ctkCmdLineModuleMenuFactoryQtGui.h" #include #include #include #include #include #include #include #include #include // MITK #include //----------------------------------------------------------------------------- CommandLineModulesView::CommandLineModulesView() : m_Controls(NULL) , m_Parent(NULL) , m_ModuleManager(NULL) , m_ModuleBackend(NULL) , m_ModuleFactory(NULL) -, m_MenuFactory(NULL) , m_DirectoryWatcher(NULL) , m_Watcher(NULL) , m_TemporaryDirectoryName("") , m_DebugOutput(false) { qRegisterMetaType(); qRegisterMetaType(); } //----------------------------------------------------------------------------- CommandLineModulesView::~CommandLineModulesView() { if (m_ModuleManager != NULL) { delete m_ModuleManager; } if (m_ModuleBackend != NULL) { delete m_ModuleBackend; } if (m_ModuleFactory != NULL) { delete m_ModuleFactory; } - if (m_MenuFactory != NULL) - { - delete m_MenuFactory; - } - if (m_DirectoryWatcher != NULL) { delete m_DirectoryWatcher; } if (m_Watcher != NULL) { delete m_Watcher; } this->ClearUpTemporaryFiles(); } //----------------------------------------------------------------------------- void CommandLineModulesView::SetFocus() { this->m_Controls->m_ComboBox->setFocus(); } //----------------------------------------------------------------------------- void CommandLineModulesView::CreateQtPartControl( QWidget *parent ) { if (!m_Controls) { m_MapTabToModuleInstance.clear(); m_TemporaryFileNames.clear(); // We create CommandLineModulesViewControls, which derives from the Qt generated class. m_Controls = new CommandLineModulesViewControls(parent); // 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. m_ModuleBackend = new ctkCmdLineModuleBackendLocalProcess(); m_ModuleFactory = new QmitkCmdLineModuleFactoryGui(this->GetDataStorage()); - m_MenuFactory = new ctkCmdLineModuleMenuFactoryQtGui(); m_ModuleManager = new ctkCmdLineModuleManager(ctkCmdLineModuleManager::STRICT_VALIDATION, m_TemporaryDirectoryName); - m_ModuleManager->registerBackend(m_ModuleBackend); + + m_Controls->m_ComboBox->SetManager(m_ModuleManager); m_DirectoryWatcher = new ctkCmdLineModuleDirectoryWatcher(m_ModuleManager); - // This connect must come before we update the preferences for the first time, - // so that as you retrieve the preference values, and set up a load path, the m_ModuleManager - // is already listening. - connect(this->m_ModuleManager, SIGNAL(moduleRegistered(ctkCmdLineModuleReference)), this, SLOT(OnModulesChanged())); - connect(this->m_ModuleManager, SIGNAL(moduleUnregistered(ctkCmdLineModuleReference)), this, SLOT(OnModulesChanged())); + m_ModuleManager->registerBackend(m_ModuleBackend); - // Loads the preferences like directory settings into member variables. 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_StopButton, SIGNAL(pressed()), this, SLOT(OnStopButtonPressed())); 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, before asking him for the paths to scan. ctkCmdLineModuleDefaultPathBuilder builder; builder.setLoadFromApplicationDir(loadApplicationDir); builder.setLoadFromHomeDir(loadHomeDir); builder.setLoadFromCurrentDir(loadCurrentDir); builder.setLoadFromCtkModuleLoadPath(loadAutoLoadDir); QStringList defaultPaths = builder.build(); // We get additional paths from preferences. QString pathString = QString::fromStdString(prefs->Get(CommandLineModulesViewConstants::MODULE_DIRECTORIES_NODE_NAME, "")); QStringList additionalPaths = pathString.split(";", QString::SkipEmptyParts); // Combine the sets of paths. QStringList totalPaths; totalPaths << defaultPaths; totalPaths << additionalPaths; // 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 this once, // so I am checking if the list of directory names has changed. if (this->m_DirectoryWatcher->directories() != totalPaths) { // This should update the directory watcher, which should sort out if any new modules have been loaded // and if so, should signal ModulesChanged, which is caught by this class, and re-build the GUI. m_DirectoryWatcher->setDirectories(totalPaths); } } //----------------------------------------------------------------------------- void CommandLineModulesView::OnPreferencesChanged(const berry::IBerryPreferences* /*prefs*/) { this->RetrieveAndStoreTemporaryDirectoryPreferenceValues(); this->RetrieveAndStorePreferenceValues(); } -//----------------------------------------------------------------------------- -void CommandLineModulesView::OnModulesChanged() -{ - QList refs = this->m_ModuleManager->moduleReferences(); - QMenu *menu = m_MenuFactory->create(refs); - this->m_Controls->m_ComboBox->setMenu(menu); -} - - //----------------------------------------------------------------------------- void CommandLineModulesView::AddModuleTab(const ctkCmdLineModuleReference& moduleRef) { // 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; } if (!description.description().isEmpty()) { QString descriptionHtml = "

" + description.description() + "

"; helpString += descriptionHtml; } if (!description.documentationURL().isEmpty()) { QString docUrlHtml = "

For more information please see the online documentation.

"; helpString += docUrlHtml; } QString aboutString = ""; if (!description.title().isEmpty()) { QString titleHtml = "

" + description.title() + "

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

Contributed By

" + description.contributor() + "

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

License

" + description.license() + "

"; aboutString += licenseHtml; } if (!description.acknowledgements().isEmpty()) { QString acknowledgementsHtml = "

Acknowledgements

" + description.acknowledgements() + "

"; aboutString += acknowledgementsHtml; } 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; } //----------------------------------------------------------------------------- ctkCmdLineModuleReference CommandLineModulesView::GetReferenceByIdentifier(QString identifier) { ctkCmdLineModuleReference result; QList references = this->m_ModuleManager->moduleReferences(); ctkCmdLineModuleReference ref; foreach(ref, references) { if (ref.description().title() == identifier) { result = ref; } } return result; } //----------------------------------------------------------------------------- void CommandLineModulesView::OnRunPauseButtonPressed() { this->ProcessInstruction(RunPauseButton); } //----------------------------------------------------------------------------- void CommandLineModulesView::OnStopButtonPressed() { this->ProcessInstruction(StopButton); } //----------------------------------------------------------------------------- void CommandLineModulesView::OnRestoreButtonPressed() { QString message = "restoring defaults."; this->PublishMessage(message); ctkCmdLineModuleFrontend* moduleInstance = m_MapTabToModuleInstance[m_Controls->m_TabWidget->currentIndex()]; if (!moduleInstance) { qWarning() << "Invalid module instance"; return; } moduleInstance->resetValues(); message = "restored defaults."; this->PublishMessage(message); } //----------------------------------------------------------------------------- void CommandLineModulesView::OnActionChanged(QAction* action) { ctkCmdLineModuleReference ref = this->GetReferenceByIdentifier(action->text()); if (ref) { this->AddModuleTab(ref); } } //----------------------------------------------------------------------------- void CommandLineModulesView::ProcessInstruction(const ProcessingInstruction& instruction) { // This code places one method between OnRunButtonPressed and // OnStopButtonPressed, and is responsible for calling // OnRun, OnStop, OnPause, OnResume, and so could be refactored // into a separate class for ease of unit testing. if (instruction == RunPauseButton) { if (m_Watcher == NULL) { // Never been run before ... so just run it. this->Run(); } else { if (m_Watcher->isCanceled()) { this->Run(); } else if (m_Watcher->isFinished()) { this->Run(); } else if (m_Watcher->isPaused()) { this->Resume(); } else if (m_Watcher->isRunning()) { this->Pause(); } else if (m_Watcher->isStarted()) { this->Pause(); } } } else if (instruction == StopButton) { if (m_Watcher != NULL) { if (m_Watcher->isPaused()) { this->Resume(); this->Stop(); } else if (m_Watcher->isRunning()) { this->Stop(); } else if (m_Watcher->isStarted()) { this->Stop(); } } } } //----------------------------------------------------------------------------- void CommandLineModulesView::Run() { // Get hold of the command line module. ctkCmdLineModuleFrontend* moduleInstance = m_MapTabToModuleInstance[m_Controls->m_TabWidget->currentIndex()]; if (!moduleInstance) { qWarning() << "Invalid module instance"; return; } m_OutputDataToLoad.clear(); ctkCmdLineModuleReference reference = moduleInstance->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 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 = moduleInstance->parameters("image", ctkCmdLineModuleFrontend::Input); foreach (ctkCmdLineModuleParameter parameter, parameters) { parameterName = parameter.name(); QVariant tmp = moduleInstance->value(parameterName, ctkCmdLineModuleFrontend::UserRole); mitk::DataNode::Pointer node = tmp.value(); if (node.IsNotNull()) { mitk::Image* image = dynamic_cast(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); moduleInstance->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 = moduleInstance->parameters("image", ctkCmdLineModuleFrontend::Output); parameters << moduleInstance->parameters("file", ctkCmdLineModuleFrontend::Output); foreach (ctkCmdLineModuleParameter parameter, parameters) { parameterName = parameter.name(); QString outputFileName = moduleInstance->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_Watcher != NULL) { QObject::disconnect(m_Watcher, 0, 0, 0); delete m_Watcher; } m_Watcher = new QFutureWatcher(); QObject::connect(m_Watcher, SIGNAL(started()), this, SLOT(OnModuleStarted())); QObject::connect(m_Watcher, SIGNAL(finished()), this, SLOT(OnModuleFinished())); QObject::connect(m_Watcher, SIGNAL(progressValueChanged(int)), this, SLOT(OnModuleProgressValueChanged(int))); QObject::connect(m_Watcher, SIGNAL(progressTextChanged(QString)), this, SLOT(OnModuleProgressTextChanged(QString))); ctkCmdLineModuleFuture future = m_ModuleManager->run(moduleInstance); m_Watcher->setFuture(future); m_Controls->Running(); } //----------------------------------------------------------------------------- void CommandLineModulesView::Stop() { QString message = "stopping."; this->PublishMessage(message); this->ClearUpTemporaryFiles(); m_TemporaryFileNames.clear(); m_OutputDataToLoad.clear(); m_Watcher->cancel(); m_Watcher->waitForFinished(); m_Controls->Cancel(); message = "stopped."; this->PublishMessage(message); } //----------------------------------------------------------------------------- void CommandLineModulesView::Pause() { QString message = "pausing."; this->PublishMessage(message); m_Watcher->pause(); m_Controls->Pause(); message = "paused."; this->PublishMessage(message); } //----------------------------------------------------------------------------- void CommandLineModulesView::Resume() { QString message = "resuming."; this->PublishMessage(message); m_Watcher->resume(); m_Controls->Resume(); message = "resumed."; this->PublishMessage(message); } //----------------------------------------------------------------------------- void CommandLineModulesView::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 CommandLineModulesView::LoadOutputData() { std::vector 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) { mitk::DataStorage::Pointer dataStorage = this->GetDataStorage(); int numberLoaded = mitk::IOUtil::LoadFiles(fileNames, *(dataStorage.GetPointer())); QString message = QObject::tr("loaded %1 files").arg(numberLoaded); this->PublishMessage(message); } } //----------------------------------------------------------------------------- void CommandLineModulesView::PublishMessage(const QString& message) { QString prefix = "Command Line Module ... "; qDebug() << prefix << message; m_Controls->m_ConsoleOutputTextEdit->appendPlainText(prefix + message); } //----------------------------------------------------------------------------- void CommandLineModulesView::OnModuleStarted() { QString message = "started."; this->PublishMessage(message); } //----------------------------------------------------------------------------- void CommandLineModulesView::OnModuleProgressValueChanged(int value) { QString message = QObject::tr("OnModuleProgressValueChanged int=%1.").arg(value); this->PublishMessage(message); } //----------------------------------------------------------------------------- void CommandLineModulesView::OnModuleProgressTextChanged(QString value) { QString message = QObject::tr("OnModuleProgressValueChanged QString=%1.").arg(value); this->PublishMessage(message); } //----------------------------------------------------------------------------- void CommandLineModulesView::OnModuleFinished() { QString message = "finishing."; this->PublishMessage(message); this->LoadOutputData(); this->ClearUpTemporaryFiles(); m_Controls->Finished(); message = "finished."; this->PublishMessage(message); } 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 e48b7d2afa..18c8575ff4 100644 --- a/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesView.h +++ b/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesView.h @@ -1,290 +1,277 @@ /*=================================================================== 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 ctkCmdLineModuleManager; class QmitkCmdLineModuleFactoryGui; -class ctkCmdLineModuleMenuFactoryQtGui; class ctkCmdLineModuleFrontend; class ctkCmdLineModuleBackendLocalProcess; class ctkCmdLineModuleDirectoryWatcher; class CommandLineModulesViewControls; class QAction; 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 * * This class is a basic interface to the CTK command line modules library. * Ideally, an MITK base application would load command line modules dynamically * at runtime, and promote them to the main window menu bar to appear as fully * fledged Views. However, currently this is not supported, and so this view * provides a simplified interface, contained within one plugin in order to * facilitate testing, debugging, and understanding of use-cases. * * \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. */ void OnActionChanged(QAction*); /** * \brief Slot that is called when the Run button is pressed. */ void OnRunPauseButtonPressed(); /** * \brief Slot that is called when the Stop button is pressed. */ void OnStopButtonPressed(); /** * \brief Slot that is called when the restore defaults button is pressed. */ void OnRestoreButtonPressed(); /** * \brief Slot called from QFutureWatcher when the module has been launched. */ void OnModuleStarted(); /** * \brief Slot called from QFutureWatcher when the module has finished. */ void OnModuleFinished(); /** * \brief Slot called from QFutureWatcher to notify of any progress, * currently just printing console debug messages. */ void OnModuleProgressValueChanged(int); /** * \brief Slot called from QFutureWatcher to notify of any progress, * currently just printing console debug messages. */ void OnModuleProgressTextChanged(QString); - /** - * \brief We register this slot with the ctkCmdLineModuleManager so that if - * the modulesAdded or modulesRemoved signals are emmitted from ctkCmdLineModuleManager - * we rebuild the whole menu. In future this could be made more efficient, and only add/remove single items. - */ - void OnModulesChanged(); - 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: enum ProcessingInstruction { RunPauseButton, StopButton }; /** * \brief Called on startup and by OnPreferencesChanged to load the preferences into member variables. * * Does not do the temporary folder. */ void RetrieveAndStorePreferenceValues(); /** * \brief Called on startup and by OnPreferencesChanged to load the temporary folder preference into member variables. */ void RetrieveAndStoreTemporaryDirectoryPreferenceValues(); /** * \brief Called to get hold of the actual prefefences node. */ berry::IBerryPreferences::Pointer RetrievePreferences(); /** * \brief Used to write output to console. */ void PublishMessage(const QString& message); /** * \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. */ ctkCmdLineModuleReference GetReferenceByIdentifier(QString identifier); /** * \brief Adds a module to the views tabbed widget, creating a new tab each time. * \param moduleRef A ctkCmdLineModuleReference. */ void AddModuleTab(const ctkCmdLineModuleReference& moduleRef); /** * \brief Destroys any images listed in m_TemporaryFileNames, silently failing. */ void ClearUpTemporaryFiles(); /** * \brief Loads any data listed in m_OutputDataToLoad into the mitk::DataStorage. */ void LoadOutputData(); /** * \brief Called by OnRunButtonPressed() and OnStopButtonPressed() to actually decide what to run. */ void ProcessInstruction(const ProcessingInstruction& instruction); /** * \brief Slot to launch the command line module. */ void Run(); /** * \brief Slot to stop (kill) the command line module. */ void Stop(); /** * \brief Slot to pause the command line module. */ void Pause(); /** * \brief Slot to resume the command line module. */ void Resume(); /** * \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. */ 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 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 ctkCmdLineModuleMenuFactoryQtGui will build a QMenu from the list of available modules. - */ - ctkCmdLineModuleMenuFactoryQtGui *m_MenuFactory; - /** * \brief The ctkCmdLineModuleDirectoryWatcher maintains the list of directories * we are using to load modules, to provide automatic updates. */ ctkCmdLineModuleDirectoryWatcher *m_DirectoryWatcher; /** * \brief This is the QFutureWatcher that will watch for when the process has finished, and call OnFutureFinished() slot. */ QFutureWatcher* m_Watcher; /** * \brief We use this map to decide if we want to create more tabs or not. */ QHash m_MapTabToModuleInstance; /** * \brief We store a temporary folder name, accessible via user preferences. */ QString m_TemporaryDirectoryName; /** * \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 successfull completion of * a command line module, we load the output data into the mitk::DataStorage. */ QStringList m_OutputDataToLoad; /** * \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.ui b/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesViewControls.ui index ab4334122e..60eb679be8 100644 --- a/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesViewControls.ui +++ b/Plugins/org.mitk.gui.qt.cli/src/internal/CommandLineModulesViewControls.ui @@ -1,179 +1,173 @@ CommandLineModulesViewControls 0 0 678 582 0 0 QmitkTemplate 0 0 choose: - - - - 0 - 0 - - + 0 0 restore default parameters 0 0 run the command line module 0 0 stop the command line module Qt::Horizontal 40 20 0 0 0 0 0 0 Console true - - ctkMenuComboBox - QWidget -
ctkMenuComboBox.h
- 1 -
ctkCollapsibleGroupBox QGroupBox
ctkCollapsibleGroupBox.h
1
+ + QmitkCmdLineModuleMenuComboBox + QWidget +
QmitkCmdLineModuleMenuComboBox.h
+ 1 +
diff --git a/Plugins/org.mitk.gui.qt.cli/src/internal/ctkCmdLineModuleMenuComboBox.cpp b/Plugins/org.mitk.gui.qt.cli/src/internal/ctkCmdLineModuleMenuComboBox.cpp deleted file mode 100644 index faddd0cff9..0000000000 --- a/Plugins/org.mitk.gui.qt.cli/src/internal/ctkCmdLineModuleMenuComboBox.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/*============================================================================= - - Library: CTK - - Copyright (c) University College London - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -=============================================================================*/ - -#include "ctkCmdLineModuleMenuComboBox.h" - -// ------------------------------------------------------------------------- -ctkCmdLineModuleMenuComboBox::ctkCmdLineModuleMenuComboBox(QWidget* parent) -: ctkMenuComboBox(parent) -{ - -} - - -// ------------------------------------------------------------------------- -ctkCmdLineModuleMenuComboBox::~ctkCmdLineModuleMenuComboBox() -{ - -} diff --git a/Plugins/org.mitk.gui.qt.cli/src/internal/ctkCmdLineModuleMenuComboBox.h b/Plugins/org.mitk.gui.qt.cli/src/internal/ctkCmdLineModuleMenuComboBox.h deleted file mode 100644 index f5a1ed8b3c..0000000000 --- a/Plugins/org.mitk.gui.qt.cli/src/internal/ctkCmdLineModuleMenuComboBox.h +++ /dev/null @@ -1,45 +0,0 @@ -/*============================================================================= - - Library: CTK - - Copyright (c) University College London - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -=============================================================================*/ - -#ifndef CTKCMDLINEMODULEMENUCOMBOBOX_H -#define CTKCMDLINEMODULEMENUCOMBOBOX_H - -#include -#include - -/** - * \class ctkCmdLineModuleMenuComboBox - * \brief Subclass of ctkMenuComboBox to listen to ctkCmdLineModuleManager - * moduleRegistered and moduleUnregistered signals, and update the menu accordingly. - * \ingroup org_mitk_gui_qt_cli_internal - */ -class ctkCmdLineModuleMenuComboBox : public ctkMenuComboBox { - - Q_OBJECT - -public: - - ctkCmdLineModuleMenuComboBox(QWidget* parent = 0); - virtual ~ctkCmdLineModuleMenuComboBox(); - -}; - -#endif CTKCMDLINEMODULEMENUCOMBOBOX_H - diff --git a/Plugins/org.mitk.gui.qt.cli/src/internal/ctkCmdLineModuleMenuFactoryQtGui.cpp b/Plugins/org.mitk.gui.qt.cli/src/internal/ctkCmdLineModuleMenuFactoryQtGui.cpp deleted file mode 100644 index 4bcd25ff7f..0000000000 --- a/Plugins/org.mitk.gui.qt.cli/src/internal/ctkCmdLineModuleMenuFactoryQtGui.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/*============================================================================= - - Library: CTK - - Copyright (c) University College London - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -=============================================================================*/ - -#include "ctkCmdLineModuleMenuFactoryQtGui.h" -#include "ctkCmdLineModuleDescription.h" -#include -#include - -//----------------------------------------------------------------------------- -ctkCmdLineModuleMenuFactoryQtGui::ctkCmdLineModuleMenuFactoryQtGui() -{ - -} - - -//----------------------------------------------------------------------------- -ctkCmdLineModuleMenuFactoryQtGui::~ctkCmdLineModuleMenuFactoryQtGui() -{ - -} - -//----------------------------------------------------------------------------- -QMenu* ctkCmdLineModuleMenuFactoryQtGui::create(const QList& references) -{ - QMenu *menu = new QMenu(); - ctkCmdLineModuleReference ref; - - foreach (ref, references) - { - menu->addAction(ref.description().title()); - } - return menu; -} diff --git a/Plugins/org.mitk.gui.qt.cli/src/internal/ctkCmdLineModuleMenuFactoryQtGui.h b/Plugins/org.mitk.gui.qt.cli/src/internal/ctkCmdLineModuleMenuFactoryQtGui.h deleted file mode 100644 index 31c851966f..0000000000 --- a/Plugins/org.mitk.gui.qt.cli/src/internal/ctkCmdLineModuleMenuFactoryQtGui.h +++ /dev/null @@ -1,49 +0,0 @@ -/*============================================================================= - - Library: CTK - - Copyright (c) University College London - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -=============================================================================*/ - -#ifndef CTKCMDLINEMODULEMENUFACTORYQTGUI_H -#define CTKCMDLINEMODULEMENUFACTORYQTGUI_H - -#include -#include -#include "ctkCmdLineModuleReference.h" - -/** - * \class ctkCmdLineModuleMenuFactoryQtGui - * \brief Takes a QHash of filename and ctkCmdLineModuleReference and produces a QMenu. - * \author m.clarkson@ucl.ac.uk - * \ingroup org_mitk_gui_qt_cli_internal - */ -class ctkCmdLineModuleMenuFactoryQtGui -{ -public: - - ctkCmdLineModuleMenuFactoryQtGui(); - virtual ~ctkCmdLineModuleMenuFactoryQtGui(); - - /** - * \brief Constructs a menu, for all the items in the QHash. - * \param list List of references, from which to build a menu. - * \return QMenu* a menu. - */ - QMenu* create(const QList& list); -}; - -#endif // CTKCMDLINEMODULEMENUFACTORYQTGUI_H