diff --git a/CoreUI/Bundles/org.mitk.gui.qt.application/files.cmake b/CoreUI/Bundles/org.mitk.gui.qt.application/files.cmake index 0a07f8f2b4..d76df60f76 100644 --- a/CoreUI/Bundles/org.mitk.gui.qt.application/files.cmake +++ b/CoreUI/Bundles/org.mitk.gui.qt.application/files.cmake @@ -1,32 +1,36 @@ SET(SRC_CPP_FILES QmitkApplication.cpp QmitkDefaultPerspective.cpp + QmitkGeneralPreferencePage.cpp ) SET(INTERNAL_CPP_FILES QmitkActionBarAdvisor.cpp QmitkWorkbenchAdvisor.cpp QmitkWorkbenchWindowAdvisor.cpp + QmitkPreferencesDialog.cpp ) SET(INTERNAL_MOC_H_FILES ) SET(MOC_H_FILES + src/QmitkGeneralPreferencePage.h src/internal/QmitkWorkbenchWindowAdvisorHack.h + src/internal/QmitkPreferencesDialog.h ) # todo: add some qt style sheet resources -#SET(RES_FILES -# resources/orgmitkguiqtapplication.qrc -#) +SET(RES_FILES + resources/resources.qrc +) SET(CPP_FILES manifest.cpp) 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/CoreUI/Bundles/org.mitk.gui.qt.application/manifest.cpp b/CoreUI/Bundles/org.mitk.gui.qt.application/manifest.cpp index dde48a6d8d..3cf02a84a2 100644 --- a/CoreUI/Bundles/org.mitk.gui.qt.application/manifest.cpp +++ b/CoreUI/Bundles/org.mitk.gui.qt.application/manifest.cpp @@ -1,31 +1,36 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include #include #include "src/QmitkApplication.h" #include "src/QmitkDefaultPerspective.h" +#include "src/QmitkGeneralPreferencePage.h" POCO_BEGIN_NAMED_MANIFEST(cherryIApplication, cherry::IApplication) POCO_EXPORT_CLASS(QmitkApplication) POCO_END_MANIFEST POCO_BEGIN_NAMED_MANIFEST(cherryIPerspectiveFactory, cherry::IPerspectiveFactory) POCO_EXPORT_CLASS(QmitkDefaultPerspective) POCO_END_MANIFEST + +POCO_BEGIN_NAMED_MANIFEST(cherryIQtPreferencePage, cherry::IQtPreferencePage) + POCO_EXPORT_CLASS(QmitkGeneralPreferencePage) +POCO_END_MANIFEST diff --git a/CoreUI/Bundles/org.mitk.gui.qt.application/plugin.xml b/CoreUI/Bundles/org.mitk.gui.qt.application/plugin.xml index ae48894432..651057a345 100644 --- a/CoreUI/Bundles/org.mitk.gui.qt.application/plugin.xml +++ b/CoreUI/Bundles/org.mitk.gui.qt.application/plugin.xml @@ -1,18 +1,28 @@ + + + + + + + + + + \ No newline at end of file diff --git a/CoreUI/Bundles/org.mitk.gui.qt.application/resources/Thumbs.db b/CoreUI/Bundles/org.mitk.gui.qt.application/resources/Thumbs.db new file mode 100644 index 0000000000..821ac9ed78 Binary files /dev/null and b/CoreUI/Bundles/org.mitk.gui.qt.application/resources/Thumbs.db differ diff --git a/CoreUI/Bundles/org.mitk.gui.qt.application/resources/document-save.png b/CoreUI/Bundles/org.mitk.gui.qt.application/resources/document-save.png new file mode 100644 index 0000000000..db5c52b769 Binary files /dev/null and b/CoreUI/Bundles/org.mitk.gui.qt.application/resources/document-save.png differ diff --git a/CoreUI/Bundles/org.mitk.gui.qt.application/resources/edit-redo.png b/CoreUI/Bundles/org.mitk.gui.qt.application/resources/edit-redo.png new file mode 100644 index 0000000000..3eb7b05c84 Binary files /dev/null and b/CoreUI/Bundles/org.mitk.gui.qt.application/resources/edit-redo.png differ diff --git a/CoreUI/Bundles/org.mitk.gui.qt.application/resources/edit-undo.png b/CoreUI/Bundles/org.mitk.gui.qt.application/resources/edit-undo.png new file mode 100644 index 0000000000..61b2ce9a53 Binary files /dev/null and b/CoreUI/Bundles/org.mitk.gui.qt.application/resources/edit-undo.png differ diff --git a/CoreUI/Bundles/org.mitk.gui.qt.application/resources/preferences-system.png b/CoreUI/Bundles/org.mitk.gui.qt.application/resources/preferences-system.png new file mode 100644 index 0000000000..6e52db7cfd Binary files /dev/null and b/CoreUI/Bundles/org.mitk.gui.qt.application/resources/preferences-system.png differ diff --git a/CoreUI/Bundles/org.mitk.gui.qt.application/resources/resources.qrc b/CoreUI/Bundles/org.mitk.gui.qt.application/resources/resources.qrc new file mode 100644 index 0000000000..300bf1490d --- /dev/null +++ b/CoreUI/Bundles/org.mitk.gui.qt.application/resources/resources.qrc @@ -0,0 +1,9 @@ + + + document-save.png + edit-redo.png + edit-undo.png + preferences-system.png + system-log-out.png + + diff --git a/CoreUI/Bundles/org.mitk.gui.qt.application/resources/system-log-out.png b/CoreUI/Bundles/org.mitk.gui.qt.application/resources/system-log-out.png new file mode 100644 index 0000000000..fddbc2bce1 Binary files /dev/null and b/CoreUI/Bundles/org.mitk.gui.qt.application/resources/system-log-out.png differ diff --git a/CoreUI/Bundles/org.mitk.gui.qt.application/src/QmitkGeneralPreferencePage.cpp b/CoreUI/Bundles/org.mitk.gui.qt.application/src/QmitkGeneralPreferencePage.cpp new file mode 100644 index 0000000000..e439901a93 --- /dev/null +++ b/CoreUI/Bundles/org.mitk.gui.qt.application/src/QmitkGeneralPreferencePage.cpp @@ -0,0 +1,63 @@ +/*========================================================================= + + Program: Medical Imaging & Interaction Toolkit + Language: C++ + Date: $Date: 2009-07-07 16:57:15 +0200 (Di, 07 Jul 2009) $ + Version: $Revision: 18019 $ + + Copyright (c) German Cancer Research Center, Division of Medical and + Biological Informatics. All rights reserved. + See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + + =========================================================================*/ + +#include "QmitkGeneralPreferencePage.h" + +#include "cherryIPreferencesService.h" +#include "cherryPlatform.h" + +#include +#include +#include +#include + +using namespace cherry; + +QmitkGeneralPreferencePage::QmitkGeneralPreferencePage( QWidget* parent, Qt::WindowFlags f ) +: IQtPreferencePage(parent, f) +{ + IPreferencesService::Pointer prefService = Platform::GetServiceRegistry().GetServiceById(IPreferencesService::ID); + cherry::IPreferences::Pointer _GeneralPreferencesNode = prefService->GetSystemPreferences()->Node("/General"); + m_GeneralPreferencesNode = _GeneralPreferencesNode; + + m_StartMaximized = new QCheckBox("Start Main Window &Maximized", this); + m_StartMaximized->setChecked(_GeneralPreferencesNode->GetBool("startMaximized", false)); + + QGridLayout* layout = new QGridLayout; + layout->addWidget(m_StartMaximized, 0,0); + layout->setRowStretch(0, 0); + layout->setRowStretch(1, 20); + + this->setLayout(layout); +} + +bool QmitkGeneralPreferencePage::PerformOk() +{ + IPreferences::Pointer _GeneralPreferencesNode = m_GeneralPreferencesNode.Lock(); + if(_GeneralPreferencesNode.IsNotNull()) + { + _GeneralPreferencesNode->PutBool("startMaximized", m_StartMaximized->isChecked()); + _GeneralPreferencesNode->Flush(); + return true; + } + return false; +} + +void QmitkGeneralPreferencePage::PerformCancel() +{ + +} \ No newline at end of file diff --git a/CoreUI/Bundles/org.mitk.gui.qt.application/src/QmitkGeneralPreferencePage.h b/CoreUI/Bundles/org.mitk.gui.qt.application/src/QmitkGeneralPreferencePage.h new file mode 100644 index 0000000000..9c29bde550 --- /dev/null +++ b/CoreUI/Bundles/org.mitk.gui.qt.application/src/QmitkGeneralPreferencePage.h @@ -0,0 +1,51 @@ +/*========================================================================= + + Program: Medical Imaging & Interaction Toolkit + Language: C++ + Date: $Date: 2009-02-10 14:14:32 +0100 (Di, 10 Feb 2009) $ + Version: $Revision: 16224 $ + + Copyright (c) German Cancer Research Center, Division of Medical and + Biological Informatics. All rights reserved. + See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + + =========================================================================*/ + + +#ifndef QMITKGENERALPREFERENCEPAGE_H_ +#define QMITKGENERALPREFERENCEPAGE_H_ + +#include + +#include "cherryIQtPreferencePage.h" +#include "mitkQtAppDll.h" + +class QCheckBox; + +struct MITK_QT_APP QmitkGeneralPreferencePage : public cherry::IQtPreferencePage +{ + Q_OBJECT + +public: + QmitkGeneralPreferencePage(QWidget* parent = 0, Qt::WindowFlags f = 0); + + /// + /// Invoked when the OK button was clicked in the preferences dialog + /// + virtual bool PerformOk(); + + /// + /// Invoked when the Cancel button was clicked in the preferences dialog + /// + virtual void PerformCancel(); +protected: + cherry::IPreferences::WeakPtr m_GeneralPreferencesNode; + QCheckBox* m_StartMaximized; + +}; + +#endif /* QMITKGENERALPREFERENCEPAGE_H_ */ diff --git a/CoreUI/Bundles/org.mitk.gui.qt.application/src/internal/QmitkPreferencesDialog.cpp b/CoreUI/Bundles/org.mitk.gui.qt.application/src/internal/QmitkPreferencesDialog.cpp new file mode 100644 index 0000000000..4eff304d5d --- /dev/null +++ b/CoreUI/Bundles/org.mitk.gui.qt.application/src/internal/QmitkPreferencesDialog.cpp @@ -0,0 +1,470 @@ +/*========================================================================= + + Program: openCherry Platform + Language: C++ + Date: $Date: 2009-07-08 13:02:46 +0200 (Mi, 08 Jul 2009) $ + Version: $Revision: 18037 $ + + Copyright (c) German Cancer Research Center, Division of Medical and + Biological Informatics. All rights reserved. + See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + + =========================================================================*/ + +#include "QmitkPreferencesDialog.h" + +#include "cherryPlatform.h" +#include "cherryIPreferencePage.h" +#include "cherryIConfigurationElement.h" +#include "cherryIExtensionPointService.h" +#include "cherryIExtension.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace std; + +QmitkPreferencesDialog::QmitkPreferencesDialog(QWidget * parent, Qt::WindowFlags f) +: QDialog(parent, f) +{ + // m_PreferencesService + m_PreferencesService = + cherry::Platform::GetServiceRegistry().GetServiceById(cherry::IPreferencesService::ID); + + // m_PrefPages + cherry::IExtensionPointService::Pointer extensionPointService = cherry::Platform::GetExtensionPointService(); + cherry::IConfigurationElement::vector prefPages(extensionPointService->GetConfigurationElementsFor("org.opencherry.ui.preferencePages")); + cherry::IConfigurationElement::vector keywordExts(extensionPointService->GetConfigurationElementsFor("org.opencherry.ui.keywords")); + cherry::IConfigurationElement::vector::iterator prefPagesIt; + std::string id; + std::string name; + std::string category; + std::string className; + std::vector keywords; + vector keywordRefs; + cherry::IConfigurationElement::vector::iterator keywordRefsIt; + cherry::IConfigurationElement::vector::iterator keywordExtsIt; + string keywordRefId; + string keywordId; + string keywordLabels; + + for (prefPagesIt = prefPages.begin(); prefPagesIt != prefPages.end(); ++prefPagesIt) + { + keywords.clear(); + if((*prefPagesIt)->GetAttribute("id", id) + && (*prefPagesIt)->GetAttribute("name", name) + && (*prefPagesIt)->GetAttribute("class", className)) + { + (*prefPagesIt)->GetAttribute("category", category); + //# collect keywords + keywordRefs = (*prefPagesIt)->GetChildren("keywordreference"); // get all keyword references + for (keywordRefsIt = keywordRefs.begin() + ; keywordRefsIt != keywordRefs.end(); ++keywordRefsIt) // iterate over all refs + { + (*keywordRefsIt)->GetAttribute("id", keywordRefId); // get referenced id + + for (keywordExtsIt = keywordExts.begin(); keywordExtsIt != keywordExts.end(); ++keywordExtsIt) // iterate over all keywords + { + (*keywordExtsIt)->GetAttribute("id", keywordId); // get keyword id + if(keywordId == keywordRefId) // if referenced id is equals the current keyword id + { + //# collect all keywords from label attribute with a tokenizer + (*keywordExtsIt)->GetAttribute("label", keywordLabels); + + break; // break here; possibly search for other referenced keywords + } + } + } + + // add information as PrefPage + m_PrefPages.push_back(PrefPage(id, name, category, className, keywordLabels, cherry::IConfigurationElement::Pointer(*prefPagesIt))); + } + + } + + //#QWidget + + //# m_Keyword + m_Keyword = new QLineEdit(""); + //m_Keyword->installEventFilter(this); + QObject::connect(m_Keyword, SIGNAL(editingFinished()), this, SLOT(OnKeywordEditingFinished())); + QObject::connect(m_Keyword, SIGNAL(textChanged ( const QString & )), this, SLOT(OnKeywordTextChanged(const QString &))); + + //# m_PreferencesTree + m_PreferencesTree = new QTreeWidget; + m_PreferencesTree->setHeaderHidden(true); + QObject::connect(m_PreferencesTree, SIGNAL(itemSelectionChanged()), this, SLOT(OnPreferencesTreeItemSelectionChanged())); + + //# m_LeftLayout + m_LeftLayout = new QGridLayout; + m_LeftLayout->setContentsMargins(0,0,0,0); + m_LeftLayout->setSpacing(0); + m_LeftLayout->addWidget(m_Keyword, 0, 0); + m_LeftLayout->addWidget(m_PreferencesTree, 1, 0); + + //# m_LeftPanel + m_LeftPanel = new QWidget; + m_LeftPanel->setLayout(m_LeftLayout); + + //# m_Headline + m_Headline = new QLabel(""); + m_Headline->setStyleSheet("background-color: silver; " + "border-style: solid; border-width: 1px;" + "border-color: white; font: bold 13px; color: white;"); + + //# m_PreferencesPanel + m_PreferencesPanel = new QStackedWidget; + + //# m_RightLayout + m_RightLayout = new QGridLayout; + m_RightLayout->setRowStretch(0, 1); + m_RightLayout->setRowStretch(1, 20); + m_RightLayout->setContentsMargins(0,0,0,0); + m_RightLayout->setSpacing(0); + m_RightLayout->addWidget(m_Headline, 0, 0); + m_RightLayout->addWidget(m_PreferencesPanel, 1, 0); + + //# m_RightPanel + m_RightPanel = new QWidget; + m_RightPanel->setLayout(m_RightLayout); + + //# m_Splitter + m_Splitter = new QSplitter(Qt::Horizontal); + m_Splitter->setContentsMargins(0,0,0,0); + //m_Splitter->setFrameStyle(QFrame::Plain | QFrame::Sunken); + m_Splitter->setLineWidth(2); + m_Splitter->addWidget(m_LeftPanel); + m_Splitter->addWidget(m_RightPanel); + //QList sizes; sizes.push_back(this->width()*(1/3)); sizes.push_back(this->width()*(2/3)); + //m_Splitter->setSizes(sizes); + m_Splitter->setStretchFactor(0,0); + m_Splitter->setStretchFactor(1,2); + + //# m_ImportButton + m_ImportButton = new QPushButton(QString(tr("Import ..."))); + QObject::connect(m_ImportButton, SIGNAL(clicked(bool)), this, SLOT(OnImportButtonClicked(bool))); + m_ImportButton->setIcon(QIcon(":/org.mitk.gui.qt.application/edit-redo.png")); + m_ImportButton->setFlat(true); + m_ImportButton->setDefault(false); + + //# m_ExportButton + m_ExportButton = new QPushButton(QString(tr("Export ...")), this); + QObject::connect(m_ExportButton, SIGNAL(clicked(bool)), this, SLOT(OnExportButtonClicked(bool))); + m_ExportButton->setIcon(QIcon(":/org.mitk.gui.qt.application/edit-undo.png")); + m_ExportButton->setFlat(true); + m_ExportButton->setDefault(false); + + //# m_ApplyButton + m_ApplyButton = new QPushButton(QString(tr("Apply")), this); + QObject::connect(m_ApplyButton, SIGNAL(clicked(bool)), this, SLOT(OnApplyButtonClicked(bool))); + m_ApplyButton->setIcon(QIcon(":/org.mitk.gui.qt.application/document-save.png")); + m_ApplyButton->setFlat(true); + m_ApplyButton->setDefault(false); + + //# m_CloseButton + m_CloseButton = new QPushButton(QString(tr("Close")), this); + QObject::connect(m_CloseButton, SIGNAL(clicked(bool)), this, SLOT(OnCloseButtonClicked(bool))); + m_CloseButton->setIcon(QIcon(":/org.mitk.gui.qt.application/system-log-out.png")); + m_CloseButton->setFlat(true); + m_CloseButton->setDefault(true); + m_CloseButton->setFocus(); + + //# m_Layout + m_Layout = new QGridLayout; + //m_Layout->setContentsMargins(0,0,0,0); + //m_Layout->setSpacing(2); + //m_Layout->setRowStretch(0, 20); + //m_Layout->setRowStretch(1, 1); + m_Layout->addWidget(m_Splitter, 0, 0, 1, 4); + m_Layout->addWidget(m_ImportButton, 2, 0); + m_Layout->addWidget(m_ExportButton, 2, 1); + m_Layout->addWidget(m_ApplyButton, 2, 2); + m_Layout->addWidget(m_CloseButton, 2, 3); + + // this + this->setModal(true); + this->setSizeGripEnabled(true); + this->setWhatsThis("Dialog to set application wide preferences"); + this->setWindowIcon(QIcon(":/org.mitk.gui.qt.application/preferences-system.png")); + QRect parentGeometry = parent->geometry(); + int w = parentGeometry.width()/2; int h = parentGeometry.height()/2; + int x = parentGeometry.x()+(parentGeometry.width()-w)/2; + int y = parentGeometry.y()+(parentGeometry.height()-h)/2; + this->setGeometry(x,y,w,h); + this->setWindowTitle("Preferences"); + this->setLayout(m_Layout); + this->UpdateTree(); +} + +QmitkPreferencesDialog::~QmitkPreferencesDialog() +{ +} + + +void QmitkPreferencesDialog::OnImportButtonClicked( bool triggered ) +{ + int answer = QMessageBox::question(this, "Importing Preferences" + , "All existing preferences will be overwritten!\nAre you sure that you want to import other preferences?", QMessageBox::Yes | QMessageBox::No ); + if(answer == QMessageBox::No) + return; + + try + { + cherry::IPreferencesService::Pointer prefService = m_PreferencesService.Lock(); + if(prefService.IsNotNull()) + { + cherry::ICherryPreferencesService* cherryPrefService + = dynamic_cast(prefService.GetPointer()); + if(cherryPrefService != 0) + { + QFileDialog fd(this, "Choose file to import preferences", "", "XML files (*.xml)" ); + fd.setFileMode(QFileDialog::ExistingFile); + QStringList fileNames; + if (fd.exec()) + { + fileNames = fd.selectedFiles(); + if(fileNames.size()>0) + { + Poco::File f(fileNames.at(0).toStdString()); + cherryPrefService->ImportPreferences(f, ""); + LOG_INFO("QmitkPreferencesDialog") << "Preferences successfully imported from " << f.path(); + } + } + } + } + } + catch (Poco::Exception& pe) + { + QMessageBox::critical(this, "Error Importing", pe.message().c_str()); + LOG_ERROR("QmitkPreferencesDialog") << pe.what(); + } + catch (std::exception& e) + { + QMessageBox::critical(this, "Error Importing", e.what()); + LOG_ERROR("QmitkPreferencesDialog") << e.what(); + } +} + +void QmitkPreferencesDialog::OnExportButtonClicked( bool triggered ) +{ + try + { + cherry::IPreferencesService::Pointer prefService = m_PreferencesService.Lock(); + if(prefService.IsNotNull()) + { + cherry::ICherryPreferencesService* cherryPrefService + = dynamic_cast(prefService.GetPointer()); + if(cherryPrefService != 0) + { + QFileDialog fd(this, "Choose file to import preferences", "", "XML files (*.xml)" ); + fd.setFileMode(QFileDialog::AnyFile); + QStringList fileNames; + if (fd.exec()) + { + fileNames = fd.selectedFiles(); + if(fileNames.size()>0) + { + Poco::File f(fileNames.at(0).toStdString()); + cherryPrefService->ExportPreferences(f, ""); + LOG_INFO("QmitkPreferencesDialog") << "Preferences successfully exported to " << f.path(); + } + } + } + } + } + catch (Poco::Exception& pe) + { + QMessageBox::critical(this, "Error Exporting", pe.message().c_str()); + LOG_ERROR("QmitkPreferencesDialog") << pe.what(); + } + catch (std::exception& e) + { + QMessageBox::critical(this, "Error Exporting", e.what()); + LOG_ERROR("QmitkPreferencesDialog") << e.what(); + } +} + +void QmitkPreferencesDialog::OnApplyButtonClicked( bool triggered ) +{ + cherry::IQtPreferencePage* prefPage + = dynamic_cast(m_PreferencesPanel->currentWidget()); + if(prefPage) + if(prefPage->PerformOk()) + this->done(QDialog::Accepted); +} + +void QmitkPreferencesDialog::OnCloseButtonClicked( bool triggered ) +{ + cherry::IQtPreferencePage* prefPage + = dynamic_cast(m_PreferencesPanel->currentWidget()); + if(prefPage) + prefPage->PerformCancel(); + + this->done(QDialog::Accepted); +} + +void QmitkPreferencesDialog::OnKeywordTextChanged(const QString & s) +{ + // search for text + this->UpdateTree(); + +} + +void QmitkPreferencesDialog::OnKeywordEditingFinished() +{ +} + +bool QmitkPreferencesDialog::eventFilter( QObject *obj, QEvent *event ) +{ + if(obj = m_Keyword) + { + if(event->type() == QEvent::FocusIn && m_Keyword->text() == "search ...") + { + m_Keyword->setText(""); + m_Keyword->setStyleSheet("color: black;"); + } + else if(event->type() == QEvent::FocusOut && m_Keyword->text() == "") + { + m_Keyword->setText("search ..."); + m_Keyword->setStyleSheet("color: gray;"); + } + } + return true; +} + +void QmitkPreferencesDialog::OnPreferencesTreeItemSelectionChanged() +{ + if(m_PreferencesTree == 0) + return; + + // TODO: create page and show it + QList selectedItems = m_PreferencesTree->selectedItems(); + if(selectedItems.size()>0) + { + + for(vector::iterator it = m_PrefPages.begin(); + it != m_PrefPages.end(); ++it) + { + if(it->treeWidgetItem == selectedItems.at(0)) + { + m_Headline->setText(QString::fromStdString(it->name)); + if(it->prefPage == 0) + { + it->prefPage = it->confElem->CreateExecutableExtension("class"); + m_PreferencesPanel->addWidget(it->prefPage); + } + m_PreferencesPanel->setCurrentWidget(it->prefPage); + + break; + } + } + } +} + +void QmitkPreferencesDialog::UpdateTree() +{ + if(m_PreferencesTree == 0) + return; + + //m_PreferencesTree->clear(); + string keyword = m_Keyword->text().toStdString(); + + map items; + + for(vector::iterator it = m_PrefPages.begin(); + it != m_PrefPages.end(); ++it) + { + if(it->treeWidgetItem == 0) + { + + if(it->category.empty()) + { + it->treeWidgetItem = new QTreeWidgetItem(m_PreferencesTree); + } + else + { + it->treeWidgetItem = new QTreeWidgetItem(items[it->category]); + } + it->treeWidgetItem->setText(0, QString::fromStdString(it->name)); + items[it->id] = it->treeWidgetItem; + } + + // hide treeWidgetItem if keyword not matches + if(!keyword.empty()) + { + if( it->keywords.find(keyword) == string::npos ) + it->treeWidgetItem->setHidden(true); + else + { + //#make the whole branch visible + QTreeWidgetItem* treeWidgetParent = it->treeWidgetItem->parent(); + while(treeWidgetParent!=0) + { + treeWidgetParent->setHidden(false); + treeWidgetParent->setExpanded(true); + treeWidgetParent = treeWidgetParent->parent(); + } + + it->treeWidgetItem->setHidden(false); + QFont f = it->treeWidgetItem->font(0); + f.setBold(true); + it->treeWidgetItem->setFont(0, f); + } + } + else + { + QFont f = it->treeWidgetItem->font(0); + f.setBold(false); + it->treeWidgetItem->setFont(0, f); + it->treeWidgetItem->setHidden(false); + } + } + + if(m_PrefPages.size()>0) + { + if(m_PrefPages.front().treeWidgetItem != 0) + m_PrefPages.front().treeWidgetItem->setSelected(true); + } + +} + +bool QmitkPreferencesDialog::PrefPage::operator==( const PrefPage& other ) +{ + return id == other.id; +} + +bool QmitkPreferencesDialog::PrefPage::operator<( const PrefPage& other ) +{ + return name < other.name; +} + +QmitkPreferencesDialog::PrefPage::PrefPage( std::string _id, std::string _name, std::string _category + , std::string _className, std::string _keywords + , cherry::IConfigurationElement::Pointer _confElem ) +: id(_id) +, name(_name) +, category(_category) +, className(_className) +, keywords(_keywords) +, prefPage(0) +, confElem(_confElem) +, treeWidgetItem(0) +{ + +} \ No newline at end of file diff --git a/CoreUI/Bundles/org.mitk.gui.qt.application/src/internal/QmitkPreferencesDialog.h b/CoreUI/Bundles/org.mitk.gui.qt.application/src/internal/QmitkPreferencesDialog.h new file mode 100644 index 0000000000..8d0aa2bce3 --- /dev/null +++ b/CoreUI/Bundles/org.mitk.gui.qt.application/src/internal/QmitkPreferencesDialog.h @@ -0,0 +1,114 @@ +/*========================================================================= + + Program: openCherry Platform + Language: C++ + Date: $Date: 2009-02-22 15:57:29 +0100 (So, 22 Feb 2009) $ + Version: $Revision: 16375 $ + + Copyright (c) German Cancer Research Center, Division of Medical and + Biological Informatics. All rights reserved. + See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + + =========================================================================*/ + + +#ifndef CHERRYQMITKPREFERENCESDIALOG_H_ +#define CHERRYQMITKPREFERENCESDIALOG_H_ + +#include "cherryICherryPreferencesService.h" +#include "cherryIQtPreferencePage.h" +#include "cherryIConfigurationElement.h" + +#include + +class QVBoxLayout; +class QGridLayout; +class QHBoxLayout; +class QLineEdit; +class QTreeWidget; +class QLabel; +class QPushButton; +class QSplitter; +class QTreeWidgetItem; +class QStackedWidget; + +#include +#include + +class QmitkPreferencesDialog : public QDialog +{ + Q_OBJECT + +public: + QmitkPreferencesDialog(QWidget * parent = 0, Qt::WindowFlags f = 0); + ~QmitkPreferencesDialog(); + +protected slots: + void OnImportButtonClicked(bool triggered=false); + void OnExportButtonClicked(bool triggered=false); + void OnApplyButtonClicked(bool triggered=false); + void OnCloseButtonClicked(bool triggered=false); + void OnKeywordTextChanged(const QString & s); + void OnKeywordEditingFinished(); + void OnPreferencesTreeItemSelectionChanged(); + +protected: + /// + /// Just a stub class for holding information on prefpages (metadata) + /// + struct PrefPage + { + PrefPage(std::string _id, std::string _name, std::string _category + , std::string _className, std::string _keywords, cherry::IConfigurationElement::Pointer _confElem); + bool operator==(const PrefPage& other); + bool operator<(const PrefPage& other); + + std::string id; + std::string name; + std::string category; + std::string className; + std::string keywords; + cherry::IQtPreferencePage* prefPage; + cherry::IConfigurationElement::Pointer confElem; + QTreeWidgetItem* treeWidgetItem; + }; + + bool eventFilter(QObject *obj, QEvent *event); + void UpdateTree(); + + /// + /// The Preferences Service to retrieve and store preferences. + /// + cherry::IPreferencesService::WeakPtr m_PreferencesService; + + /// + /// Saves all treewidgetitems in a map, the key is the id of the preferencepage. + /// + std::vector m_PrefPages; + + //# QWidgets + QGridLayout* m_Layout; + QSplitter* m_Splitter; + + QWidget* m_LeftPanel; + QGridLayout* m_LeftLayout; + QLineEdit* m_Keyword; + QTreeWidget* m_PreferencesTree; + + QWidget* m_RightPanel; + QGridLayout* m_RightLayout; + QLabel* m_Headline; + QStackedWidget* m_PreferencesPanel; + + QPushButton* m_ImportButton; + QPushButton* m_ExportButton; + QPushButton* m_ApplyButton; + QPushButton* m_CloseButton; + +}; + +#endif /* CHERRYQMITKPREFERENCESDIALOG_H_ */ diff --git a/CoreUI/Bundles/org.mitk.gui.qt.application/src/internal/QmitkWorkbenchWindowAdvisor.cpp b/CoreUI/Bundles/org.mitk.gui.qt.application/src/internal/QmitkWorkbenchWindowAdvisor.cpp index 22343b9c11..db1d7e6ad2 100644 --- a/CoreUI/Bundles/org.mitk.gui.qt.application/src/internal/QmitkWorkbenchWindowAdvisor.cpp +++ b/CoreUI/Bundles/org.mitk.gui.qt.application/src/internal/QmitkWorkbenchWindowAdvisor.cpp @@ -1,166 +1,186 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "QmitkWorkbenchWindowAdvisor.h" #include "QmitkActionBarAdvisor.h" #include #include #include #include +#include #include #include +#include #include #include #include #include #include +#include "QmitkPreferencesDialog.h" // UGLYYY #include "QmitkWorkbenchWindowAdvisorHack.h" #include "mitkUndoController.h" #include "mitkVerboseLimitedLinearUndo.h" QmitkWorkbenchWindowAdvisorHelperHack* QmitkWorkbenchWindowAdvisorHelperHack::undohack = new QmitkWorkbenchWindowAdvisorHelperHack(); QmitkWorkbenchWindowAdvisor::QmitkWorkbenchWindowAdvisor(cherry::IWorkbenchWindowConfigurer::Pointer configurer) : cherry::WorkbenchWindowAdvisor(configurer) { } cherry::ActionBarAdvisor::Pointer QmitkWorkbenchWindowAdvisor::CreateActionBarAdvisor( cherry::IActionBarConfigurer::Pointer configurer) { cherry::ActionBarAdvisor::Pointer actionBarAdvisor(new QmitkActionBarAdvisor(configurer)); return actionBarAdvisor; } void QmitkWorkbenchWindowAdvisor::PostWindowCreate() { // very bad hack... cherry::IWorkbenchWindow::Pointer window = this->GetWindowConfigurer()->GetWindow(); QMainWindow* mainWindow = static_cast(window->GetShell()->GetControl()); + + // show maximized if preference is set + cherry::IPreferencesService::Pointer prefService + = cherry::Platform::GetServiceRegistry().GetServiceById(cherry::IPreferencesService::ID); + cherry::IPreferences::Pointer _GeneralPreferencesNode = prefService->GetSystemPreferences()->Node("/General"); + bool startMaximized = _GeneralPreferencesNode->GetBool("startMaximized", false); + if(startMaximized) + mainWindow->setWindowState(mainWindow->windowState() ^ Qt::WindowMaximized); + + QMenuBar* menuBar = mainWindow->menuBar(); QMenu* fileMenu = menuBar->addMenu("&File"); fileMenu->addAction(new QmitkFileOpenAction(window)); cherry::IViewRegistry* viewRegistry = cherry::PlatformUI::GetWorkbench()->GetViewRegistry(); const std::vector& viewDescriptors = viewRegistry->GetViews(); // another bad hack to get an edit/undo menu... QMenu* editMenu = menuBar->addMenu("&Edit"); QAction* undoAction = editMenu->addAction("&Undo", QmitkWorkbenchWindowAdvisorHelperHack::undohack, SLOT(onUndo()), QKeySequence("CTRL+Z")); QAction* redoAction = editMenu->addAction("&Redo", QmitkWorkbenchWindowAdvisorHelperHack::undohack, SLOT(onRedo()), QKeySequence("CTRL+Y")); + editMenu->addSeparator(); + QAction* preferencesAction = editMenu->addAction("&Preferences...", QmitkWorkbenchWindowAdvisorHelperHack::undohack, SLOT(onEditPreferences()), QKeySequence("CTRL+P")); QMenu* viewMenu = menuBar->addMenu("Show &View"); // sort elements (converting vector to map...) std::vector::const_iterator iter; std::map VDMap; for (iter = viewDescriptors.begin(); iter != viewDescriptors.end(); ++iter) { std::pair p((*iter)->GetLabel(), (*iter)); VDMap.insert(p); } std::map::const_iterator MapIter; for (MapIter = VDMap.begin(); MapIter != VDMap.end(); ++MapIter) { cherry::QtShowViewAction* viewAction = new cherry::QtShowViewAction(window, (*MapIter).second); //m_ViewActions.push_back(viewAction); viewMenu->addAction(viewAction); } QStatusBar* qStatusBar = new QStatusBar(); //creating a QmitkStatusBar for Output on the QStatusBar and connecting it with the MainStatusBar QmitkStatusBar *statusBar = new QmitkStatusBar(qStatusBar); //disabling the SizeGrip in the lower right corner statusBar->SetSizeGripEnabled(false); QmitkProgressBar *progBar = new QmitkProgressBar(); qStatusBar->addPermanentWidget(progBar, 0); progBar->hide(); mainWindow->setStatusBar(qStatusBar); QmitkMemoryUsageIndicatorView* memoryIndicator = new QmitkMemoryUsageIndicatorView(); qStatusBar->addPermanentWidget(memoryIndicator, 0); } //-------------------------------------------------------------------------------- // Ugly hack from here on. Feel free to delete when command framework // and undo buttons are done. //-------------------------------------------------------------------------------- QmitkWorkbenchWindowAdvisorHelperHack::QmitkWorkbenchWindowAdvisorHelperHack() :QObject() { } void QmitkWorkbenchWindowAdvisorHelperHack::onUndo() { mitk::UndoModel* model = mitk::UndoController::GetCurrentUndoModel(); if (model) { if (mitk::VerboseLimitedLinearUndo* verboseundo = dynamic_cast( model )) { mitk::VerboseLimitedLinearUndo::StackDescription descriptions = verboseundo->GetUndoDescriptions(); if (descriptions.size() >= 1) { LOG_INFO << "Undo " << descriptions.front().second; } } model->Undo(); } else { LOG_ERROR << "No undo model instantiated"; } } void QmitkWorkbenchWindowAdvisorHelperHack::onRedo() { mitk::UndoModel* model = mitk::UndoController::GetCurrentUndoModel(); if (model) { if (mitk::VerboseLimitedLinearUndo* verboseundo = dynamic_cast( model )) { mitk::VerboseLimitedLinearUndo::StackDescription descriptions = verboseundo->GetRedoDescriptions(); if (descriptions.size() >= 1) { LOG_INFO << "Redo " << descriptions.front().second; } } model->Redo(); } else { LOG_ERROR << "No undo model instantiated"; } } +void QmitkWorkbenchWindowAdvisorHelperHack::onEditPreferences() +{ + QmitkPreferencesDialog _PreferencesDialog(QApplication::activeWindow()); + _PreferencesDialog.exec(); +} \ No newline at end of file diff --git a/CoreUI/Bundles/org.mitk.gui.qt.application/src/internal/QmitkWorkbenchWindowAdvisorHack.h b/CoreUI/Bundles/org.mitk.gui.qt.application/src/internal/QmitkWorkbenchWindowAdvisorHack.h index e453e5c37c..cb02ea4496 100644 --- a/CoreUI/Bundles/org.mitk.gui.qt.application/src/internal/QmitkWorkbenchWindowAdvisorHack.h +++ b/CoreUI/Bundles/org.mitk.gui.qt.application/src/internal/QmitkWorkbenchWindowAdvisorHack.h @@ -1,17 +1,20 @@ #include +class QmitkPreferencesDialog; + class QmitkWorkbenchWindowAdvisorHelperHack : public QObject { Q_OBJECT public slots: void onUndo(); void onRedo(); + void onEditPreferences(); public: QmitkWorkbenchWindowAdvisorHelperHack(); static QmitkWorkbenchWindowAdvisorHelperHack* undohack; }; diff --git a/CoreUI/Qmitk/QmitkDataStorageTableModel.cpp b/CoreUI/Qmitk/QmitkDataStorageTableModel.cpp index c9a2156e59..9b48232558 100644 --- a/CoreUI/Qmitk/QmitkDataStorageTableModel.cpp +++ b/CoreUI/Qmitk/QmitkDataStorageTableModel.cpp @@ -1,528 +1,533 @@ #include "QmitkDataStorageTableModel.h" //# Own includes #include "mitkNodePredicateBase.h" #include "mitkProperties.h" #include "mitkRenderingManager.h" #include "QmitkEnums.h" #include "QmitkCustomVariants.h" //# Toolkit includes #include #include //#CTORS/DTOR QmitkDataStorageTableModel::QmitkDataStorageTableModel(mitk::DataStorage::Pointer _DataStorage , mitk::NodePredicateBase* _Predicate , QObject* parent ) : QAbstractTableModel(parent) , m_DataStorage(0) , m_Predicate(0) , m_BlockEvents(false) , m_SortDescending(false) { this->SetPredicate(_Predicate); this->SetDataStorage(_DataStorage); } QmitkDataStorageTableModel::~QmitkDataStorageTableModel() { // set data storage 0 to remove event listeners this->SetDataStorage(0); } //# Public GETTER const mitk::DataStorage::Pointer QmitkDataStorageTableModel::GetDataStorage() const { return m_DataStorage.GetPointer(); } mitk::NodePredicateBase::Pointer QmitkDataStorageTableModel::GetPredicate() const { return m_Predicate; } mitk::DataTreeNode::Pointer QmitkDataStorageTableModel::GetNode( const QModelIndex &index ) const { mitk::DataTreeNode::Pointer node; if(index.isValid()) { node = m_NodeSet.at(index.row()); } return node; } QVariant QmitkDataStorageTableModel::headerData(int section, Qt::Orientation orientation, int role) const { QVariant headerData; // show only horizontal header if ( role == Qt::DisplayRole ) { if( orientation == Qt::Horizontal ) { // first column: "Name" if(section == 0) headerData = "Name"; else if(section == 1) headerData = "Data Type"; else if(section == 2) headerData = "Visibility"; } else if( orientation == Qt::Vertical ) { // show numbers for rows headerData = section+1; } } return headerData; } Qt::ItemFlags QmitkDataStorageTableModel::flags(const QModelIndex &index) const { Qt::ItemFlags flags = QAbstractItemModel::flags(index); // name & visibility is editable if (index.column() == 0 || index.column() == 2) { flags |= Qt::ItemIsEditable; } return flags; } int QmitkDataStorageTableModel::rowCount(const QModelIndex &) const { return m_NodeSet.size(); } int QmitkDataStorageTableModel::columnCount(const QModelIndex &) const { // show name, type and visible columnn int columns = 3; return columns; } QVariant QmitkDataStorageTableModel::data(const QModelIndex &index, int role) const { QVariant data; if (index.isValid() && !m_NodeSet.empty()) { mitk::DataTreeNode::Pointer node = m_NodeSet.at(index.row()); std::string nodeName = node->GetName(); if(nodeName.empty()) nodeName = "unnamed"; // get name if(index.column() == 0) { // get name of node (may also be edited) if (role == Qt::DisplayRole || role == Qt::EditRole) { data = nodeName.c_str(); } else if (role == QmitkDataTreeNodeRole) { data = QVariant::fromValue(node); } } else if (index.column() == 1) { // Get DataType mitk::BaseData* mitkData = node->GetData(); std::string className; if(mitkData) { className = node->GetData()->GetNameOfClass(); bool isSegmentation = false; node->GetBoolProperty("segmentation", isSegmentation); // if we have a binary image, call it image mask if(className == "Image" && isSegmentation) className = "Image Mask"; } else className = "unknown"; // get type property of mitk::BaseData if (role == Qt::DisplayRole) { data = QString::fromStdString(className); } // show some nice icons for datatype else if(role == Qt::DecorationRole) { if(className == "Image") data = QIcon(":/datamanager/data-type-image-24.png"); else if(className == "Image Mask") data = QIcon(":/datamanager/data-type-image-mask-24.png"); else if(className == "Surface") data = QIcon(":/datamanager/data-type-mesh-24.png"); else if(className == "PointSet") data = QIcon(":/datamanager/data-type-pointset-24.png"); else if(className == "Geometry2DData" && nodeName == "widget1Plane") data = QIcon(":/datamanager/data-type-planegeometry1-24.png"); else if(className == "Geometry2DData" && nodeName == "widget2Plane") data = QIcon(":/datamanager/data-type-planegeometry2-24.png"); else if(className == "Geometry2DData" && nodeName == "widget3Plane") data = QIcon(":/datamanager/data-type-planegeometry3-24.png"); else data = QIcon(":/datamanager/data-type-unknown-24.png"); } } else if (index.column() == 2) { // get visible property of mitk::BaseData bool visibility = false; if(node->GetVisibility(visibility, 0)) { if (role == Qt::DisplayRole || role == Qt::EditRole) { data = visibility; } // role == Qt::DisplayRole } // node->GetVisibility(visibility, 0) } // index.column() == 2 } // index.isValid() && !m_NodeSet.empty() return data; } //# Public SETTERS void QmitkDataStorageTableModel::SetPredicate( mitk::NodePredicateBase* _Predicate ) { // ensure that a new predicate is set in order to avoid unnecessary changed events if(m_Predicate != _Predicate) { m_Predicate = _Predicate; this->Reset(); } } void QmitkDataStorageTableModel::SetDataStorage( mitk::DataStorage::Pointer _DataStorage ) { // only proceed if we have a new datastorage if(m_DataStorage.GetPointer() != _DataStorage.GetPointer()) { // if a data storage was set before remove old event listeners if(m_DataStorage != 0) { this->m_DataStorage->AddNodeEvent.RemoveListener( mitk::MessageDelegate1( this, &QmitkDataStorageTableModel::AddNode ) ); this->m_DataStorage->RemoveNodeEvent.RemoveListener( mitk::MessageDelegate1( this, &QmitkDataStorageTableModel::RemoveNode ) ); } // set new data storage m_DataStorage = _DataStorage.GetPointer(); // if new storage is not 0 subscribe for events if(m_DataStorage != 0) { // subscribe for node added/removed events this->m_DataStorage->AddNodeEvent.AddListener( mitk::MessageDelegate1( this, &QmitkDataStorageTableModel::AddNode ) ); this->m_DataStorage->RemoveNodeEvent.AddListener( mitk::MessageDelegate1( this, &QmitkDataStorageTableModel::RemoveNode ) ); } // Reset model (even if datastorage is 0->will be checked in Reset()) this->Reset(); } } void QmitkDataStorageTableModel::AddNode( const mitk::DataTreeNode* node ) { // garantuee no recursions when a new node event is thrown if(!m_BlockEvents) { // if we have a predicate, check node against predicate first if(m_Predicate.IsNotNull() && !m_Predicate->CheckNode(node)) return; // dont add nodes without data (formerly known as helper objects) if(node->GetData() == 0) return; // create listener commands to listen to changes in the name or the visibility of the node itk::MemberCommand::Pointer propertyModifiedCommand = itk::MemberCommand::New(); propertyModifiedCommand->SetCallbackFunction(this, &QmitkDataStorageTableModel::PropertyModified); mitk::BaseProperty* tempProperty = 0; // add listener for properties tempProperty = node->GetProperty("visible"); if(tempProperty) m_VisiblePropertyModifiedObserverTags[tempProperty] = tempProperty->AddObserver(itk::ModifiedEvent(), propertyModifiedCommand); tempProperty = node->GetProperty("name"); if(tempProperty) m_NamePropertyModifiedObserverTags[tempProperty] = tempProperty->AddObserver(itk::ModifiedEvent(), propertyModifiedCommand); // emit beginInsertRows event beginInsertRows(QModelIndex(), m_NodeSet.size(), m_NodeSet.size()); // add node m_NodeSet.push_back(const_cast(node)); // emit endInsertRows event endInsertRows(); } } void QmitkDataStorageTableModel::RemoveNode( const mitk::DataTreeNode* node ) { // garantuee no recursions when a new node event is thrown if(!m_BlockEvents) { // find corresponding node std::vector::iterator nodeIt = std::find(m_NodeSet.begin(), m_NodeSet.end(), node); if(nodeIt != m_NodeSet.end()) { // now: remove listeners for name property ... mitk::BaseProperty* tempProperty = 0; tempProperty = (*nodeIt)->GetProperty("visible"); if(tempProperty) tempProperty->RemoveObserver(m_VisiblePropertyModifiedObserverTags[tempProperty]); m_VisiblePropertyModifiedObserverTags.erase(tempProperty); // ... and visibility property tempProperty = (*nodeIt)->GetProperty("name"); if(tempProperty) tempProperty->RemoveObserver(m_NamePropertyModifiedObserverTags[tempProperty]); m_NamePropertyModifiedObserverTags.erase(tempProperty); // get an index from iterator int row = std::distance(m_NodeSet.begin(), nodeIt); // emit beginRemoveRows event (QModelIndex is empty because we dont have a tree model) this->beginRemoveRows(QModelIndex(), row, row); // remove node m_NodeSet.erase(nodeIt); // emit endRemoveRows event endRemoveRows(); } } } void QmitkDataStorageTableModel::PropertyModified( const itk::Object *caller, const itk::EventObject & ) { if(!m_BlockEvents) { // get modified property const mitk::BaseProperty* modifiedProperty = dynamic_cast(caller); if(modifiedProperty) { // find node that holds the modified property int row = -1; int column = -1; std::vector::iterator it; mitk::BaseProperty* visibilityProperty = 0; mitk::BaseProperty* nameProperty = 0; // search for property that changed and emit datachanged on the corresponding ModelIndex for(it=m_NodeSet.begin(); it!=m_NodeSet.end(); it++) { // check for the visible property or the name property visibilityProperty = (*it)->GetProperty("visible"); if(modifiedProperty == visibilityProperty) { column = 2; break; } nameProperty = (*it)->GetProperty("name"); if(modifiedProperty == nameProperty) { column = 0; break; } } // if we have the property we have a valid iterator if( it != m_NodeSet.end() ) row = std::distance(m_NodeSet.begin(), it); // now emit the dataChanged signal QModelIndex indexOfChangedProperty = index(row, column); emit dataChanged(indexOfChangedProperty, indexOfChangedProperty); } } } bool QmitkDataStorageTableModel::setData(const QModelIndex &index, const QVariant &value, int role) { bool noErr = false; if (index.isValid() && role == Qt::EditRole) { // any change events produced here should not be caught in this class // --> set m_BlockEvents to true m_BlockEvents = true; mitk::DataTreeNode::Pointer node = m_NodeSet.at(index.row()); if(index.column() == 0) { node->SetStringProperty("name", value.toString().toStdString().c_str()); } else if(index.column() == 2) { node->SetBoolProperty("visible", value.toBool()); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } // inform listeners about changes emit dataChanged(index, index); m_BlockEvents = false; noErr = true; } return noErr; } //#Protected SETTER void QmitkDataStorageTableModel::Reset() { mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet; // remove all nodes now (dont use iterators because removing elements // would invalidate the iterator) // start at the last element: first in, last out unsigned int i = m_NodeSet.size(); while(!m_NodeSet.empty()) { --i; this->RemoveNode(m_NodeSet.at(i)); } // normally now everything should be empty->just to be sure // erase all arrays again m_NamePropertyModifiedObserverTags.clear(); m_VisiblePropertyModifiedObserverTags.clear(); m_NodeSet.clear(); // the whole reset depends on the fact if a data storage is set or not if(m_DataStorage.IsNotNull()) { if(m_Predicate.IsNotNull()) // get subset _NodeSet = m_DataStorage->GetSubset(m_Predicate); // if predicate is NULL, select all nodes else { _NodeSet = m_DataStorage->GetAll(); // remove ghost root node } // finally add all nodes to the model for(mitk::DataStorage::SetOfObjects::const_iterator it=_NodeSet->begin(); it!=_NodeSet->end() ; it++) { // save node this->AddNode(*it); } } } void QmitkDataStorageTableModel::sort( int column, Qt::SortOrder order /*= Qt::AscendingOrder */ ) { bool sortDescending = (order == Qt::DescendingOrder) ? true: false; // do not sort twice !!! (dont know why, but qt calls this func twice. STUPID!) /* if(sortDescending != m_SortDescending) {*/ //m_SortDescending = sortDescending; DataTreeNodeCompareFunction::CompareCriteria _CompareCriteria = DataTreeNodeCompareFunction::CompareByName; DataTreeNodeCompareFunction::CompareOperator _CompareOperator = sortDescending ? DataTreeNodeCompareFunction::Greater: DataTreeNodeCompareFunction::Less; if(column == 1) _CompareCriteria = DataTreeNodeCompareFunction::CompareByClassName; else if(column == 2) _CompareCriteria = DataTreeNodeCompareFunction::CompareByVisibility; DataTreeNodeCompareFunction compareFunc(_CompareCriteria, _CompareOperator); std::sort(m_NodeSet.begin(), m_NodeSet.end(), compareFunc); QAbstractTableModel::reset(); //} } +std::vector QmitkDataStorageTableModel::GetNodeSet() const +{ + return m_NodeSet; +} + QmitkDataStorageTableModel::DataTreeNodeCompareFunction::DataTreeNodeCompareFunction( CompareCriteria _CompareCriteria , CompareOperator _CompareOperator ) : m_CompareCriteria(_CompareCriteria) , m_CompareOperator(_CompareOperator) { } bool QmitkDataStorageTableModel::DataTreeNodeCompareFunction::operator() ( const mitk::DataTreeNode::Pointer& _Left , const mitk::DataTreeNode::Pointer& _Right ) const { switch(m_CompareCriteria) { case CompareByClassName: if(m_CompareOperator == Less) return (_Left->GetData()->GetNameOfClass() < _Right->GetData()->GetNameOfClass() ); else return (_Left->GetData()->GetNameOfClass() > _Right->GetData()->GetNameOfClass() ); break; case CompareByVisibility: { bool _LeftVisibility = false; bool _RightVisibility = false; _Left->GetVisibility(_LeftVisibility, 0); _Right->GetVisibility(_RightVisibility, 0); if(m_CompareOperator == Less) return (_LeftVisibility < _RightVisibility); else return (_LeftVisibility > _RightVisibility); } break; // CompareByName: default: if(m_CompareOperator == Less) return (_Left->GetName() < _Right->GetName()); else return (_Left->GetName() > _Right->GetName()); break; } } diff --git a/CoreUI/Qmitk/QmitkDataStorageTableModel.h b/CoreUI/Qmitk/QmitkDataStorageTableModel.h index 9c5cf99f90..243744cb11 100644 --- a/CoreUI/Qmitk/QmitkDataStorageTableModel.h +++ b/CoreUI/Qmitk/QmitkDataStorageTableModel.h @@ -1,206 +1,210 @@ #ifndef QmitkDataStorageTableModel_h #define QmitkDataStorageTableModel_h /// Own includes. #include "mitkDataStorage.h" #include "mitkBaseProperty.h" #include "mitkWeakPointer.h" #include "mitkNodePredicateBase.h" /// Toolkit includes. #include /// Forward declarations. /// /// \class QmitkDataStorageTableModel /// /// \brief A table model for a set of DataTreeNodes defined by a predicate. /// \TODO make columns interchangeable, select which properties to show as columns /// class QMITK_EXPORT QmitkDataStorageTableModel : public QAbstractTableModel { Q_OBJECT //#Ctors/Dtor public: /// /// Constructs a new QmitkDataStorageTableModel and sets a predicate that defines /// this list. /// \see setPredicate() /// QmitkDataStorageTableModel(mitk::DataStorage::Pointer _DataStorage, mitk::NodePredicateBase* _Predicate = 0 , QObject* parent = 0 ); /// /// Standard dtor. Delete predicate, disconnect from DataStorage. /// virtual ~QmitkDataStorageTableModel(); //# Public GETTER public: /// /// Get the DataStorage. /// const mitk::DataStorage::Pointer GetDataStorage() const; /// /// Get the predicate. /// mitk::NodePredicateBase::Pointer GetPredicate() const; /// /// Get node at a specific model index. Another way to implement this, is /// by introducing a new role like "DateTreeNode" and capture /// that in the data function. /// mitk::DataTreeNode::Pointer GetNode(const QModelIndex &index) const; /// /// Overridden from QAbstractTableModel. Returns the header data at section /// for given orientation and role. /// QVariant headerData(int section, Qt::Orientation orientation, int role) const; /// /// Overridden from QAbstractTableModel. Returns what can be done /// with an item. /// Qt::ItemFlags flags(const QModelIndex &index) const; /// /// Overridden from QAbstractTableModel. Returns the node count. /// int rowCount(const QModelIndex &parent) const; /// /// Overridden from QAbstractTableModel. Returns the number of features (columns) to display. /// int columnCount(const QModelIndex &parent) const; /// /// Overridden from QAbstractTableModel. Returns the data at index for given role. /// QVariant data(const QModelIndex &index, int role) const; //# Public SETTERS public: /// /// Sets the DataStorage. /// void SetDataStorage(mitk::DataStorage::Pointer _DataStorage); /// /// Sets the predicate. QmitkDataStorageTableModel is owner of the predicate! /// void SetPredicate(mitk::NodePredicateBase* _Predicate); /// /// Adds a node to this model. /// There are two constraints for nodes in this model: /// 1. If a predicate is set (not null) the node will be checked against it. /// 2. The node has to have a data object (no one wants to see empty nodes). /// Also adds event listeners to the node. /// virtual void AddNode(const mitk::DataTreeNode* node); /// /// Removes a node from this model. Also removes any event listener from the node. /// virtual void RemoveNode(const mitk::DataTreeNode* node); /// + /// Returns a copy of the node-vector that is shown by this model + /// + virtual std::vector GetNodeSet() const; + /// /// \brief Called when a single property was changed. /// The function searches through the list of nodes in this model for the changed /// property. If the property was found a dataChanged signal is emitted forcing /// all observing views to request the data again. /// virtual void PropertyModified(const itk::Object *caller, const itk::EventObject &event); /// /// Overridden from QAbstractTableModel. Sets data at index for given role. /// bool setData(const QModelIndex &index, const QVariant &value, int role); /// /// \brief Reimplemented sort function from QAbstractTableModel to enable sorting on the table. /// void sort ( int column, Qt::SortOrder order = Qt::AscendingOrder ); //#PROTECTED INNER CLASSES protected: /// /// \struct DataTreeNodeCompareFunction /// \brief A struct that inherits from std::binary_function. You can use it in std::sort algorithm for sorting the node list elements. /// struct DataTreeNodeCompareFunction : public std::binary_function { /// /// \brief Specifies field of the property with which it will be sorted. /// enum CompareCriteria { CompareByName = 0, CompareByClassName, CompareByVisibility }; /// /// \brief Specifies Ascending/descending ordering. /// enum CompareOperator { Less = 0, Greater }; /// /// \brief Creates a PropertyDataSetCompareFunction. A CompareCriteria and a CompareOperator must be given. /// DataTreeNodeCompareFunction(CompareCriteria _CompareCriteria = CompareByName, CompareOperator _CompareOperator = Less); /// /// \brief The reimplemented compare function. /// bool operator()(const mitk::DataTreeNode::Pointer& _Left , const mitk::DataTreeNode::Pointer& _Right) const; protected: CompareCriteria m_CompareCriteria; CompareOperator m_CompareOperator; }; //#Protected SETTER protected: /// /// Called when DataStorage or Predicate changed. Resets whole model and reads all nodes /// in again. /// virtual void Reset(); //#Protected MEMBER VARIABLES protected: /// /// Pointer to the DataStorage from which the nodes are selected (remember: in OpenCherry there /// might be more than one DataStorage). /// Store it in a weak pointer. This is a GUI class which should not hold a strong reference /// to any non-GUI Object. /// mitk::WeakPointer m_DataStorage; /// /// Holds the predicate that defines this SubSet of Nodes. If m_Predicate /// is NULL all Nodes will be selected. /// mitk::NodePredicateBase::Pointer m_Predicate; /// /// Holds all selected Nodes. /// std::vector m_NodeSet; /// /// \brief Maps a property to an observer tag. /// std::map m_NamePropertyModifiedObserverTags; /// /// \brief Maps a property to an observer tag. /// std::map m_VisiblePropertyModifiedObserverTags; /// /// Saves if this model is currently working on events to prevent endless event loops. /// bool m_BlockEvents; /// /// \brief The property is true when the property list is sorted in descending order. /// bool m_SortDescending; }; #endif