diff --git a/Modules/ImageStatisticsUI/Qmitk/QmitkStatisticsModelToStringConverter.cpp b/Modules/ImageStatisticsUI/Qmitk/QmitkStatisticsModelToStringConverter.cpp index 9ddad668b6..fbcc3f80cd 100644 --- a/Modules/ImageStatisticsUI/Qmitk/QmitkStatisticsModelToStringConverter.cpp +++ b/Modules/ImageStatisticsUI/Qmitk/QmitkStatisticsModelToStringConverter.cpp @@ -1,128 +1,128 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "QmitkStatisticsModelToStringConverter.h" #include "mitkExceptionMacro.h" QmitkStatisticsModelToStringConverter::QmitkStatisticsModelToStringConverter() {} void QmitkStatisticsModelToStringConverter::SetModel(QmitkImageStatisticsTreeModel *model) { m_statisticsModel = model; } void QmitkStatisticsModelToStringConverter::SetRootIndex(QModelIndex rootIndex) { m_rootIndex = rootIndex; } QString QmitkStatisticsModelToStringConverter::GetString() const { if (m_statisticsModel == nullptr) { mitkThrow() << "Cannot convert TableModel to String: TableModel is nullptr"; } QString textData; int columns = m_statisticsModel->columnCount(); if (m_includeHeaderData) { for (int i = 0; i < columns; i++) { if (i > 0) { textData += m_columnDelimiter; } textData += m_statisticsModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString(); } textData += m_rowDelimiter; } textData += Iterate(m_rootIndex, m_statisticsModel); return textData; } void QmitkStatisticsModelToStringConverter::SetRowDelimiter(QChar rowDelimiter) { m_rowDelimiter = rowDelimiter; } void QmitkStatisticsModelToStringConverter::SetColumnDelimiter(QChar columnDelimiter) { m_columnDelimiter = columnDelimiter; } void QmitkStatisticsModelToStringConverter::SetIncludeHeaderData(bool includeHeaderData) { m_includeHeaderData = includeHeaderData; } QString QmitkStatisticsModelToStringConverter::Iterate(const QModelIndex &index, const QmitkImageStatisticsTreeModel *model, QString label) const { QString content; if (model->hasChildren(index)) { if (index.isValid()) { label += index.data().toString() + QString(" >> "); } auto rows = model->rowCount(index); for (int r = 0; r < rows; ++r) { auto childIndex = model->index(r, 0, index); if (model->hasChildren(childIndex)) { content += Iterate(childIndex, model, label); } else { content += label; auto cols = model->columnCount(index); for (int c = 0; c < cols; ++c) { if (c > 0) { content += m_columnDelimiter; } auto columnChildIndex = model->index(r, c, index); content += Iterate(columnChildIndex, model, label); } content += m_rowDelimiter; } } } else { if (index.isValid()) { auto data = index.data(); - if (static_cast(data.type()) == QMetaType::Double) + if (data.typeId() == QMetaType::Double) { content = QString("%L1").arg(data.toDouble(), 0, 'f'); } else { content = data.toString(); } } } return content; } diff --git a/Modules/MatchPointRegistrationUI/Qmitk/QmitkMapPropertyDelegate.cpp b/Modules/MatchPointRegistrationUI/Qmitk/QmitkMapPropertyDelegate.cpp index 9d510b60be..2a194df5f2 100644 --- a/Modules/MatchPointRegistrationUI/Qmitk/QmitkMapPropertyDelegate.cpp +++ b/Modules/MatchPointRegistrationUI/Qmitk/QmitkMapPropertyDelegate.cpp @@ -1,268 +1,266 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef NOMINMAX #define NOMINMAX #endif #include "QmitkMapPropertyDelegate.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include QmitkMapPropertyDelegate::QmitkMapPropertyDelegate(QObject * /*parent*/) { } void QmitkMapPropertyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { QVariant data = index.data(Qt::DisplayRole); QString name = data.value(); QStyledItemDelegate::paint(painter, option, index); } QWidget *QmitkMapPropertyDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { QVariant data = index.data(Qt::EditRole); QVariant displayData = index.data(Qt::DisplayRole); QString name = index.model()->data(index.model()->index(index.row(), index.column() - 1)).value(); if (data.isValid()) { QWidget *editorWidget = nullptr; - if (data.type() == QVariant::Int) + if (data.typeId() == QMetaType::Int) { QSpinBox *spinBox = new QSpinBox(parent); spinBox->setSingleStep(1); spinBox->setMinimum(std::numeric_limits::min()); spinBox->setMaximum(std::numeric_limits::max()); editorWidget = spinBox; } - // see qt documentation. cast is correct, it would be obsolete if we - // store doubles - else if (static_cast(data.type()) == QMetaType::Float) + else if (data.typeId() == QMetaType::Float) { QDoubleSpinBox *spinBox = new QDoubleSpinBox(parent); spinBox->setDecimals(5); spinBox->setSingleStep(0.1); spinBox->setMinimum(std::numeric_limits::min()); spinBox->setMaximum(std::numeric_limits::max()); editorWidget = spinBox; } - else if (data.type() == QVariant::StringList) + else if (data.typeId() == QMetaType::QStringList) { QStringList entries = data.value(); QComboBox *comboBox = new QComboBox(parent); comboBox->setEditable(false); comboBox->addItems(entries); editorWidget = comboBox; } else { editorWidget = QStyledItemDelegate::createEditor(parent, option, index); } if (editorWidget) { // install event filter editorWidget->installEventFilter(const_cast(this)); } return editorWidget; } else return new QLabel(displayData.toString(), parent); } void QmitkMapPropertyDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { QVariant data = index.data(Qt::EditRole); QVariant displayData = index.data(Qt::DisplayRole); std::cout << "Set EDITOR DATA : " << data.toDouble() << std::endl; if (data.isValid()) { - if (data.type() == QVariant::Int) + if (data.typeId() == QMetaType::Int) { QSpinBox *spinBox = qobject_cast(editor); spinBox->setValue(data.toInt()); } // see qt documentation. cast is correct, it would be obsolete if we // store doubles - else if (static_cast(data.type()) == QMetaType::Float) + else if (data.typeId() == QMetaType::Float) { QDoubleSpinBox *spinBox = qobject_cast(editor); spinBox->setValue(data.toDouble()); std::cout << "Set EDITOR DATA : " << spinBox->value() << std::endl; } - else if (data.type() == QVariant::StringList) + else if (data.typeId() == QMetaType::QStringList) { QComboBox *comboBox = qobject_cast(editor); QString displayString = displayData.value(); comboBox->setCurrentIndex(comboBox->findData(displayString)); } else return QStyledItemDelegate::setEditorData(editor, index); } } void QmitkMapPropertyDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { QVariant data = index.data(Qt::EditRole); QVariant displayData = index.data(Qt::DisplayRole); if (data.isValid()) { - if (data.type() == QVariant::Color) + if (data.typeId() == QMetaType::QColor) { QWidget *colorBtn = qobject_cast(editor); auto colorVariant = QVariant::fromValue(colorBtn->palette().color(QPalette::Button)); model->setData(index, colorVariant); } - else if (data.type() == QVariant::Int) + else if (data.typeId() == QMetaType::Int) { QSpinBox *spinBox = qobject_cast(editor); int intValue = spinBox->value(); QVariant intValueVariant; intValueVariant.setValue(static_cast(intValue)); model->setData(index, intValueVariant); } - else if (static_cast(data.type()) == QMetaType::Float) + else if (data.typeId() == QMetaType::Float) { QDoubleSpinBox *spinBox = qobject_cast(editor); double doubleValue = spinBox->value(); std::cout << "SET MODEL DATA << FLOAT : " << doubleValue << std::endl; QVariant doubleValueVariant; doubleValueVariant.setValue(static_cast(doubleValue)); std::cout << "SET MODEL DATA << Variant : " << doubleValue << std::endl; model->setData(index, doubleValueVariant); } - else if (data.type() == QVariant::StringList) + else if (data.typeId() == QMetaType::QStringList) { QString displayData = data.value(); QComboBox *comboBox = qobject_cast(editor); QString comboBoxValue = comboBox->currentText(); auto comboBoxValueVariant = QVariant::fromValue(comboBoxValue); model->setData(index, comboBoxValueVariant); } else QStyledItemDelegate::setModelData(editor, model, index); } } void QmitkMapPropertyDelegate::commitAndCloseEditor() { QWidget *editor = nullptr; if (QPushButton *pushBtn = qobject_cast(sender())) { editor = pushBtn; } if (editor) { emit commitData(editor); emit closeEditor(editor); } } void QmitkMapPropertyDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex & /*index*/) const { editor->setGeometry(option.rect); } void QmitkMapPropertyDelegate::ComboBoxCurrentIndexChanged(int /*index*/) { if (QComboBox *comboBox = qobject_cast(sender())) { emit commitData(comboBox); emit closeEditor(comboBox); } } void QmitkMapPropertyDelegate::SpinBoxValueChanged(const QString & /*value*/) { QAbstractSpinBox *spinBox = nullptr; if ((spinBox = qobject_cast(sender())) || (spinBox = qobject_cast(sender()))) { emit commitData(spinBox); emit closeEditor(spinBox); } } void QmitkMapPropertyDelegate::showColorDialog() { } bool QmitkMapPropertyDelegate::eventFilter(QObject *o, QEvent *e) { // filter all kind of events on our editor widgets // when certain events occur, repaint all render windows, because rendering relevant properties might have changed switch (e->type()) { case QEvent::KeyRelease: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: case QEvent::Wheel: case QEvent::FocusIn: { if (QWidget *editor = dynamic_cast(o)) { emit commitData(editor); } break; } default: { break; } } return false; } diff --git a/Modules/QtWidgets/src/QmitkPropertyDelegate.cpp b/Modules/QtWidgets/src/QmitkPropertyDelegate.cpp index ca972a3729..2c309928a8 100644 --- a/Modules/QtWidgets/src/QmitkPropertyDelegate.cpp +++ b/Modules/QtWidgets/src/QmitkPropertyDelegate.cpp @@ -1,320 +1,319 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef NOMINMAX #define NOMINMAX #endif #include "QmitkPropertyDelegate.h" #include "QmitkCustomVariants.h" #include "mitkRenderingManager.h" #include #include #include #include #include #include #include #include #include #include #include #include QmitkPropertyDelegate::QmitkPropertyDelegate(QObject * /*parent*/) { } void QmitkPropertyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { QVariant data = index.data(Qt::DisplayRole); QString name = data.value(); - if (index.column() == 1 && data.type() == QVariant::Color) + if (index.column() == 1 && data.typeId() == QMetaType::QColor) { QColor qcol = data.value(); painter->save(); painter->fillRect(option.rect, qcol); QRect rect = option.rect; rect.setWidth(rect.width() - 1); rect.setHeight(rect.height() - 1); QPen pen; pen.setWidth(1); painter->setPen(pen); painter->drawRect(rect); painter->restore(); } else { QStyledItemDelegate::paint(painter, option, index); } } QWidget *QmitkPropertyDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { QVariant data = index.data(Qt::EditRole); QVariant displayData = index.data(Qt::DisplayRole); QString name = index.model()->data(index.model()->index(index.row(), index.column() - 1)).value(); if (data.isValid()) { QWidget *editorWidget = nullptr; - if (data.type() == QVariant::Color) + if (data.typeId() == QMetaType::QColor) { auto colorBtn = new QPushButton(parent); QColor color = data.value(); QColor result = QColorDialog::getColor(color); if (result.isValid()) { QPalette palette = colorBtn->palette(); palette.setColor(QPalette::Button, result); colorBtn->setPalette(palette); colorBtn->setStyleSheet( QString("background-color: %1;foreground-color: %1; border-style: none;").arg(result.name())); } // QColorDialog closed by 'Cancel' button, use the old property color else { QPalette palette = colorBtn->palette(); palette.setColor(QPalette::Button, color); colorBtn->setPalette(palette); colorBtn->setStyleSheet( QString("background-color: %1;foreground-color: %1; border-style: none;").arg(color.name())); } connect(colorBtn, SIGNAL(pressed()), this, SLOT(commitAndCloseEditor())); editorWidget = colorBtn; } - else if (data.type() == QVariant::Int) + else if (data.typeId() == QMetaType::Int) { auto spinBox = new QSpinBox(parent); spinBox->setSingleStep(1); spinBox->setMinimum(std::numeric_limits::min()); spinBox->setMaximum(std::numeric_limits::max()); editorWidget = spinBox; } - // see qt documentation. cast is correct, it would be obsolete if we - // store doubles - else if (static_cast(data.type()) == QMetaType::Float) + + else if (data.typeId() == QMetaType::Float) { auto spinBox = new QDoubleSpinBox(parent); spinBox->setDecimals(2); spinBox->setSingleStep(0.1); if (name == "opacity") { spinBox->setMinimum(0.0); spinBox->setMaximum(1.0); } else { spinBox->setMinimum(std::numeric_limits::min()); spinBox->setMaximum(std::numeric_limits::max()); } editorWidget = spinBox; } - else if (data.type() == QVariant::StringList) + else if (data.typeId() == QMetaType::QStringList) { QStringList entries = data.value(); auto comboBox = new QComboBox(parent); comboBox->setEditable(false); comboBox->addItems(entries); editorWidget = comboBox; } else { editorWidget = QStyledItemDelegate::createEditor(parent, option, index); } if (editorWidget) { // install event filter editorWidget->installEventFilter(const_cast(this)); } return editorWidget; } else return new QLabel(displayData.toString(), parent); } void QmitkPropertyDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { QVariant data = index.data(Qt::EditRole); QVariant displayData = index.data(Qt::DisplayRole); if (data.isValid()) { - if (data.type() == QVariant::Int) + if (data.typeId() == QMetaType::Int) { QSpinBox *spinBox = qobject_cast(editor); spinBox->setValue(data.toInt()); } // see qt documentation. cast is correct, it would be obsolete if we // store doubles - else if (static_cast(data.type()) == QMetaType::Float) + else if (data.typeId() == QMetaType::Float) { QDoubleSpinBox *spinBox = qobject_cast(editor); spinBox->setValue(data.toDouble()); } - else if (data.type() == QVariant::StringList) + else if (data.typeId() == QMetaType::QStringList) { QComboBox *comboBox = qobject_cast(editor); QString displayString = displayData.value(); comboBox->setCurrentIndex(comboBox->findData(displayString)); } else return QStyledItemDelegate::setEditorData(editor, index); } } void QmitkPropertyDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { QVariant data = index.data(Qt::EditRole); QVariant displayData = index.data(Qt::DisplayRole); if (data.isValid()) { - if (data.type() == QVariant::Color) + if (data.typeId() == QMetaType::QColor) { QWidget *colorBtn = qobject_cast(editor); QVariant colorVariant; colorVariant.setValue(colorBtn->palette().color(QPalette::Button)); model->setData(index, colorVariant); } - else if (data.type() == QVariant::Int) + else if (data.typeId() == QMetaType::Int) { QSpinBox *spinBox = qobject_cast(editor); int intValue = spinBox->value(); QVariant intValueVariant; intValueVariant.setValue(static_cast(intValue)); model->setData(index, intValueVariant); } - else if (static_cast(data.type()) == QMetaType::Float) + else if (data.typeId() == QMetaType::Float) { QDoubleSpinBox *spinBox = qobject_cast(editor); double doubleValue = spinBox->value(); QVariant doubleValueVariant; doubleValueVariant.setValue(static_cast(doubleValue)); model->setData(index, doubleValueVariant); } - else if (data.type() == QVariant::StringList) + else if (data.typeId() == QMetaType::QStringList) { QString displayData = data.value(); QComboBox *comboBox = qobject_cast(editor); QString comboBoxValue = comboBox->currentText(); QVariant comboBoxValueVariant; comboBoxValueVariant.setValue(comboBoxValue); model->setData(index, comboBoxValueVariant); } else QStyledItemDelegate::setModelData(editor, model, index); } } void QmitkPropertyDelegate::commitAndCloseEditor() { QWidget *editor = nullptr; if (QPushButton *pushBtn = qobject_cast(sender())) { editor = pushBtn; } if (editor) { emit commitData(editor); emit closeEditor(editor); } } void QmitkPropertyDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex & /*index*/) const { editor->setGeometry(option.rect); } void QmitkPropertyDelegate::ComboBoxCurrentIndexChanged(int /*index*/) { if (QComboBox *comboBox = qobject_cast(sender())) { emit commitData(comboBox); emit closeEditor(comboBox); } } void QmitkPropertyDelegate::SpinBoxValueChanged(const QString & /*value*/) { QAbstractSpinBox *spinBox = nullptr; if ((spinBox = qobject_cast(sender())) || (spinBox = qobject_cast(sender()))) { emit commitData(spinBox); emit closeEditor(spinBox); } } void QmitkPropertyDelegate::showColorDialog() { } bool QmitkPropertyDelegate::eventFilter(QObject *o, QEvent *e) { // filter all kind of events on our editor widgets // when certain events occur, repaint all render windows, because rendering relevant properties might have changed switch (e->type()) { case QEvent::KeyRelease: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: case QEvent::Wheel: case QEvent::FocusIn: { if (QWidget *editor = dynamic_cast(o)) { emit commitData(editor); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); break; } default: { break; } } return false; } diff --git a/Modules/QtWidgets/src/QmitkRenderWindow.cpp b/Modules/QtWidgets/src/QmitkRenderWindow.cpp index ab9657b238..669bf58cbe 100644 --- a/Modules/QtWidgets/src/QmitkRenderWindow.cpp +++ b/Modules/QtWidgets/src/QmitkRenderWindow.cpp @@ -1,516 +1,518 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "QmitkRenderWindow.h" #include "mitkInteractionKeyEvent.h" #include "mitkInternalEvent.h" #include "mitkMouseDoubleClickEvent.h" #include "mitkMouseMoveEvent.h" #include "mitkMousePressEvent.h" #include "mitkMouseReleaseEvent.h" #include "mitkMouseWheelEvent.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include QmitkRenderWindow::QmitkRenderWindow(QWidget *parent, const QString &name, mitk::VtkPropRenderer *) : QVTKOpenGLNativeWidget(parent) , m_ResendQtEvents(true) , m_MenuWidget(nullptr) , m_MenuWidgetActivated(false) , m_LayoutIndex(QmitkRenderWindowMenu::LayoutIndex::Axial) , m_GeometryViolationWarningOverlay(nullptr) { m_InternalRenderWindow = vtkSmartPointer::New(); m_InternalRenderWindow->SetMultiSamples(0); m_InternalRenderWindow->SetAlphaBitPlanes(0); setRenderWindow(m_InternalRenderWindow); Initialize(name.toStdString().c_str()); setFocusPolicy(Qt::StrongFocus); setMouseTracking(true); QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); setSizePolicy(sizePolicy); // setup overlay widget to show a warning message with a button m_GeometryViolationWarningOverlay = new QmitkButtonOverlayWidget(this); m_GeometryViolationWarningOverlay->setVisible(false); m_GeometryViolationWarningOverlay->SetOverlayText( QStringLiteral("

Interaction is not possible because the " "render window geometry
does not match the interaction reference geometry.

")); m_GeometryViolationWarningOverlay->SetButtonText("Reset geometry"); m_GeometryViolationWarningOverlay->SetButtonIcon(QmitkStyleManager::ThemeIcon(QLatin1String(":/Qmitk/reset.svg"))); connect(m_GeometryViolationWarningOverlay, &QmitkButtonOverlayWidget::Clicked, this, &QmitkRenderWindow::ResetGeometry); } QmitkRenderWindow::~QmitkRenderWindow() { Destroy(); // Destroy mitkRenderWindowBase } void QmitkRenderWindow::SetResendQtEvents(bool resend) { m_ResendQtEvents = resend; } void QmitkRenderWindow::SetLayoutIndex(QmitkRenderWindowMenu::LayoutIndex layoutIndex) { m_LayoutIndex = layoutIndex; if (nullptr != m_MenuWidget) { m_MenuWidget->SetLayoutIndex(layoutIndex); } } QmitkRenderWindowMenu::LayoutIndex QmitkRenderWindow::GetLayoutIndex() { if (nullptr != m_MenuWidget) { return m_MenuWidget->GetLayoutIndex(); } else { return QmitkRenderWindowMenu::LayoutIndex::Axial; } } void QmitkRenderWindow::UpdateLayoutDesignList(QmitkRenderWindowMenu::LayoutDesign layoutDesign) { if (nullptr != m_MenuWidget) { m_MenuWidget->UpdateLayoutDesignList(layoutDesign); } } void QmitkRenderWindow::UpdateCrosshairVisibility(bool visible) { m_MenuWidget->UpdateCrosshairVisibility(visible); } void QmitkRenderWindow::UpdateCrosshairRotationMode(int mode) { m_MenuWidget->UpdateCrosshairRotationMode(mode); } void QmitkRenderWindow::ActivateMenuWidget(bool state) { if (nullptr == m_MenuWidget) { m_MenuWidget = new QmitkRenderWindowMenu(this, {}, m_Renderer); m_MenuWidget->SetLayoutIndex(m_LayoutIndex); } if (m_MenuWidgetActivated == state) { // no new state; nothing to do return; } m_MenuWidgetActivated = state; if (m_MenuWidgetActivated) { connect(m_MenuWidget, &QmitkRenderWindowMenu::LayoutDesignChanged, this, &QmitkRenderWindow::LayoutDesignChanged); connect(m_MenuWidget, &QmitkRenderWindowMenu::ResetView, this, &QmitkRenderWindow::ResetView); connect(m_MenuWidget, &QmitkRenderWindowMenu::CrosshairVisibilityChanged, this, &QmitkRenderWindow::CrosshairVisibilityChanged); connect(m_MenuWidget, &QmitkRenderWindowMenu::CrosshairRotationModeChanged, this, &QmitkRenderWindow::CrosshairRotationModeChanged); } else { disconnect(m_MenuWidget, &QmitkRenderWindowMenu::LayoutDesignChanged, this, &QmitkRenderWindow::LayoutDesignChanged); disconnect(m_MenuWidget, &QmitkRenderWindowMenu::ResetView, this, &QmitkRenderWindow::ResetView); disconnect(m_MenuWidget, &QmitkRenderWindowMenu::CrosshairVisibilityChanged, this, &QmitkRenderWindow::CrosshairVisibilityChanged); disconnect(m_MenuWidget, &QmitkRenderWindowMenu::CrosshairRotationModeChanged, this, &QmitkRenderWindow::CrosshairRotationModeChanged); m_MenuWidget->hide(); } } void QmitkRenderWindow::ShowOverlayMessage(bool show) { m_GeometryViolationWarningOverlay->setVisible(show); } void QmitkRenderWindow::moveEvent(QMoveEvent *event) { QVTKOpenGLNativeWidget::moveEvent(event); // after a move the overlays need to be positioned emit moved(); } void QmitkRenderWindow::showEvent(QShowEvent *event) { QVTKOpenGLNativeWidget::showEvent(event); // this singleshot is necessary to have the overlays positioned correctly after initial show // simple call of moved() is no use here!! QTimer::singleShot(0, this, SIGNAL(moved())); } bool QmitkRenderWindow::event(QEvent* e) { mitk::InteractionEvent::Pointer mitkEvent = nullptr; mitk::Point2D mousePosition; bool updateStatusBar = false; switch (e->type()) { case QEvent::MouseMove: { auto me = static_cast(e); mousePosition = this->GetMousePosition(me); mitkEvent = mitk::MouseMoveEvent::New(m_Renderer, mousePosition, GetButtonState(me), GetModifiers(me)); updateStatusBar = true; break; } case QEvent::MouseButtonPress: { auto me = static_cast(e); mitkEvent = mitk::MousePressEvent::New( m_Renderer, GetMousePosition(me), GetButtonState(me), GetModifiers(me), GetEventButton(me)); break; } case QEvent::MouseButtonRelease: { auto me = static_cast(e); mitkEvent = mitk::MouseReleaseEvent::New( m_Renderer, GetMousePosition(me), GetButtonState(me), GetModifiers(me), GetEventButton(me)); break; } case QEvent::MouseButtonDblClick: { auto me = static_cast(e); mitkEvent = mitk::MouseDoubleClickEvent::New( m_Renderer, GetMousePosition(me), GetButtonState(me), GetModifiers(me), GetEventButton(me)); break; } case QEvent::Wheel: { auto we = static_cast(e); mousePosition = this->GetMousePosition(we); mitkEvent = mitk::MouseWheelEvent::New(m_Renderer, mousePosition, GetButtonState(we), GetModifiers(we), GetDelta(we)); updateStatusBar = true; break; } case QEvent::KeyPress: { auto ke = static_cast(e); mitkEvent = mitk::InteractionKeyEvent::New(m_Renderer, GetKeyLetter(ke), GetModifiers(ke)); break; } case QEvent::Resize: { if (nullptr != m_MenuWidget) m_MenuWidget->MoveWidgetToCorrectPos(); } default: { break; } } if (mitkEvent != nullptr) { if (this->HandleEvent(mitkEvent.GetPointer())) { return m_ResendQtEvents ? false : true; } } if (updateStatusBar) { this->UpdateStatusBar(mousePosition); } return QVTKOpenGLNativeWidget::event(e); } void QmitkRenderWindow::enterEvent(QEnterEvent *e) { auto* baseRenderer = mitk::BaseRenderer::GetInstance(this->GetVtkRenderWindow()); this->ShowOverlayMessage(!baseRenderer->GetReferenceGeometryAligned()); if (nullptr != m_MenuWidget) m_MenuWidget->ShowMenu(); QVTKOpenGLNativeWidget::enterEvent(e); } void QmitkRenderWindow::leaveEvent(QEvent *e) { auto statusBar = mitk::StatusBar::GetInstance(); statusBar->DisplayGreyValueText(""); this->ShowOverlayMessage(false); if (nullptr != m_MenuWidget) m_MenuWidget->HideMenu(); QVTKOpenGLNativeWidget::leaveEvent(e); } void QmitkRenderWindow::resizeGL(int w, int h) { QVTKOpenGLNativeWidget::resizeGL(w, h); mitk::RenderingManager::GetInstance()->ForceImmediateUpdate(renderWindow()); } void QmitkRenderWindow::dragEnterEvent(QDragEnterEvent *event) { if (event->mimeData()->hasFormat("application/x-mitk-datanodes")) { event->accept(); } } void QmitkRenderWindow::dropEvent(QDropEvent *event) { QList dataNodeList = QmitkMimeTypes::ToDataNodePtrList(event->mimeData()); if (!dataNodeList.empty()) { std::vector dataNodes(dataNodeList.begin(), dataNodeList.end()); emit NodesDropped(this, dataNodes); } } void QmitkRenderWindow::DeferredHideMenu() { MITK_DEBUG << "QmitkRenderWindow::DeferredHideMenu"; if (nullptr != m_MenuWidget) { m_MenuWidget->HideMenu(); } } mitk::Point2D QmitkRenderWindow::GetMousePosition(QMouseEvent *me) const { mitk::Point2D point; const auto scale = this->devicePixelRatioF(); - point[0] = me->x()*scale; + const auto position = me->position(); + point[0] = position.x()*scale; // We need to convert the y component, as the display and vtk have other definitions for the y direction - point[1] = m_Renderer->GetSizeY() - me->y()*scale; + point[1] = m_Renderer->GetSizeY() - position.y()*scale; return point; } mitk::Point2D QmitkRenderWindow::GetMousePosition(QWheelEvent *we) const { mitk::Point2D point; const auto scale = this->devicePixelRatioF(); - point[0] = we->position().x()*scale; + const auto position = we->position(); + point[0] = position.x()*scale; // We need to convert the y component, as the display and vtk have other definitions for the y direction - point[1] = m_Renderer->GetSizeY() - we->position().y()*scale; + point[1] = m_Renderer->GetSizeY() - position.y()*scale; return point; } mitk::InteractionEvent::MouseButtons QmitkRenderWindow::GetEventButton(QMouseEvent *me) const { mitk::InteractionEvent::MouseButtons eventButton; switch (me->button()) { case Qt::LeftButton: eventButton = mitk::InteractionEvent::LeftMouseButton; break; case Qt::RightButton: eventButton = mitk::InteractionEvent::RightMouseButton; break; case Qt::MiddleButton: eventButton = mitk::InteractionEvent::MiddleMouseButton; break; default: eventButton = mitk::InteractionEvent::NoButton; break; } return eventButton; } mitk::InteractionEvent::MouseButtons QmitkRenderWindow::GetButtonState(QMouseEvent *me) const { mitk::InteractionEvent::MouseButtons buttonState = mitk::InteractionEvent::NoButton; if (me->buttons() & Qt::LeftButton) { buttonState = buttonState | mitk::InteractionEvent::LeftMouseButton; } if (me->buttons() & Qt::RightButton) { buttonState = buttonState | mitk::InteractionEvent::RightMouseButton; } if (me->buttons() & Qt::MiddleButton) { buttonState = buttonState | mitk::InteractionEvent::MiddleMouseButton; } return buttonState; } mitk::InteractionEvent::ModifierKeys QmitkRenderWindow::GetModifiers(QInputEvent *me) const { mitk::InteractionEvent::ModifierKeys modifiers = mitk::InteractionEvent::NoKey; if (me->modifiers() & Qt::ALT) { modifiers = modifiers | mitk::InteractionEvent::AltKey; } if (me->modifiers() & Qt::CTRL) { modifiers = modifiers | mitk::InteractionEvent::ControlKey; } if (me->modifiers() & Qt::SHIFT) { modifiers = modifiers | mitk::InteractionEvent::ShiftKey; } return modifiers; } mitk::InteractionEvent::MouseButtons QmitkRenderWindow::GetButtonState(QWheelEvent *we) const { mitk::InteractionEvent::MouseButtons buttonState = mitk::InteractionEvent::NoButton; if (we->buttons() & Qt::LeftButton) { buttonState = buttonState | mitk::InteractionEvent::LeftMouseButton; } if (we->buttons() & Qt::RightButton) { buttonState = buttonState | mitk::InteractionEvent::RightMouseButton; } if (we->buttons() & Qt::MiddleButton) { buttonState = buttonState | mitk::InteractionEvent::MiddleMouseButton; } return buttonState; } std::string QmitkRenderWindow::GetKeyLetter(QKeyEvent *ke) const { // Converting Qt Key Event to string element. std::string key = ""; int tkey = ke->key(); if (tkey < 128) { // standard ascii letter key = (char)toupper(tkey); } else { // special keys switch (tkey) { case Qt::Key_Return: key = mitk::InteractionEvent::KeyReturn; break; case Qt::Key_Enter: key = mitk::InteractionEvent::KeyEnter; break; case Qt::Key_Escape: key = mitk::InteractionEvent::KeyEsc; break; case Qt::Key_Delete: key = mitk::InteractionEvent::KeyDelete; break; case Qt::Key_Up: key = mitk::InteractionEvent::KeyArrowUp; break; case Qt::Key_Down: key = mitk::InteractionEvent::KeyArrowDown; break; case Qt::Key_Left: key = mitk::InteractionEvent::KeyArrowLeft; break; case Qt::Key_Right: key = mitk::InteractionEvent::KeyArrowRight; break; case Qt::Key_F1: key = mitk::InteractionEvent::KeyF1; break; case Qt::Key_F2: key = mitk::InteractionEvent::KeyF2; break; case Qt::Key_F3: key = mitk::InteractionEvent::KeyF3; break; case Qt::Key_F4: key = mitk::InteractionEvent::KeyF4; break; case Qt::Key_F5: key = mitk::InteractionEvent::KeyF5; break; case Qt::Key_F6: key = mitk::InteractionEvent::KeyF6; break; case Qt::Key_F7: key = mitk::InteractionEvent::KeyF7; break; case Qt::Key_F8: key = mitk::InteractionEvent::KeyF8; break; case Qt::Key_F9: key = mitk::InteractionEvent::KeyF9; break; case Qt::Key_F10: key = mitk::InteractionEvent::KeyF10; break; case Qt::Key_F11: key = mitk::InteractionEvent::KeyF11; break; case Qt::Key_F12: key = mitk::InteractionEvent::KeyF12; break; case Qt::Key_End: key = mitk::InteractionEvent::KeyEnd; break; case Qt::Key_Home: key = mitk::InteractionEvent::KeyPos1; break; case Qt::Key_Insert: key = mitk::InteractionEvent::KeyInsert; break; case Qt::Key_PageDown: key = mitk::InteractionEvent::KeyPageDown; break; case Qt::Key_PageUp: key = mitk::InteractionEvent::KeyPageUp; break; case Qt::Key_Space: key = mitk::InteractionEvent::KeySpace; break; } } return key; } int QmitkRenderWindow::GetDelta(QWheelEvent *we) const { return we->angleDelta().y(); } void QmitkRenderWindow::UpdateStatusBar(mitk::Point2D pointerPositionOnScreen) { mitk::Point3D worldPosition; m_Renderer->ForceImmediateUpdate(); m_Renderer->DisplayToWorld(pointerPositionOnScreen, worldPosition); auto statusBar = mitk::StatusBar::GetInstance(); statusBar->DisplayRendererInfo(worldPosition, m_Renderer->GetTime()); } diff --git a/Modules/QtWidgets/src/QmitkSliderLevelWindowWidget.cpp b/Modules/QtWidgets/src/QmitkSliderLevelWindowWidget.cpp index f837423397..2f4bbf0926 100644 --- a/Modules/QtWidgets/src/QmitkSliderLevelWindowWidget.cpp +++ b/Modules/QtWidgets/src/QmitkSliderLevelWindowWidget.cpp @@ -1,550 +1,550 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include // mitk core #include // mitk qt widgets #include // qt #include #include #include #include // itk #include // c++ #include QmitkSliderLevelWindowWidget::QmitkSliderLevelWindowWidget(QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f) { m_Manager = mitk::LevelWindowManager::New(); itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction(this, &QmitkSliderLevelWindowWidget::OnPropertyModified); m_ObserverTag = m_Manager->AddObserver(itk::ModifiedEvent(), command); m_IsObserverTagSet = true; setMouseTracking(true); m_Resize = false; m_Bottom = false; m_CtrlPressed = false; m_MouseDown = false; m_Font.setPointSize(6); m_MoveHeight = height() - 25; m_ScaleVisible = true; m_Contextmenu = new QmitkLevelWindowWidgetContextMenu(this); this->hide(); Update(); } QmitkSliderLevelWindowWidget::~QmitkSliderLevelWindowWidget() { if (m_IsObserverTagSet) { m_Manager->RemoveObserver(m_ObserverTag); m_IsObserverTagSet = false; } } void QmitkSliderLevelWindowWidget::SetLevelWindowManager(mitk::LevelWindowManager *levelWindowManager) { if (m_IsObserverTagSet) { m_Manager->RemoveObserver(m_ObserverTag); m_IsObserverTagSet = false; } m_Manager = levelWindowManager; if (m_Manager.IsNotNull()) { itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction(this, &QmitkSliderLevelWindowWidget::OnPropertyModified); m_ObserverTag = m_Manager->AddObserver(itk::ModifiedEvent(), command); m_IsObserverTagSet = true; } } void QmitkSliderLevelWindowWidget::OnPropertyModified(const itk::EventObject &) { try { m_LevelWindow = m_Manager->GetLevelWindow(); this->show(); Update(); } catch (...) { try { this->hide(); } catch (...) { } } } void QmitkSliderLevelWindowWidget::paintEvent(QPaintEvent *itkNotUsed(e)) { QPixmap pm(width(), height()); pm.fill(this->palette().color(this->backgroundRole())); QPainter painter(&pm); painter.setFont(m_Font); painter.setPen(this->palette().color(this->foregroundRole())); QColor c(51, 153, 204); QColor cl = c.lighter(); QColor cd = c.darker(); painter.setBrush(c); painter.drawRect(m_Rect); mitk::ScalarType mr = m_LevelWindow.GetRange(); float smallestLevelableValue = 1e-9; //This check is needed as safe guard. LevelWindow is refactored to only deduce finite ranges //from images, but old scene serialization may contain infinite ranges that overwrite the new //business logic. This roots in two many "jobs" LevelWindow" is used for; see also T24962. //Until LevelWindow and this widget is refactored the check was the minimal invasive fix. if (!std::isfinite(mr)) { mr = m_LevelWindow.GetWindow(); } // avoiding a division by 0 while still enabling small level windows if (mr < smallestLevelableValue) mr = smallestLevelableValue; mitk::ScalarType fact = m_MoveHeight / mr; // begin draw scale if (m_ScaleVisible) { mitk::ScalarType minRange = m_LevelWindow.GetRangeMin(); mitk::ScalarType maxRange = m_LevelWindow.GetRangeMax(); //This check is needed as safe guard. LevelWindow is refactored to only deduce finite ranges //from images, but old scene serialization may contain infinite ranges that overwrite the new //business logic. This roots in two many "jobs" LevelWindow" is used for; see also T24962. //Until LevelWindow and this widget is refactored the check was the minimal invasive fix. if (!std::isfinite(minRange)) { minRange = m_LevelWindow.GetLowerWindowBound(); } //This check is needed as safe guard. LevelWindow is refactored to only deduce finite ranges //from images, but old scene serialization may contain infinite ranges that overwrite the new //business logic. This roots in two many "jobs" LevelWindow" is used for; see also T24962. //Until LevelWindow and this widget is refactored the check was the minimal invasive fix. if (!std::isfinite(maxRange)) { maxRange = m_LevelWindow.GetUpperWindowBound(); } int yValue = m_MoveHeight + static_cast(minRange * fact); QString s = " 0"; if (minRange < 0 && maxRange > 0) { painter.drawLine(5, yValue, 15, yValue); painter.drawText(21, yValue + 3, s); } int count = 1; int k = 5; bool enoughSpace = false; bool enoughSpace2 = false; double dStepSize = pow(10, floor(log10(mr / 100)) + 1); for (int i = m_MoveHeight + static_cast(minRange * fact); i < m_MoveHeight;) // negative { if (-count * dStepSize < minRange) { break; } yValue = m_MoveHeight + static_cast((minRange + count * dStepSize) * fact); s = QString::number(-count * dStepSize); if (count % k && ((dStepSize * fact) > 2.5)) { painter.drawLine(8, yValue, 12, yValue); enoughSpace = true; } else if (!(count % k)) { if ((k * dStepSize * fact) > 7) { painter.drawLine(5, yValue, 15, yValue); painter.drawText(21, yValue + 3, s); enoughSpace2 = true; } else { k += 5; } } if (enoughSpace) { i = yValue; count++; } else if (enoughSpace2) { i = yValue; count += k; } else { i = yValue; count = k; } } count = 1; k = 5; enoughSpace = false; enoughSpace2 = false; for (int i = m_MoveHeight + static_cast(minRange * fact); i >= 0;) { if (count * dStepSize > maxRange) { break; } yValue = m_MoveHeight + static_cast((minRange - count * dStepSize) * fact); s = QString::number(count * dStepSize); if (count % k && ((dStepSize * fact) > 2.5)) { if (!(minRange > 0 && (count * dStepSize) < minRange)) painter.drawLine(8, yValue, 12, yValue); enoughSpace = true; } else if (!(count % k)) { if ((k * dStepSize * fact) > 7) { if (!(minRange > 0 && (count * dStepSize) < minRange)) { painter.drawLine(5, yValue, 15, yValue); painter.drawText(21, yValue + 3, s); } enoughSpace2 = true; } else { k += 5; } } if (enoughSpace) { i = yValue; count++; } else if (enoughSpace2) { i = yValue; count += k; } else { i = yValue; count = k; } } } // end draw scale painter.setPen(cl); painter.drawLine(m_Rect.topLeft(), m_Rect.topRight()); painter.drawLine(m_Rect.topLeft(), m_Rect.bottomLeft()); painter.setPen(cd); painter.drawLine(m_Rect.topRight(), m_Rect.bottomRight()); painter.drawLine(m_Rect.bottomRight(), m_Rect.bottomLeft()); painter.end(); QPainter p(this); p.drawPixmap(0, 0, pm); } void QmitkSliderLevelWindowWidget::mouseMoveEvent(QMouseEvent *mouseEvent) { if (!mouseEvent) return; if (m_LevelWindow.IsFixed()) return; if (!m_MouseDown) { if (mouseEvent->pos().y() >= 0 && mouseEvent->pos().y() <= (m_Rect.topLeft().y() + 3)) { setCursor(Qt::SizeVerCursor); m_UpperBound.setRect(m_Rect.topLeft().x(), m_Rect.topLeft().y() - 3, 17, 7); this->setToolTip("Ctrl + left click to change only upper bound"); m_Resize = true; } else if (mouseEvent->pos().y() >= (m_Rect.bottomLeft().y() - 3)) { setCursor(Qt::SizeVerCursor); m_LowerBound.setRect(m_Rect.bottomLeft().x(), m_Rect.bottomLeft().y() - 3, 17, 7); this->setToolTip("Ctrl + left click to change only lower bound"); m_Resize = true; m_Bottom = true; } else { setCursor(Qt::ArrowCursor); this->setToolTip("Left click and mouse move to adjust the slider"); m_Resize = false; m_Bottom = false; } } else { mitk::ScalarType fact = m_MoveHeight / m_LevelWindow.GetRange(); if (m_Leftbutton) { if (m_Resize && !m_CtrlPressed) { mitk::ScalarType diff = (mouseEvent->pos().y()) / fact; diff -= (m_StartPos.y()) / fact; m_StartPos = mouseEvent->pos(); if (diff == 0) return; mitk::ScalarType value; if (m_Bottom) value = m_LevelWindow.GetWindow() + ((2 * diff)); else value = m_LevelWindow.GetWindow() - ((2 * diff)); if (value < 0) value = 0; m_LevelWindow.SetLevelWindow(m_LevelWindow.GetLevel(), value); } else if (m_Resize && m_CtrlPressed) { if (!m_Bottom) { mitk::ScalarType diff = (mouseEvent->pos().y()) / fact; diff -= (m_StartPos.y()) / fact; m_StartPos = mouseEvent->pos(); if (diff == 0) return; mitk::ScalarType value; value = m_LevelWindow.GetWindow() - ((diff)); if (value < 0) value = 0; mitk::ScalarType oldWindow; mitk::ScalarType oldLevel; mitk::ScalarType newLevel; oldWindow = m_LevelWindow.GetWindow(); oldLevel = m_LevelWindow.GetLevel(); newLevel = oldLevel + (value - oldWindow) / 2; if (!((newLevel + value / 2) > m_LevelWindow.GetRangeMax())) m_LevelWindow.SetLevelWindow(newLevel, value); } else { mitk::ScalarType diff = (mouseEvent->pos().y()) / fact; diff -= (m_StartPos.y()) / fact; m_StartPos = mouseEvent->pos(); if (diff == 0) return; mitk::ScalarType value; value = m_LevelWindow.GetWindow() + ((diff)); if (value < 0) value = 0; mitk::ScalarType oldWindow; mitk::ScalarType oldLevel; mitk::ScalarType newLevel; oldWindow = m_LevelWindow.GetWindow(); oldLevel = m_LevelWindow.GetLevel(); newLevel = oldLevel - (value - oldWindow) / 2; if (!((newLevel - value / 2) < m_LevelWindow.GetRangeMin())) m_LevelWindow.SetLevelWindow(newLevel, value); } } else { const mitk::ScalarType minv = m_LevelWindow.GetRangeMin(); const mitk::ScalarType level = (m_MoveHeight - mouseEvent->pos().y()) / fact + minv; mitk::ScalarType diff = (mouseEvent->pos().x()) / fact; diff -= (m_StartPos.x()) / fact; m_StartPos = mouseEvent->pos(); mitk::ScalarType window; if (m_Bottom) window = m_LevelWindow.GetWindow() + ((2 * diff)); else window = m_LevelWindow.GetWindow() - ((2 * diff)); if (window < 0) window = 0; m_LevelWindow.SetLevelWindow(level, window); } m_Manager->SetLevelWindow(m_LevelWindow); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } } void QmitkSliderLevelWindowWidget::enterEvent(QEnterEvent * /*event*/) { - QPoint p = QCursor::pos(); - p = this->mapFromGlobal(p); - QMouseEvent ev(QEvent::MouseMove, p, Qt::NoButton, Qt::NoButton, Qt::NoModifier); + const auto pos = QCursor::pos(); + const auto localPos = this->mapFromGlobal(pos); + QMouseEvent ev(QEvent::MouseMove, localPos, pos, Qt::NoButton, Qt::NoButton, Qt::NoModifier); this->mouseMoveEvent(&ev); } void QmitkSliderLevelWindowWidget::mousePressEvent(QMouseEvent *mouseEvent) { if (m_LevelWindow.IsFixed()) return; m_MouseDown = true; m_StartPos = mouseEvent->pos(); if (mouseEvent->button() == Qt::LeftButton) { if (mouseEvent->modifiers() == Qt::ControlModifier || mouseEvent->modifiers() == Qt::ShiftModifier) { m_CtrlPressed = true; } else { m_CtrlPressed = false; } m_Leftbutton = true; } else m_Leftbutton = false; mouseMoveEvent(mouseEvent); } void QmitkSliderLevelWindowWidget::resizeEvent(QResizeEvent *event) { m_MoveHeight = event->size().height() - 25; Update(); } void QmitkSliderLevelWindowWidget::mouseReleaseEvent(QMouseEvent *) { if (m_LevelWindow.IsFixed()) return; m_MouseDown = false; } void QmitkSliderLevelWindowWidget::Update() { int rectWidth; if (m_ScaleVisible) { rectWidth = 17; setMinimumSize(QSize(50, 50)); setMaximumSize(QSize(50, 2000)); setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding)); } else { rectWidth = 26; setMinimumSize(QSize(40, 50)); setMaximumSize(QSize(50, 2000)); setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding)); } mitk::ScalarType mr = m_LevelWindow.GetRange(); if (mr < 1e-9) mr = 1e-9; mitk::ScalarType fact = m_MoveHeight / mr; mitk::ScalarType rectHeight = m_LevelWindow.GetWindow() * fact; if (rectHeight < 15) rectHeight = 15; if (m_LevelWindow.GetLowerWindowBound() < 0) m_Rect.setRect(2, static_cast(m_MoveHeight - (m_LevelWindow.GetUpperWindowBound() - m_LevelWindow.GetRangeMin()) * fact), rectWidth, static_cast(rectHeight)); else m_Rect.setRect(2, static_cast(m_MoveHeight - (m_LevelWindow.GetUpperWindowBound() - m_LevelWindow.GetRangeMin()) * fact), rectWidth, static_cast(rectHeight)); QWidget::repaint(); } void QmitkSliderLevelWindowWidget::contextMenuEvent(QContextMenuEvent *) { m_Contextmenu->SetLevelWindowManager(m_Manager.GetPointer()); auto contextMenu = new QMenu(this); Q_CHECK_PTR(contextMenu); if (m_ScaleVisible) contextMenu->addAction(tr("Hide Scale"), this, SLOT(HideScale())); else contextMenu->addAction(tr("Show Scale"), this, SLOT(ShowScale())); contextMenu->addSeparator(); m_Contextmenu->GetContextMenu(contextMenu); // Fix: Bug #13327 we need to reset the m_MouseDown value // otherwise the cursor is not correctly restored afterwards m_MouseDown = false; } void QmitkSliderLevelWindowWidget::HideScale() { m_ScaleVisible = false; Update(); } void QmitkSliderLevelWindowWidget::ShowScale() { m_ScaleVisible = true; Update(); } void QmitkSliderLevelWindowWidget::SetDataStorage(mitk::DataStorage *ds) { m_Manager->SetDataStorage(ds); } mitk::LevelWindowManager *QmitkSliderLevelWindowWidget::GetManager() { return m_Manager.GetPointer(); } diff --git a/Modules/QtWidgetsExt/src/QmitkTransferFunctionCanvas.cpp b/Modules/QtWidgetsExt/src/QmitkTransferFunctionCanvas.cpp index b71f2fb889..7e68f1c758 100755 --- a/Modules/QtWidgetsExt/src/QmitkTransferFunctionCanvas.cpp +++ b/Modules/QtWidgetsExt/src/QmitkTransferFunctionCanvas.cpp @@ -1,232 +1,234 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "QmitkTransferFunctionCanvas.h" #include #include #include #include QmitkTransferFunctionCanvas::QmitkTransferFunctionCanvas(QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f), m_GrabbedHandle(-1), m_Lower(0.0), m_Upper(1.0), m_Min(0.0), m_Max(1.0), m_Histogram(nullptr), m_ImmediateUpdate(false), m_Range(0.0f), m_LineEditAvailable(false), m_XEdit(nullptr), m_YEdit(nullptr) { setEnabled(false); setFocusPolicy(Qt::ClickFocus); } void QmitkTransferFunctionCanvas::paintEvent(QPaintEvent *ev) { QWidget::paintEvent(ev); } std::pair QmitkTransferFunctionCanvas::FunctionToCanvas(std::pair functionPoint) { return std::make_pair( (int)((functionPoint.first - m_Lower) / (m_Upper - m_Lower) * contentsRect().width()) + contentsRect().x(), (int)(contentsRect().height() * (1 - functionPoint.second)) + contentsRect().y()); } std::pair QmitkTransferFunctionCanvas::CanvasToFunction(std::pair canvasPoint) { return std::make_pair( (canvasPoint.first - contentsRect().x()) * (m_Upper - m_Lower) / contentsRect().width() + m_Lower, 1.0 - (double)(canvasPoint.second - contentsRect().y()) / contentsRect().height()); } void QmitkTransferFunctionCanvas::mouseDoubleClickEvent(QMouseEvent *mouseEvent) { int nearHandle = GetNearHandle(mouseEvent->pos().x(), mouseEvent->pos().y()); if (nearHandle != -1) { this->DoubleClickOnHandle(nearHandle); } } /** returns index of a near handle or -1 if none is near */ int QmitkTransferFunctionCanvas::GetNearHandle(int, int, unsigned int) { return -1; } void QmitkTransferFunctionCanvas::mousePressEvent(QMouseEvent *mouseEvent) { if (m_LineEditAvailable) { m_XEdit->clear(); if (m_YEdit) m_YEdit->clear(); } - m_GrabbedHandle = GetNearHandle(mouseEvent->pos().x(), mouseEvent->pos().y()); + const auto pos = mouseEvent->position().toPoint(); + m_GrabbedHandle = GetNearHandle(pos.x(), pos.y()); if ((mouseEvent->button() & Qt::LeftButton) && m_GrabbedHandle == -1) { - this->AddFunctionPoint(this->CanvasToFunction(std::make_pair(mouseEvent->pos().x(), mouseEvent->pos().y())).first, - this->CanvasToFunction(std::make_pair(mouseEvent->x(), mouseEvent->y())).second); - m_GrabbedHandle = GetNearHandle(mouseEvent->pos().x(), mouseEvent->pos().y()); + auto [x, value] = this->CanvasToFunction(std::make_pair(pos.x(), pos.y())); + this->AddFunctionPoint(x, value); + m_GrabbedHandle = GetNearHandle(pos.x(), pos.y()); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } else if ((mouseEvent->button() & Qt::RightButton) && m_GrabbedHandle != -1 && this->GetFunctionSize() > 1) { this->RemoveFunctionPoint(this->GetFunctionX(m_GrabbedHandle)); m_GrabbedHandle = -1; mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } update(); } void QmitkTransferFunctionCanvas::mouseMoveEvent(QMouseEvent *mouseEvent) { if (m_GrabbedHandle != -1) { - std::pair newPos = this->CanvasToFunction(std::make_pair(mouseEvent->x(), mouseEvent->y())); + const auto pos = mouseEvent->position().toPoint(); + std::pair newPos = this->CanvasToFunction(std::make_pair(pos.x(), pos.y())); // X Clamping { // Check with predecessor if (m_GrabbedHandle > 0) if (newPos.first <= this->GetFunctionX(m_GrabbedHandle - 1)) newPos.first = this->GetFunctionX(m_GrabbedHandle); // Check with sucessor if (m_GrabbedHandle < this->GetFunctionSize() - 1) if (newPos.first >= this->GetFunctionX(m_GrabbedHandle + 1)) newPos.first = this->GetFunctionX(m_GrabbedHandle); // Clamping to histogramm if (newPos.first < m_Min) newPos.first = m_Min; else if (newPos.first > m_Max) newPos.first = m_Max; } // Y Clamping { if (newPos.second < 0.0) newPos.second = 0.0; else if (newPos.second > 1.0) newPos.second = 1.0; } // Move selected point this->MoveFunctionPoint(m_GrabbedHandle, newPos); update(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkTransferFunctionCanvas::mouseReleaseEvent(QMouseEvent *) { update(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkTransferFunctionCanvas::PaintHistogram(QPainter &p) { if (m_Histogram) { p.save(); p.setPen(Qt::gray); int displayWidth = contentsRect().width(); int displayHeight = contentsRect().height(); double windowLeft = m_Lower; double windowRight = m_Upper; double step = (windowRight - windowLeft) / double(displayWidth); double pos = windowLeft; for (int x = 0; x < displayWidth; x++) { double left = pos; double right = pos + step; float height = m_Histogram->GetRelativeBin(left, right); if (height >= 0) p.drawLine(x, displayHeight * (1 - height), x, displayHeight); pos += step; } p.restore(); } } void QmitkTransferFunctionCanvas::keyPressEvent(QKeyEvent *e) { if (m_GrabbedHandle == -1) return; switch (e->key()) { case Qt::Key_Delete: if (this->GetFunctionSize() > 1) { this->RemoveFunctionPoint(GetFunctionX(m_GrabbedHandle)); m_GrabbedHandle = -1; } break; case Qt::Key_Left: this->MoveFunctionPoint( m_GrabbedHandle, ValidateCoord(std::make_pair(GetFunctionX(m_GrabbedHandle) - 1, GetFunctionY(m_GrabbedHandle)))); break; case Qt::Key_Right: this->MoveFunctionPoint( m_GrabbedHandle, ValidateCoord(std::make_pair(GetFunctionX(m_GrabbedHandle) + 1, GetFunctionY(m_GrabbedHandle)))); break; case Qt::Key_Up: this->MoveFunctionPoint( m_GrabbedHandle, ValidateCoord(std::make_pair(GetFunctionX(m_GrabbedHandle), GetFunctionY(m_GrabbedHandle) + 0.001))); break; case Qt::Key_Down: this->MoveFunctionPoint( m_GrabbedHandle, ValidateCoord(std::make_pair(GetFunctionX(m_GrabbedHandle), GetFunctionY(m_GrabbedHandle) - 0.001))); break; } update(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } // Update immediatly while changing the transfer function void QmitkTransferFunctionCanvas::SetImmediateUpdate(bool state) { m_ImmediateUpdate = state; } diff --git a/Modules/SegmentationUI/Qmitk/QmitkToolSelectionBox.cpp b/Modules/SegmentationUI/Qmitk/QmitkToolSelectionBox.cpp index 8676ab7211..995433d58e 100755 --- a/Modules/SegmentationUI/Qmitk/QmitkToolSelectionBox.cpp +++ b/Modules/SegmentationUI/Qmitk/QmitkToolSelectionBox.cpp @@ -1,623 +1,623 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ //#define MBILOG_ENABLE_DEBUG 1 #include #include "QmitkToolSelectionBox.h" #include "QmitkToolGUI.h" #include "mitkBaseRenderer.h" #include #include #include #include #include #include #include #include #include "usModuleResource.h" #include "usModuleResourceStream.h" #include "mitkToolManagerProvider.h" QmitkToolSelectionBox::QmitkToolSelectionBox(QWidget *parent, mitk::DataStorage *) : QWidget(parent), m_SelfCall(false), m_DisplayedGroups("default"), m_LayoutColumns(2), m_ShowNames(true), m_GenerateAccelerators(false), m_ToolGUIWidget(nullptr), m_LastToolGUI(nullptr), m_ToolButtonGroup(nullptr), m_ButtonLayout(nullptr) { QFont currentFont = QWidget::font(); currentFont.setBold(true); QWidget::setFont(currentFont); m_ToolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); // QButtonGroup m_ToolButtonGroup = new QButtonGroup(this); // some features of QButtonGroup m_ToolButtonGroup->setExclusive(false); // mutually exclusive toggle buttons RecreateButtons(); QWidget::setContentsMargins(0, 0, 0, 0); if (layout() != nullptr) { layout()->setContentsMargins(0, 0, 0, 0); } // reactions to signals connect(m_ToolButtonGroup, &QButtonGroup::idClicked, this, &QmitkToolSelectionBox::toolButtonClicked); // reactions to ToolManager events m_ToolManager->ActiveToolChanged += mitk::MessageDelegate(this, &QmitkToolSelectionBox::OnToolManagerToolModified); m_ToolManager->ReferenceDataChanged += mitk::MessageDelegate(this, &QmitkToolSelectionBox::OnToolManagerReferenceDataModified); m_ToolManager->WorkingDataChanged += mitk::MessageDelegate(this, &QmitkToolSelectionBox::OnToolManagerWorkingDataModified); // show active tool SetOrUnsetButtonForActiveTool(); QWidget::setEnabled(false); } QmitkToolSelectionBox::~QmitkToolSelectionBox() { m_ToolManager->ActiveToolChanged -= mitk::MessageDelegate(this, &QmitkToolSelectionBox::OnToolManagerToolModified); m_ToolManager->ReferenceDataChanged -= mitk::MessageDelegate(this, &QmitkToolSelectionBox::OnToolManagerReferenceDataModified); m_ToolManager->WorkingDataChanged -= mitk::MessageDelegate(this, &QmitkToolSelectionBox::OnToolManagerWorkingDataModified); } mitk::ToolManager *QmitkToolSelectionBox::GetToolManager() { return m_ToolManager; } void QmitkToolSelectionBox::SetToolManager( mitk::ToolManager &newManager) // no nullptr pointer allowed here, a manager is required { // say bye to the old manager m_ToolManager->ActiveToolChanged -= mitk::MessageDelegate(this, &QmitkToolSelectionBox::OnToolManagerToolModified); m_ToolManager->ReferenceDataChanged -= mitk::MessageDelegate(this, &QmitkToolSelectionBox::OnToolManagerReferenceDataModified); m_ToolManager->WorkingDataChanged -= mitk::MessageDelegate(this, &QmitkToolSelectionBox::OnToolManagerWorkingDataModified); if (QWidget::isEnabled()) { m_ToolManager->UnregisterClient(); } m_ToolManager = &newManager; RecreateButtons(); // greet the new one m_ToolManager->ActiveToolChanged += mitk::MessageDelegate(this, &QmitkToolSelectionBox::OnToolManagerToolModified); m_ToolManager->ReferenceDataChanged += mitk::MessageDelegate(this, &QmitkToolSelectionBox::OnToolManagerReferenceDataModified); m_ToolManager->WorkingDataChanged += mitk::MessageDelegate(this, &QmitkToolSelectionBox::OnToolManagerWorkingDataModified); if (QWidget::isEnabled()) { m_ToolManager->RegisterClient(); } // ask the new one what the situation is like SetOrUnsetButtonForActiveTool(); } void QmitkToolSelectionBox::toolButtonClicked(int id) { if (!QWidget::isEnabled()) return; // this method could be triggered from the constructor, when we are still disabled MITK_DEBUG << "toolButtonClicked(" << id << "): id translates to tool ID " << m_ToolIDForButtonID[id]; QToolButton *toolButton = dynamic_cast(m_ToolButtonGroup->buttons().at(id)); if (toolButton) { if ((m_ButtonIDForToolID.find(m_ToolManager->GetActiveToolID()) != m_ButtonIDForToolID.end()) // if we have this tool in our box && (m_ButtonIDForToolID[m_ToolManager->GetActiveToolID()] == id)) // the tool corresponding to this button is already active { // disable this button, disable all tools toolButton->setChecked(false); m_ToolManager->ActivateTool(-1); // disable everything } else { // enable the corresponding tool m_SelfCall = true; m_ToolManager->ActivateTool(m_ToolIDForButtonID[id]); m_SelfCall = false; } } } void QmitkToolSelectionBox::OnToolManagerToolModified() { SetOrUnsetButtonForActiveTool(); } void QmitkToolSelectionBox::SetOrUnsetButtonForActiveTool() { // we want to emit a signal in any case, whether we selected ourselves or somebody else changes "our" tool manager. // --> emit before check on m_SelfCall int id = m_ToolManager->GetActiveToolID(); // don't emit signal for shape model tools bool emitSignal = true; mitk::Tool *tool = m_ToolManager->GetActiveTool(); if (tool && std::string(tool->GetGroup()) == "organ_segmentation") emitSignal = false; if (emitSignal) emit ToolSelected(id); // delete old GUI (if any) if (m_LastToolGUI && m_ToolGUIWidget) { if (m_ToolGUIWidget->layout()) { m_ToolGUIWidget->layout()->removeWidget(m_LastToolGUI); } m_LastToolGUI->setParent(nullptr); delete m_LastToolGUI; // will hopefully notify parent and layouts m_LastToolGUI = nullptr; QLayout *layout = m_ToolGUIWidget->layout(); if (layout) { layout->activate(); } } QToolButton *toolButton(nullptr); if (m_ButtonIDForToolID.find(id) != m_ButtonIDForToolID.end()) // if this tool is in our box { toolButton = dynamic_cast(m_ToolButtonGroup->buttons().at(m_ButtonIDForToolID[id])); } if (toolButton) { // mmueller // uncheck all other buttons QAbstractButton *tmpBtn = nullptr; for (int i = 0; i < m_ToolButtonGroup->buttons().size(); ++i) { tmpBtn = m_ToolButtonGroup->buttons().at(i); if (tmpBtn != toolButton) dynamic_cast(tmpBtn)->setChecked(false); } toolButton->setChecked(true); if (m_ToolGUIWidget && tool) { // create and reparent new GUI (if any) itk::Object::Pointer possibleGUI = tool->GetGUI("Qmitk", "GUI").GetPointer(); // prefix and postfix if (possibleGUI.IsNull()) possibleGUI = tool->GetGUI("", "GUI").GetPointer(); QmitkToolGUI *gui = dynamic_cast(possibleGUI.GetPointer()); //! m_LastToolGUI = gui; if (gui) { gui->SetTool(tool); gui->setParent(m_ToolGUIWidget); gui->move(gui->geometry().topLeft()); gui->show(); QLayout *layout = m_ToolGUIWidget->layout(); if (!layout) { layout = new QVBoxLayout(m_ToolGUIWidget); } if (layout) { layout->addWidget(gui); layout->activate(); } } } } else { // disable all buttons QToolButton *selectedToolButton = dynamic_cast(m_ToolButtonGroup->checkedButton()); if (selectedToolButton) { selectedToolButton->setChecked(false); } } } void QmitkToolSelectionBox::OnToolManagerReferenceDataModified() { if (m_SelfCall) return; MITK_DEBUG << "OnToolManagerReferenceDataModified()"; this->UpdateButtonsEnabledState(); } void QmitkToolSelectionBox::OnToolManagerWorkingDataModified() { if (m_SelfCall) return; MITK_DEBUG << "OnToolManagerWorkingDataModified()"; this->UpdateButtonsEnabledState(); } void QmitkToolSelectionBox::setEnabled(bool enable) { if (QWidget::isEnabled() == enable) return; QWidget::setEnabled(enable); if (enable) { m_ToolManager->RegisterClient(); auto id = m_ToolManager->GetActiveToolID(); emit ToolSelected(id); } else { m_ToolManager->ActivateTool(-1); m_ToolManager->UnregisterClient(); emit ToolSelected(-1); } } void QmitkToolSelectionBox::UpdateButtonsEnabledState() { auto buttons = m_ToolButtonGroup->buttons(); const auto refDataNode = m_ToolManager->GetReferenceData(0); const mitk::BaseData* refData = nullptr; if (nullptr != refDataNode) { refData = refDataNode->GetData(); } const auto workingDataNode = m_ToolManager->GetWorkingData(0); const mitk::BaseData* workingData = nullptr; if (nullptr != workingDataNode) { workingData = workingDataNode->GetData(); } for (const auto& button : std::as_const(buttons)) { const auto buttonID = m_ToolButtonGroup->id(button); const auto toolID = m_ToolIDForButtonID[buttonID]; const auto tool = m_ToolManager->GetToolById(toolID); button->setEnabled(tool->CanHandle(refData, workingData)); } } void QmitkToolSelectionBox::RecreateButtons() { if (m_ToolManager.IsNull()) return; QList l = m_ToolButtonGroup->buttons(); // remove all buttons that are there QList::iterator it; QAbstractButton *btn; for (it = l.begin(); it != l.end(); ++it) { btn = *it; m_ToolButtonGroup->removeButton(btn); delete btn; } mitk::ToolManager::ToolVectorTypeConst allPossibleTools = m_ToolManager->GetTools(); mitk::ToolManager::ToolVectorTypeConst allTools; typedef std::pair SortPairType; typedef std::priority_queue SortedToolQueueType; SortedToolQueueType toolPositions; // clear and sort all tools // step one: find name/group of all tools in m_DisplayedGroups string. remember these positions for all tools. for (mitk::ToolManager::ToolVectorTypeConst::const_iterator iter = allPossibleTools.begin(); iter != allPossibleTools.end(); ++iter) { const mitk::Tool *tool = *iter; std::string::size_type namePos = m_DisplayedGroups.find(std::string("'") + tool->GetName() + "'"); std::string::size_type groupPos = m_DisplayedGroups.find(std::string("'") + tool->GetGroup() + "'"); if (!m_DisplayedGroups.empty() && namePos == std::string::npos && groupPos == std::string::npos) continue; // skip if (m_DisplayedGroups.empty() && std::string(tool->GetName()).length() > 0) { namePos = static_cast(tool->GetName()[0]); } SortPairType thisPair = std::make_pair(namePos < groupPos ? namePos : groupPos, *iter); toolPositions.push(thisPair); } // step two: sort tools according to previously found positions in m_DisplayedGroups MITK_DEBUG << "Sorting order of tools (lower number --> earlier in button group)"; while (!toolPositions.empty()) { SortPairType thisPair = toolPositions.top(); MITK_DEBUG << "Position " << thisPair.first << " : " << thisPair.second->GetName(); allTools.push_back(thisPair.second); toolPositions.pop(); } std::reverse(allTools.begin(), allTools.end()); MITK_DEBUG << "Sorted tools:"; for (mitk::ToolManager::ToolVectorTypeConst::const_iterator iter = allTools.begin(); iter != allTools.end(); ++iter) { MITK_DEBUG << (*iter)->GetName(); } if (m_ButtonLayout == nullptr) m_ButtonLayout = new QGridLayout; int row(0); int column(-1); int currentButtonID(0); m_ButtonIDForToolID.clear(); m_ToolIDForButtonID.clear(); QToolButton *button = nullptr; MITK_DEBUG << "Creating buttons for tools"; // fill group box with buttons for (mitk::ToolManager::ToolVectorTypeConst::const_iterator iter = allTools.begin(); iter != allTools.end(); ++iter) { const mitk::Tool *tool = *iter; int currentToolID(m_ToolManager->GetToolID(tool)); ++column; // new line if we are at the maximum columns if (column == m_LayoutColumns) { ++row; column = 0; } button = new QToolButton; button->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum)); // add new button to the group MITK_DEBUG << "Adding button with ID " << currentToolID; m_ToolButtonGroup->addButton(button, currentButtonID); // ... and to the layout MITK_DEBUG << "Adding button in row/column " << row << "/" << column; m_ButtonLayout->addWidget(button, row, column); if (m_LayoutColumns == 1) { button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); } else { button->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); } button->setCheckable(true); if (currentToolID == m_ToolManager->GetActiveToolID()) button->setChecked(true); QString label; if (m_GenerateAccelerators) { label += "&"; } label += tool->GetName(); QString tooltip = tool->GetName(); MITK_DEBUG << tool->GetName() << ", " << label.toLocal8Bit().constData() << ", '" << tooltip.toLocal8Bit().constData(); if (m_ShowNames) { button->setText(label); // a label button->setToolTip(tooltip); QFont currentFont = button->font(); currentFont.setBold(false); button->setFont(currentFont); } us::ModuleResource iconResource = tool->GetIconResource(); if (!iconResource.IsValid()) { button->setIcon(QIcon(QPixmap(tool->GetXPM()))); } else { auto isSVG = "svg" == iconResource.GetSuffix(); auto openmode = isSVG ? std::ios_base::in : std::ios_base::binary; us::ModuleResourceStream resourceStream(iconResource, openmode); resourceStream.seekg(0, std::ios::end); std::ios::pos_type length = resourceStream.tellg(); resourceStream.seekg(0, std::ios::beg); char *data = new char[length]; resourceStream.read(data, length); if (isSVG) { button->setIcon(QmitkStyleManager::ThemeIcon(QByteArray::fromRawData(data, length))); } else { QPixmap pixmap; pixmap.loadFromData(QByteArray::fromRawData(data, length)); button->setIcon(QIcon(pixmap)); } delete[] data; if (m_ShowNames) { if (m_LayoutColumns == 1) button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); else button->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); button->setIconSize(QSize(24, 24)); } else { button->setToolButtonStyle(Qt::ToolButtonIconOnly); button->setIconSize(QSize(32, 32)); button->setToolTip(tooltip); } } if (m_GenerateAccelerators) { QString firstLetter = QString(tool->GetName()); firstLetter.truncate(1); button->setShortcut( firstLetter); // a keyboard shortcut (just the first letter of the given name w/o any CTRL or something) } m_ButtonIDForToolID[currentToolID] = currentButtonID; m_ToolIDForButtonID[currentButtonID] = currentToolID; MITK_DEBUG << "m_ButtonIDForToolID[" << currentToolID << "] == " << currentButtonID; MITK_DEBUG << "m_ToolIDForButtonID[" << currentButtonID << "] == " << currentToolID; tool->GUIProcessEventsMessage += mitk::MessageDelegate( this, &QmitkToolSelectionBox::OnToolGUIProcessEventsMessage); // will never add a listener twice, so we don't have // to check here tool->ErrorMessage += mitk::MessageDelegate1( this, &QmitkToolSelectionBox::OnToolErrorMessage); // will never add a listener twice, so we don't have to check here tool->GeneralMessage += mitk::MessageDelegate1(this, &QmitkToolSelectionBox::OnGeneralToolMessage); ++currentButtonID; } // setting grid layout for this groupbox this->setLayout(m_ButtonLayout); this->UpdateButtonsEnabledState(); // this->update(); } void QmitkToolSelectionBox::OnToolGUIProcessEventsMessage() { qApp->processEvents(); } void QmitkToolSelectionBox::OnToolErrorMessage(std::string s) { QMessageBox::critical( - this, "MITK", QString(s.c_str()), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); + this, "MITK", QString(s.c_str()), QMessageBox::Ok | QMessageBox::NoButton, QMessageBox::NoButton); } void QmitkToolSelectionBox::OnGeneralToolMessage(std::string s) { QMessageBox::information( - this, "MITK", QString(s.c_str()), QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); + this, "MITK", QString(s.c_str()), QMessageBox::Ok | QMessageBox::NoButton, QMessageBox::NoButton); } void QmitkToolSelectionBox::SetDisplayedToolGroups(const std::string &toolGroups) { if (m_DisplayedGroups != toolGroups) { QString q_DisplayedGroups = toolGroups.c_str(); // quote all unquoted single words q_DisplayedGroups = q_DisplayedGroups.replace(QRegularExpression("\\b(\\w+)\\b|'([^']+)'"), "'\\1\\2'"); MITK_DEBUG << "m_DisplayedGroups was \"" << toolGroups << "\""; m_DisplayedGroups = q_DisplayedGroups.toLocal8Bit().constData(); MITK_DEBUG << "m_DisplayedGroups is \"" << m_DisplayedGroups << "\""; RecreateButtons(); SetOrUnsetButtonForActiveTool(); } } void QmitkToolSelectionBox::SetLayoutColumns(int columns) { if (columns > 0 && columns != m_LayoutColumns) { m_LayoutColumns = columns; RecreateButtons(); } } void QmitkToolSelectionBox::SetShowNames(bool show) { if (show != m_ShowNames) { m_ShowNames = show; RecreateButtons(); } } void QmitkToolSelectionBox::SetGenerateAccelerators(bool accel) { if (accel != m_GenerateAccelerators) { m_GenerateAccelerators = accel; RecreateButtons(); } } void QmitkToolSelectionBox::SetToolGUIArea(QWidget *parentWidget) { m_ToolGUIWidget = parentWidget; } diff --git a/Plugins/org.blueberry.ui.qt/src/actions/berryCommandContributionItem.cpp b/Plugins/org.blueberry.ui.qt/src/actions/berryCommandContributionItem.cpp index 5fc1652d1f..56426bdb85 100644 --- a/Plugins/org.blueberry.ui.qt/src/actions/berryCommandContributionItem.cpp +++ b/Plugins/org.blueberry.ui.qt/src/actions/berryCommandContributionItem.cpp @@ -1,726 +1,726 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "berryCommandContributionItem.h" #include "berryIMenuService.h" #include "berryICommandService.h" #include "berryICommandImageService.h" #include "berryIContributionManager.h" #include "berryIElementReference.h" #include "berryIElementUpdater.h" #include "berryUIElement.h" #include #include #include #include #include #include #include #include #include "../berryDisplay.h" #include "../berryAsyncRunnable.h" #include "../handlers/berryIHandlerService.h" #include "../services/berryIServiceLocator.h" #include "../berryWorkbenchPlugin.h" #include #include #include #include #include namespace berry { ContributionItem::Modes CommandContributionItem::modes = ContributionItem::MODE_FORCE_TEXT; //class CommandUIElementListener : public IUIElementListener //{ //private: // CommandContributionItem* item; // public: // CommandUIElementListener(CommandContributionItem* item); // void UIElementDisposed(UIElement* item); //void UIElementSelected(SmartPointer item); //}; CommandContributionItem::CommandContributionItem( const SmartPointer& contributionParameters) : ContributionItem(contributionParameters->id) , action(nullptr) , checkedState(false) { this->icon = contributionParameters->icon; this->label = contributionParameters->label; this->mnemonic = contributionParameters->mnemonic; this->shortcut = contributionParameters->shortcut; this->tooltip = contributionParameters->tooltip; this->style = contributionParameters->style; this->helpContextId = contributionParameters->helpContextId; this->visibleEnabled = contributionParameters->visibleEnabled; this->mode = contributionParameters->mode; menuService = contributionParameters->serviceLocator->GetService(); commandService = contributionParameters->serviceLocator->GetService(); handlerService = contributionParameters->serviceLocator->GetService(); // bindingService = (IBindingService) contributionParameters.serviceLocator // .getService(IBindingService.class); this->CreateCommand(contributionParameters->commandId, contributionParameters->parameters); if (command) { try { class CommandUIElement : public UIElement { private: CommandContributionItem* item; public: CommandUIElement(CommandContributionItem* item, IServiceLocator* serviceLocator) : UIElement(serviceLocator), item(item) {} void SetText(const QString& text) override { item->SetText(text); } void SetToolTip(const QString& text) override { item->SetToolTip(text); } void SetIcon(const QIcon& icon) override { item->SetIcon(icon); } void SetChecked(bool checked) override { item->SetChecked(checked); } void SetDropDownId(const QString& id) override { item->dropDownMenuOverride = id; } }; UIElement::Pointer callback(new CommandUIElement(this, contributionParameters->serviceLocator)); elementRef = commandService->RegisterElementForCommand(command, callback); command->GetCommand()->AddCommandListener(this->GetCommandListener()); this->SetImages(contributionParameters->serviceLocator, contributionParameters->iconStyle); if (contributionParameters->helpContextId.isEmpty()) { try { this->helpContextId = commandService->GetHelpContextId( contributionParameters->commandId); } catch (const NotDefinedException& /*e*/) { // it's OK to not have a helpContextId } } // IWorkbenchLocationService::Pointer wls = contributionParameters.serviceLocator // ->GetService(IWorkbenchLocationService::GetManifestName()).Cast(); // const IWorkbench* workbench = wls->GetWorkbench();; // if (workbench != 0 && !helpContextId.empty()) { // this->workbenchHelpSystem = workbench->GetHelpSystem(); // } } catch (const NotDefinedException& /*e*/) { WorkbenchPlugin::Log(QString("Unable to register menu item \"") + this->GetId() + "\", command \"" + contributionParameters->commandId + "\" not defined"); } } } void CommandContributionItem::Fill(QMenu* parent, QAction* before) { if (!command || action || parent == nullptr) { return; } // Menus don't support the pulldown style Style tmpStyle = style; if (tmpStyle == STYLE_PULLDOWN) tmpStyle = STYLE_PUSH; QAction* item = nullptr; if (before) { item = new QAction(icon, label, parent); parent->insertAction(before, item); } else { item = parent->addAction(icon, label); } // Remove this when key binding support is fully implemented if (!shortcut.isEmpty()) { item->setShortcut(shortcut); } item->setData(QVariant::fromValue(Object::Pointer(this))); item->setProperty("contributionItem", QVariant::fromValue(Object::Pointer(this))); // if (workbenchHelpSystem != null) // { // workbenchHelpSystem.setHelp(item, helpContextId); // } connect(item, SIGNAL(triggered()), SLOT(HandleWidgetSelection())); connect(item, SIGNAL(destroyed()), SLOT(HandleActionDestroyed())); action = item; this->Update(); this->UpdateIcons(); //bindingService.addBindingManagerListener(bindingManagerListener); } void CommandContributionItem::Fill(QToolBar *parent, QAction *before) { if (!command || action || parent == nullptr) { return; } QAction* item = nullptr; if (before) { item = parent->addAction(icon, label); } else { item = new QAction(icon, label, parent); parent->insertAction(before, item); } item->setData(QVariant::fromValue(Object::Pointer(this))); item->setProperty("contributionItem", QVariant::fromValue(Object::Pointer(this))); connect(item, SIGNAL(triggered()), SLOT(HandleWidgetSelection())); connect(item, SIGNAL(destroyed()), SLOT(HandleActionDestroyed())); action = item; this->Update(); this->UpdateIcons(); //bindingService.addBindingManagerListener(bindingManagerListener); } void CommandContributionItem::Update() { this->Update(QString()); } void CommandContributionItem::Update(const QString& /*id*/) { if (action) { - QWidget* parent = action->parentWidget(); + auto parent = qobject_cast(action->parent()); if(qobject_cast(parent)) { this->UpdateMenuItem(); } else if (qobject_cast(parent)) { this->UpdateMenuItem(); } else if (qobject_cast(parent)) { this->UpdateToolItem(); } } } void CommandContributionItem::UpdateMenuItem() { QString text = label; if (text.isEmpty()) { if (command.IsNotNull()) { try { text = command->GetCommand()->GetName(); } catch (const NotDefinedException& e) { // StatusManager.getManager().handle( // StatusUtil.newStatus(IStatus.ERROR, // "Update item failed " // + getId(), e)); BERRY_ERROR << "Update item failed " << GetId() << e.what(); } } } text = UpdateMnemonic(text); // String keyBindingText = null; // if (command != null) // { // TriggerSequence binding = bindingService // .getBestActiveBindingFor(command); // if (binding != null) // { // keyBindingText = binding.format(); // } // } // if (text != null) // { // if (keyBindingText == null) // { // item.setText(text); // } // else // { // item.setText(text + '\t' + keyBindingText); // } // } if (action->isChecked() != checkedState) { action->setChecked(checkedState); } // allow the handler update its enablement bool shouldBeEnabled = IsEnabled(); if (action->isEnabled() != shouldBeEnabled) { action->setEnabled(shouldBeEnabled); } } void CommandContributionItem::UpdateToolItem() { QString text = label; QString tooltip = label; if (text.isNull()) { if (command.IsNotNull()) { try { text = command->GetCommand()->GetName(); tooltip = command->GetCommand()->GetDescription(); if (tooltip.trimmed().isEmpty()) { tooltip = text; } } catch (const NotDefinedException& e) { // StatusManager.getManager().handle( // StatusUtil.newStatus(IStatus.ERROR, // "Update item failed " // + getId(), e)); BERRY_ERROR << "Update item failed " << GetId() << e.what(); } } } if ((icon.isNull() || (mode & MODE_FORCE_TEXT) == MODE_FORCE_TEXT) && !text.isNull()) { action->setText(text); } QString toolTipText = GetToolTipText(tooltip); action->setToolTip(toolTipText); if (action->isChecked() != checkedState) { action->setChecked(checkedState); } // allow the handler update its enablement bool shouldBeEnabled = IsEnabled(); if (action->isEnabled() != shouldBeEnabled) { action->setEnabled(shouldBeEnabled); } } CommandContributionItem::~CommandContributionItem() { if (elementRef) { commandService->UnregisterElement(elementRef); } if (commandListener) { command->GetCommand()->RemoveCommandListener(commandListener.data()); } } bool CommandContributionItem::IsEnabled() const { if (command) { command->GetCommand()->SetEnabled(menuService->GetCurrentState()); return command->GetCommand()->IsEnabled(); } return false; } bool CommandContributionItem::IsVisible() const { if (visibleEnabled) { return ContributionItem::IsVisible() && this->IsEnabled(); } return ContributionItem::IsVisible(); } void CommandContributionItem::SetImages(IServiceLocator* locator, const QString& iconStyle) { if (icon.isNull()) { ICommandImageService* service = locator->GetService(); if (service) { icon = service->GetImage(command->GetId(), iconStyle); } } } ICommandListener* CommandContributionItem::GetCommandListener() { if (!commandListener) { class MyCommandListener : public ICommandListener { private: CommandContributionItem* item; public: MyCommandListener(CommandContributionItem* item) : item(item) {} void CommandChanged(const SmartPointer& commandEvent) override { if (commandEvent->IsHandledChanged() || commandEvent->IsEnabledChanged() || commandEvent->IsDefinedChanged()) { item->UpdateCommandProperties(commandEvent); } } }; commandListener.reset(new MyCommandListener(this)); } return commandListener.data(); } void CommandContributionItem::UpdateCommandProperties(const SmartPointer< const CommandEvent> commandEvent) { if (commandEvent->IsHandledChanged()) { dropDownMenuOverride = ""; } if (!action) { return; } Display* display = Display::GetDefault(); typedef AsyncRunnable, CommandContributionItem > UpdateRunnable; Poco::Runnable* update = new UpdateRunnable(this, &CommandContributionItem::UpdateCommandPropertiesInUI, commandEvent); if (display->InDisplayThread()) { update->run(); } else { display->AsyncExec(update); } } void CommandContributionItem::UpdateCommandPropertiesInUI(const SmartPointer< const CommandEvent>& commandEvent) { if (commandEvent->GetCommand()->IsDefined()) { this->Update(); } if (commandEvent->IsEnabledChanged() || commandEvent->IsHandledChanged()) { if (visibleEnabled) { IContributionManager* parent = this->GetParent(); if (parent) { parent->Update(true); } } } } void CommandContributionItem::HandleActionDestroyed() { this->action = nullptr; } bool CommandContributionItem::ShouldRestoreAppearance(const SmartPointer& handler) { // if no handler or handler doesn't implement IElementUpdater, // restore the contributed elements if (handler.IsNull()) return true; if (!(handler.Cast())) return true; // special case, if its HandlerProxy, then check the actual handler // if (handler instanceof HandlerProxy) { // HandlerProxy handlerProxy = (HandlerProxy) handler; // IHandler actualHandler = handlerProxy.getHandler(); // return shouldRestoreAppearance(actualHandler); // } return false; } SmartPointer CommandContributionItem::GetCommand() const { return command; } void CommandContributionItem::CreateCommand(const QString &commandId, const QHash ¶meters) { if (commandId.isEmpty()) { // StatusManager.getManager().handle(StatusUtil.newStatus(IStatus.ERROR, // "Unable to create menu item \"" + getId() // + "\", no command id", null)); BERRY_ERROR << "Unable to create menu item \"" << this->GetId().toStdString() << "\", no command id"; return; } Command::Pointer cmd = commandService->GetCommand(commandId); if (!cmd->IsDefined()) { // StatusManager.getManager().handle(StatusUtil.newStatus( // IStatus.ERROR, "Unable to create menu item \"" + getId() // + "\", command \"" + commandId + "\" not defined", null)); BERRY_ERROR << "Unable to create menu item \"" << this->GetId().toStdString() << "\", command \"" << commandId.toStdString() << "\" not defined"; return; } command = ParameterizedCommand::GenerateCommand(cmd, parameters); } QString CommandContributionItem::GetToolTipText(const QString& text) const { QString tooltipText = tooltip; if (tooltip.isNull()) { if (!text.isNull()) { tooltipText = text; } else { tooltipText = ""; } } // TriggerSequence activeBinding = bindingService // .getBestActiveBindingFor(command); // if (activeBinding != null && !activeBinding.isEmpty()) // { // String acceleratorText = activeBinding.format(); // if (acceleratorText != null // && acceleratorText.length() != 0) // { // tooltipText = NLS.bind(CommandMessages.Tooltip_Accelerator, // tooltipText, acceleratorText); // } // } return tooltipText; } QString CommandContributionItem::UpdateMnemonic(const QString &s) { if (mnemonic.isNull() || s.isEmpty()) { return s; } int idx = s.indexOf(mnemonic); if (idx == -1) { return s; } return s.left(idx) + '&' + s.mid(idx); } //SmartPointer CommandContributionItem::GetItemListener() //{ // if (!itemListener) // { // itemListener = new CommandUIElementListener(this); // } // return itemListener; //} void CommandContributionItem::HandleWidgetSelection() { // // Special check for ToolBar dropdowns... // if (this->OpenDropDownMenu(event)) // //return; if ((style & STYLE_CHECK) != 0) { checkedState = action->isChecked(); } try { handlerService->ExecuteCommand(command, UIElement::Pointer(nullptr)); } catch (const ExecutionException& e) { WorkbenchPlugin::Log("Failed to execute item " + GetId(), e); } catch (const NotDefinedException& e) { WorkbenchPlugin::Log("Failed to execute item " + GetId(), e); } catch (const NotEnabledException& e) { WorkbenchPlugin::Log("Failed to execute item " + GetId(), e); } catch (const NotHandledException& e) { WorkbenchPlugin::Log("Failed to execute item " + GetId(), e); } } //TODO Tool item drop down menu contributions //bool CommandContributionItem::OpenDropDownMenu(SmartPointer event) //{ //Widget item = event.widget; //if (item != null) //{ // int style = item.getStyle(); // if ((style & SWT.DROP_DOWN) != 0) // { // if (event.detail == 4) // { // on drop-down button // ToolItem ti = (ToolItem) item; // // final MenuManager menuManager = new MenuManager(); // Menu menu = menuManager.createContextMenu(ti.getParent()); // if (workbenchHelpSystem != null) // { // workbenchHelpSystem.setHelp(menu, helpContextId); // } // menuManager.addMenuListener(new IMenuListener() // { // public void menuAboutToShow(IMenuManager manager) // { // String id = getId(); // if (dropDownMenuOverride != null) // { // id = dropDownMenuOverride; // } // menuService.populateContributionManager( // menuManager, "menu:" + id); //$NON-NLS-1$ // } // }); // // // position the menu below the drop down item // Point point = ti.getParent().toDisplay( // new Point(event.x, event.y)); // menu.setLocation(point.x, point.y); // waiting for SWT // // 0.42 // menu.setVisible(true); // return true; // we don't fire the action // } // } //} // //return false; //} void CommandContributionItem::SetIcon(const QIcon &icon) { this->icon = icon; this->UpdateIcons(); } void CommandContributionItem::UpdateIcons() { action->setIcon(icon); } void CommandContributionItem::SetText(const QString &text) { label = text; this->Update(); } void CommandContributionItem::SetChecked(bool checked) { if (checkedState == checked) { return; } checkedState = checked; action->setChecked(checkedState); } void CommandContributionItem::SetToolTip(const QString &text) { tooltip = text; action->setToolTip(text); } } diff --git a/Plugins/org.blueberry.ui.qt/src/internal/berryQtGlobalEventFilter.cpp b/Plugins/org.blueberry.ui.qt/src/internal/berryQtGlobalEventFilter.cpp index d8effa6819..890238f344 100755 --- a/Plugins/org.blueberry.ui.qt/src/internal/berryQtGlobalEventFilter.cpp +++ b/Plugins/org.blueberry.ui.qt/src/internal/berryQtGlobalEventFilter.cpp @@ -1,57 +1,57 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "berryQtGlobalEventFilter.h" #include "berryShell.h" #include "internal/berryQtControlWidget.h" #include #include #include #include #include namespace berry { QtGlobalEventFilter::QtGlobalEventFilter(QObject* parent) : QObject(parent) { } bool QtGlobalEventFilter::eventFilter(QObject* /*obj*/, QEvent* event) { if (event->type() == QEvent::MouseButtonPress) { QMouseEvent* mouseEvent = static_cast(event); - QWidget* widget = QApplication::widgetAt(mouseEvent->globalPos()); + QWidget* widget = QApplication::widgetAt(mouseEvent->globalPosition().toPoint()); if (widget) { QObject* parent = widget; while (parent) { if (parent->objectName() == "PartPaneControl") { (dynamic_cast(parent))->FireActivateEvent(); break; } parent = parent->parent(); } } } return false; } } diff --git a/Plugins/org.blueberry.ui.qt/src/internal/berryQtSash.cpp b/Plugins/org.blueberry.ui.qt/src/internal/berryQtSash.cpp index 637c6084e3..ce880798b5 100755 --- a/Plugins/org.blueberry.ui.qt/src/internal/berryQtSash.cpp +++ b/Plugins/org.blueberry.ui.qt/src/internal/berryQtSash.cpp @@ -1,296 +1,288 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "berryLog.h" #include "berryQtSash.h" #include #include #include #include namespace berry { /*! Creates a QtSash with the given orientation, parent, and smoothness. */ QtSash::QtSash(Qt::Orientation orientation, QWidget *parent, bool smooth) : QWidget(parent), smooth(smooth), orientation(orientation), rubberBand(nullptr), lastX(0), lastY(0) { if (orientation == Qt::Horizontal) this->setCursor(Qt::SplitVCursor); else this->setCursor(Qt::SplitHCursor); } QtSash::~QtSash() { } void QtSash::AddSelectionListener(GuiTk::ISelectionListener::Pointer listener) { selectionEvents.AddListener(listener); } void QtSash::RemoveSelectionListener( GuiTk::ISelectionListener::Pointer listener) { selectionEvents.AddListener(listener); } /*! Returns the sash's orientation. */ Qt::Orientation QtSash::GetOrientation() const { return orientation; } /*! Returns true if widgets are resized dynamically (smoothly), otherwise returns false. */ bool QtSash::SmoothResize() const { return smooth; } /*! Tells the splitter to move this handle to position \a pos, which is the distance from the left or top edge of the widget. Note that \a pos is also measured from the left (or top) for right-to-left languages. This function will map \a pos to the appropriate position before calling QSplitter::moveSplitter(). \sa QSplitter::moveSplitter() closestLegalPosition() */ //void QtSash::moveSplitter(int pos) //{ // Q_D(QSplitterHandle); // if (d->s->isRightToLeft() && d->orient == Qt::Horizontal) // pos = d->s->contentsRect().width() - pos; // d->s->moveSplitter(pos, d->s->indexOf(this)); //} /*! \reimp */ //QSize QtSash::sizeHint() const //{ // Q_D(const QSplitterHandle); // int hw = d->s->handleWidth(); // QStyleOption opt(0); // opt.init(d->s); // opt.state = QStyle::State_None; // return parentWidget()->style()->sizeFromContents(QStyle::CT_Splitter, &opt, QSize(hw, hw), d->s) // .expandedTo(QApplication::globalStrut()); //} /*! \reimp */ bool QtSash::event(QEvent *event) { // switch(event->type()) { // case QEvent::HoverEnter: // d->hover = true; // update(); // break; // case QEvent::HoverLeave: // d->hover = false; // update(); // break; // default: // break; // } return QWidget::event(event); } /*! \reimp */ void QtSash::mouseMoveEvent(QMouseEvent *e) { if (!dragging && !(e->buttons() & Qt::LeftButton)) return; - QPoint eventPoint(e->globalX(), e->globalY()); + auto eventPoint = e->globalPosition().toPoint(); eventPoint = this->parentWidget()->mapFromGlobal(eventPoint); + int eventX = eventPoint.x(); int eventY = eventPoint.y(); -// int eventX = e->globalX(); -// int eventY = e->globalY(); - - //int x = OS.GTK_WIDGET_X (handle); - //int y = OS.GTK_WIDGET_Y (handle); int width = this->geometry().width(); int height = this->geometry().height(); - //int parentBorder = 0; - //int parentWidth = OS.GTK_WIDGET_WIDTH (parent.handle); - //int parentHeight = OS.GTK_WIDGET_HEIGHT (parent.handle); - int newX = lastX; int newY = lastY; if ((orientation & Qt::Vertical) != 0) { //newX = std::min(std::max (0, eventX + x - startX - parentBorder), parentWidth - width); newX = eventX; } else { // newY = Math.min (Math.max (0, eventY + y - startY - parentBorder), parentHeight - height); newY = eventY; } if (newX == lastX && newY == lastY) return; drawRubberBand(lastX, lastY, width, height); GuiTk::SelectionEvent::Pointer event(new GuiTk::SelectionEvent(this)); event->x = newX; event->y = newY; event->width = width; event->height = height; if (!smooth) { event->detail = Constants::DRAG; } selectionEvents.selected(event); if (event->doit) { lastX = event->x; lastY = event->y; } //parent.update (true, (style & SWT.SMOOTH) == 0); drawRubberBand(lastX, lastY, width, height); if (smooth) { setGeometry(lastX, lastY, width, height); // widget could be disposed at this point } } /*! \reimp */ void QtSash::mousePressEvent(QMouseEvent *e) { if (e->button() == Qt::LeftButton) { // const QRect& rect = this->geometry(); // QPoint p1(this->mapToGlobal(rect.topLeft())); // QPoint p2(this->mapToGlobal(rect.bottomRight())); // startRect = QRect(p1, p2); startRect = this->geometry(); lastX = startRect.x(); lastY = startRect.y(); GuiTk::SelectionEvent::Pointer event(new GuiTk::SelectionEvent(this)); event->x = lastX; event->y = lastY; event->width = startRect.width(); event->height = startRect.height(); if (!smooth) { event->detail = Constants::DRAG; } selectionEvents.selected(event); if (event->doit) { dragging = true; lastX = event->x; lastY = event->y; //parent.update (true, (style & SWT.SMOOTH) == 0); drawRubberBand(lastX, lastY, startRect.width(), startRect.height()); if (smooth) { this->setGeometry(lastX, lastY, startRect.width(), startRect.height()); // widget could be disposed at this point } } } } /*! \reimp */ void QtSash::mouseReleaseEvent(QMouseEvent *e) { if (dragging && e->button() == Qt::LeftButton) { this->drawRubberBand(-1, -1, -1, -1); dragging = false; const QRect& rect = this->geometry(); int width = rect.width(); int height = rect.height(); GuiTk::SelectionEvent::Pointer event(new GuiTk::SelectionEvent(this)); event->x = lastX; event->y = lastY; event->width = width; event->height = height; //drawBand (lastX, lastY, width, height); selectionEvents.selected(event); if (event->doit) { if (smooth) { this->setGeometry(event->x, event->y, width, height); // widget could be disposed at this point } } } } void QtSash::drawRubberBand(int x, int y, int width, int height) { if (smooth) return; if (x < 0 || y < 0) { if (this->rubberBand) this->rubberBand->hide(); return; } if (!this->rubberBand) { this->rubberBand = new QRubberBand(QRubberBand::Line, this->parentWidget()); // For accessibility to identify this special widget. this->rubberBand->setObjectName(QLatin1String("qt_rubberband")); } this->rubberBand->setGeometry(x, y, width, height); if (!this->rubberBand->isVisible()) this->rubberBand->show(); } void QtSash::paintEvent(QPaintEvent*) { QStyleOption opt; opt.initFrom(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } } diff --git a/Plugins/org.blueberry.ui.qt/src/internal/berryQtTracker.cpp b/Plugins/org.blueberry.ui.qt/src/internal/berryQtTracker.cpp index 2241519b18..457ee2222a 100755 --- a/Plugins/org.blueberry.ui.qt/src/internal/berryQtTracker.cpp +++ b/Plugins/org.blueberry.ui.qt/src/internal/berryQtTracker.cpp @@ -1,327 +1,327 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "berryTweaklets.h" #include "berryQtTracker.h" #include "berryConstants.h" #include "berryIDropTarget.h" #include "berryDragUtil.h" #include "berryGuiWidgetsTweaklet.h" #include #include #include #include #include namespace berry { CursorType QtDragManager::PositionToCursorType(int positionConstant) { if (positionConstant == Constants::LEFT) return CURSOR_LEFT; if (positionConstant == Constants::RIGHT) return CURSOR_RIGHT; if (positionConstant == Constants::TOP) return CURSOR_TOP; if (positionConstant == Constants::BOTTOM) return CURSOR_BOTTOM; if (positionConstant == Constants::CENTER) return CURSOR_CENTER; return CURSOR_INVALID; } int QtDragManager::CursorTypeToPosition(CursorType dragCursorId) { switch (dragCursorId) { case CURSOR_LEFT: return Constants::LEFT; case CURSOR_RIGHT: return Constants::RIGHT; case CURSOR_TOP: return Constants::TOP; case CURSOR_BOTTOM: return Constants::BOTTOM; case CURSOR_CENTER: return Constants::CENTER; default: return Constants::DEFAULT; } } bool QtDragManager::eventFilter(QObject* o, QEvent* e) { if (beingCancelled) { if (e->type() == QEvent::KeyRelease && ((QKeyEvent*) e)->key() == Qt::Key_Escape) { QApplication::instance()->removeEventFilter(this); beingCancelled = false; eventLoop->exit(); return true; // block the key release } return false; } if (!o->isWidgetType()) return false; if (e->type() == QEvent::MouseMove) { QMouseEvent* me = (QMouseEvent *) e; - this->Move(me->globalPos()); + this->Move(me->globalPosition().toPoint()); return true; } else if (e->type() == QEvent::MouseButtonRelease) { //DEBUG("pre drop"); QApplication::instance()->removeEventFilter(this); beingCancelled = false; eventLoop->exit(); return true; } if (e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease) { QKeyEvent *ke = ((QKeyEvent*) e); if (ke->key() == Qt::Key_Escape && e->type() == QEvent::KeyPress) { this->Cancel(); QApplication::instance()->removeEventFilter(this); //beingCancelled = false; eventLoop->exit(); } else { // move(QCursor::pos()); } return true; // Eat all key events } // ### We bind modality to widgets, so we have to do this // ### "manually". // DnD is modal - eat all other interactive events switch (e->type()) { case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: case QEvent::MouseMove: case QEvent::KeyPress: case QEvent::KeyRelease: case QEvent::Wheel: case QEvent::ShortcutOverride: #ifdef QT3_SUPPORT case QEvent::Accel: case QEvent::AccelAvailable: #endif return true; default: return false; } } void QtDragManager::Cancel() { beingCancelled = true; } void QtDragManager::Move(const QPoint& globalPos) { emit tracker->Moved(tracker, globalPos); } bool QtDragManager::Drag(QtTracker* tracker) { if (tracker == nullptr) return false; this->tracker = tracker; beingCancelled = false; QApplication::instance()->installEventFilter(this); // if (!QWidget::mouseGrabber()) // rubberBand->grabMouse(); eventLoop = new QEventLoop; eventLoop->exec(); delete eventLoop; eventLoop = nullptr; return !beingCancelled; } QtTracker::QtTracker() : rubberBand(nullptr), dragManager(nullptr), cursorOverride(0) { rubberBand = new QRubberBand(QRubberBand::Rectangle); QPalette rubberPalette(rubberBand->palette()); //rubberPalette.setColor(QPalette::Button, QColor(Qt::darkRed)); rubberPalette.setBrush(QPalette::WindowText, QBrush(Qt::darkRed)); rubberPalette.setBrush(QPalette::Window, QBrush(Qt::darkRed)); rubberPalette.setBrush(QPalette::Base, QBrush(Qt::darkRed)); rubberPalette.setBrush(QPalette::Text, QBrush(Qt::darkRed)); rubberBand->setPalette(rubberPalette); rubberBand->ensurePolished(); QPixmap pixCursorTop(":/org.blueberry.ui.qt/cursor_top.xpm"); auto cursorTop = new QCursor(pixCursorTop, 15, 8); cursorMap.insert(CURSOR_TOP, cursorTop); QPixmap pixCursorRight(":/org.blueberry.ui.qt/cursor_right.xpm"); auto cursorRight = new QCursor(pixCursorRight, 23, 15); cursorMap.insert(CURSOR_RIGHT, cursorRight); QPixmap pixCursorBottom(":/org.blueberry.ui.qt/cursor_bottom.xpm"); auto cursorBottom = new QCursor(pixCursorBottom, 16, 23); cursorMap.insert(CURSOR_BOTTOM, cursorBottom); QPixmap pixCursorLeft(":/org.blueberry.ui.qt/cursor_left.xpm"); auto cursorLeft = new QCursor(pixCursorLeft, 8, 15); cursorMap.insert(CURSOR_LEFT, cursorLeft); QPixmap pixCursorCenter(":/org.blueberry.ui.qt/cursor_center.xpm"); auto cursorCenter = new QCursor(pixCursorCenter, 15, 15); cursorMap.insert(CURSOR_CENTER, cursorCenter); QPixmap pixCursorOffscreen(":/org.blueberry.ui.qt/cursor_offscreen.xpm"); auto cursorOffscreen = new QCursor(pixCursorOffscreen, 15, 15); cursorMap.insert(CURSOR_OFFSCREEN, cursorOffscreen); auto cursorInvalid = new QCursor(Qt::ForbiddenCursor); cursorMap.insert(CURSOR_INVALID, cursorInvalid); } QtTracker::~QtTracker() { delete rubberBand; for (QHash::iterator iter = cursorMap.begin(); iter != cursorMap.end(); ++iter) { delete iter.value(); } } QRect QtTracker::GetRectangle() const { return rubberBand->geometry(); } void QtTracker::SetRectangle(const QRect& rectangle) { rubberBand->setGeometry(rectangle); } void QtTracker::SetCursor(CursorType cursorType) { QCursor* cursor = cursorMap[cursorType]; if (!cursor) return; if (cursorOverride > 0) { QApplication::changeOverrideCursor(*cursor); } else { ++cursorOverride; QApplication::setOverrideCursor(*cursor); } } bool QtTracker::Open() { rubberBand->show(); dragManager = new QtDragManager(); bool result = dragManager->Drag(this); delete dragManager; rubberBand->hide(); while (cursorOverride > 0) { QApplication::restoreOverrideCursor(); --cursorOverride; } return result; } QtTrackerMoveListener::QtTrackerMoveListener(Object::Pointer draggedItem, const QRect& sourceBounds, const QPoint& initialLocation, bool allowSnapping) : allowSnapping(allowSnapping) , draggedItem(draggedItem) , sourceBounds(sourceBounds) , initialLocation(initialLocation) { } void QtTrackerMoveListener::Moved(QtTracker* tracker, const QPoint& location) { // Select a drop target; use the global one by default IDropTarget::Pointer target; QWidget* targetControl = Tweaklets::Get(GuiWidgetsTweaklet::KEY)->GetCursorControl(); // Get the drop target for this location target = DragUtil::GetDropTarget(targetControl, draggedItem, location, tracker->GetRectangle()); // Set up the tracker feedback based on the target QRect snapTarget; if (target != 0) { snapTarget = target->GetSnapRectangle(); tracker->SetCursor(target->GetCursor()); } else { tracker->SetCursor(CURSOR_INVALID); } // If snapping then reset the tracker's rectangle based on the current drop target if (allowSnapping) { if (snapTarget.width() <= 0 || snapTarget.height() <= 0) { snapTarget = QRect(sourceBounds.x() + location.x() - initialLocation.x(), sourceBounds.y() + location.y() - initialLocation.y(), sourceBounds.width(), sourceBounds.height()); } // Try to prevent flicker: don't change the rectangles if they're already in // the right location QRect currentRectangle = tracker->GetRectangle(); if (!(currentRectangle == snapTarget)) { tracker->SetRectangle(snapTarget); } } } } diff --git a/Plugins/org.mitk.gui.qt.datamanager/src/internal/QmitkDataManagerItemDelegate.cpp b/Plugins/org.mitk.gui.qt.datamanager/src/internal/QmitkDataManagerItemDelegate.cpp index fc48fd6312..6c34ebeb8d 100644 --- a/Plugins/org.mitk.gui.qt.datamanager/src/internal/QmitkDataManagerItemDelegate.cpp +++ b/Plugins/org.mitk.gui.qt.datamanager/src/internal/QmitkDataManagerItemDelegate.cpp @@ -1,41 +1,41 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include #include "QmitkDataManagerItemDelegate.h" QmitkDataManagerItemDelegate::QmitkDataManagerItemDelegate(QObject* parent) : QStyledItemDelegate(parent) { } QmitkDataManagerItemDelegate::~QmitkDataManagerItemDelegate() { } void QmitkDataManagerItemDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const { QVariant data = index.data(); if (!data.isValid()) return; - if (data.type() == QVariant::String) + if (data.typeId() == QMetaType::QString) { QLineEdit* lineEdit = qobject_cast(editor); lineEdit->setText(data.toString()); } else { QStyledItemDelegate::setEditorData(editor, index); } } diff --git a/Plugins/org.mitk.gui.qt.ext/src/QmitkExtWorkbenchWindowAdvisor.cpp b/Plugins/org.mitk.gui.qt.ext/src/QmitkExtWorkbenchWindowAdvisor.cpp index 50c9125b77..4ce0584739 100644 --- a/Plugins/org.mitk.gui.qt.ext/src/QmitkExtWorkbenchWindowAdvisor.cpp +++ b/Plugins/org.mitk.gui.qt.ext/src/QmitkExtWorkbenchWindowAdvisor.cpp @@ -1,1444 +1,1425 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "QmitkExtWorkbenchWindowAdvisor.h" #include "QmitkExtActionBarAdvisor.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // UGLYYY #include "internal/QmitkExtWorkbenchWindowAdvisorHack.h" #include "internal/QmitkCommonExtPlugin.h" #include "mitkUndoController.h" #include "mitkVerboseLimitedLinearUndo.h" #include #include #include #include #include #include QmitkExtWorkbenchWindowAdvisorHack* QmitkExtWorkbenchWindowAdvisorHack::undohack = new QmitkExtWorkbenchWindowAdvisorHack(); QString QmitkExtWorkbenchWindowAdvisor::QT_SETTINGS_FILENAME = "QtSettings.ini"; static bool USE_EXPERIMENTAL_COMMAND_CONTRIBUTIONS = false; class PartListenerForTitle: public berry::IPartListener { public: PartListenerForTitle(QmitkExtWorkbenchWindowAdvisor* wa) : windowAdvisor(wa) { } Events::Types GetPartEventTypes() const override { return Events::ACTIVATED | Events::BROUGHT_TO_TOP | Events::CLOSED | Events::HIDDEN | Events::VISIBLE; } void PartActivated(const berry::IWorkbenchPartReference::Pointer& ref) override { if (ref.Cast ()) { windowAdvisor->UpdateTitle(false); } } void PartBroughtToTop(const berry::IWorkbenchPartReference::Pointer& ref) override { if (ref.Cast ()) { windowAdvisor->UpdateTitle(false); } } void PartClosed(const berry::IWorkbenchPartReference::Pointer& /*ref*/) override { windowAdvisor->UpdateTitle(false); } void PartHidden(const berry::IWorkbenchPartReference::Pointer& ref) override { auto lockedLastActiveEditor = windowAdvisor->lastActiveEditor.Lock(); if (lockedLastActiveEditor.IsNotNull() && ref->GetPart(false) == lockedLastActiveEditor) { windowAdvisor->UpdateTitle(true); } } void PartVisible(const berry::IWorkbenchPartReference::Pointer& ref) override { auto lockedLastActiveEditor = windowAdvisor->lastActiveEditor.Lock(); if (lockedLastActiveEditor.IsNotNull() && ref->GetPart(false) == lockedLastActiveEditor) { windowAdvisor->UpdateTitle(false); } } private: QmitkExtWorkbenchWindowAdvisor* windowAdvisor; }; class PartListenerForViewNavigator: public berry::IPartListener { public: PartListenerForViewNavigator(QAction* act) : viewNavigatorAction(act) { } Events::Types GetPartEventTypes() const override { return Events::OPENED | Events::CLOSED | Events::HIDDEN | Events::VISIBLE; } void PartOpened(const berry::IWorkbenchPartReference::Pointer& ref) override { if (ref->GetId()=="org.mitk.views.viewnavigator") { viewNavigatorAction->setChecked(true); } } void PartClosed(const berry::IWorkbenchPartReference::Pointer& ref) override { if (ref->GetId()=="org.mitk.views.viewnavigator") { viewNavigatorAction->setChecked(false); } } void PartVisible(const berry::IWorkbenchPartReference::Pointer& ref) override { if (ref->GetId()=="org.mitk.views.viewnavigator") { viewNavigatorAction->setChecked(true); } } void PartHidden(const berry::IWorkbenchPartReference::Pointer& ref) override { if (ref->GetId()=="org.mitk.views.viewnavigator") { viewNavigatorAction->setChecked(false); } } private: QAction* viewNavigatorAction; }; class PartListenerForImageNavigator: public berry::IPartListener { public: PartListenerForImageNavigator(QAction* act) : imageNavigatorAction(act) { } Events::Types GetPartEventTypes() const override { return Events::OPENED | Events::CLOSED | Events::HIDDEN | Events::VISIBLE; } void PartOpened(const berry::IWorkbenchPartReference::Pointer& ref) override { if (ref->GetId()=="org.mitk.views.imagenavigator") { imageNavigatorAction->setChecked(true); } } void PartClosed(const berry::IWorkbenchPartReference::Pointer& ref) override { if (ref->GetId()=="org.mitk.views.imagenavigator") { imageNavigatorAction->setChecked(false); } } void PartVisible(const berry::IWorkbenchPartReference::Pointer& ref) override { if (ref->GetId()=="org.mitk.views.imagenavigator") { imageNavigatorAction->setChecked(true); } } void PartHidden(const berry::IWorkbenchPartReference::Pointer& ref) override { if (ref->GetId()=="org.mitk.views.imagenavigator") { imageNavigatorAction->setChecked(false); } } private: QAction* imageNavigatorAction; }; class PerspectiveListenerForTitle: public berry::IPerspectiveListener { public: PerspectiveListenerForTitle(QmitkExtWorkbenchWindowAdvisor* wa) : windowAdvisor(wa) , perspectivesClosed(false) { } Events::Types GetPerspectiveEventTypes() const override { if (USE_EXPERIMENTAL_COMMAND_CONTRIBUTIONS) { return Events::ACTIVATED | Events::SAVED_AS | Events::DEACTIVATED; } else { return Events::ACTIVATED | Events::SAVED_AS | Events::DEACTIVATED | Events::CLOSED | Events::OPENED; } } void PerspectiveActivated(const berry::IWorkbenchPage::Pointer& /*page*/, const berry::IPerspectiveDescriptor::Pointer& /*perspective*/) override { windowAdvisor->UpdateTitle(false); } void PerspectiveSavedAs(const berry::IWorkbenchPage::Pointer& /*page*/, const berry::IPerspectiveDescriptor::Pointer& /*oldPerspective*/, const berry::IPerspectiveDescriptor::Pointer& /*newPerspective*/) override { windowAdvisor->UpdateTitle(false); } void PerspectiveDeactivated(const berry::IWorkbenchPage::Pointer& /*page*/, const berry::IPerspectiveDescriptor::Pointer& /*perspective*/) override { windowAdvisor->UpdateTitle(false); } void PerspectiveOpened(const berry::IWorkbenchPage::Pointer& /*page*/, const berry::IPerspectiveDescriptor::Pointer& /*perspective*/) override { if (perspectivesClosed) { QListIterator i(windowAdvisor->viewActions); while (i.hasNext()) { i.next()->setEnabled(true); } //GetViewRegistry()->Find("org.mitk.views.imagenavigator"); if(windowAdvisor->GetWindowConfigurer()->GetWindow()->GetWorkbench()->GetEditorRegistry()->FindEditor("org.mitk.editors.dicombrowser")) { windowAdvisor->openDicomEditorAction->setEnabled(true); } if (windowAdvisor->GetWindowConfigurer()->GetWindow()->GetWorkbench()->GetEditorRegistry()->FindEditor("org.mitk.editors.stdmultiwidget")) { windowAdvisor->openStdMultiWidgetEditorAction->setEnabled(true); } if (windowAdvisor->GetWindowConfigurer()->GetWindow()->GetWorkbench()->GetEditorRegistry()->FindEditor("org.mitk.editors.mxnmultiwidget")) { windowAdvisor->openMxNMultiWidgetEditorAction->setEnabled(true); } windowAdvisor->fileSaveProjectAction->setEnabled(true); windowAdvisor->closeProjectAction->setEnabled(true); windowAdvisor->undoAction->setEnabled(true); windowAdvisor->redoAction->setEnabled(true); windowAdvisor->imageNavigatorAction->setEnabled(true); windowAdvisor->viewNavigatorAction->setEnabled(true); windowAdvisor->resetPerspAction->setEnabled(true); if( windowAdvisor->GetShowClosePerspectiveMenuItem() ) { windowAdvisor->closePerspAction->setEnabled(true); } } perspectivesClosed = false; } void PerspectiveClosed(const berry::IWorkbenchPage::Pointer& /*page*/, const berry::IPerspectiveDescriptor::Pointer& /*perspective*/) override { berry::IWorkbenchWindow::Pointer wnd = windowAdvisor->GetWindowConfigurer()->GetWindow(); bool allClosed = true; if (wnd->GetActivePage()) { QList perspectives(wnd->GetActivePage()->GetOpenPerspectives()); allClosed = perspectives.empty(); } if (allClosed) { perspectivesClosed = true; QListIterator i(windowAdvisor->viewActions); while (i.hasNext()) { i.next()->setEnabled(false); } if(windowAdvisor->GetWindowConfigurer()->GetWindow()->GetWorkbench()->GetEditorRegistry()->FindEditor("org.mitk.editors.dicombrowser")) { windowAdvisor->openDicomEditorAction->setEnabled(false); } if (windowAdvisor->GetWindowConfigurer()->GetWindow()->GetWorkbench()->GetEditorRegistry()->FindEditor("org.mitk.editors.stdmultiwidget")) { windowAdvisor->openStdMultiWidgetEditorAction->setEnabled(false); } if (windowAdvisor->GetWindowConfigurer()->GetWindow()->GetWorkbench()->GetEditorRegistry()->FindEditor("org.mitk.editors.mxnmultiwidget")) { windowAdvisor->openMxNMultiWidgetEditorAction->setEnabled(false); } windowAdvisor->fileSaveProjectAction->setEnabled(false); windowAdvisor->closeProjectAction->setEnabled(false); windowAdvisor->undoAction->setEnabled(false); windowAdvisor->redoAction->setEnabled(false); windowAdvisor->imageNavigatorAction->setEnabled(false); windowAdvisor->viewNavigatorAction->setEnabled(false); windowAdvisor->resetPerspAction->setEnabled(false); if( windowAdvisor->GetShowClosePerspectiveMenuItem() ) { windowAdvisor->closePerspAction->setEnabled(false); } } } private: QmitkExtWorkbenchWindowAdvisor* windowAdvisor; bool perspectivesClosed; }; class PerspectiveListenerForMenu: public berry::IPerspectiveListener { public: PerspectiveListenerForMenu(QmitkExtWorkbenchWindowAdvisor* wa) : windowAdvisor(wa) { } Events::Types GetPerspectiveEventTypes() const override { return Events::ACTIVATED | Events::DEACTIVATED; } void PerspectiveActivated(const berry::IWorkbenchPage::Pointer& /*page*/, const berry::IPerspectiveDescriptor::Pointer& perspective) override { QAction* action = windowAdvisor->mapPerspIdToAction[perspective->GetId()]; if (action) { action->setChecked(true); } } void PerspectiveDeactivated(const berry::IWorkbenchPage::Pointer& /*page*/, const berry::IPerspectiveDescriptor::Pointer& perspective) override { QAction* action = windowAdvisor->mapPerspIdToAction[perspective->GetId()]; if (action) { action->setChecked(false); } } private: QmitkExtWorkbenchWindowAdvisor* windowAdvisor; }; QmitkExtWorkbenchWindowAdvisor::QmitkExtWorkbenchWindowAdvisor(berry::WorkbenchAdvisor* wbAdvisor, berry::IWorkbenchWindowConfigurer::Pointer configurer) : berry::WorkbenchWindowAdvisor(configurer) , lastInput(nullptr) , wbAdvisor(wbAdvisor) , showViewToolbar(true) , showPerspectiveToolbar(false) , showVersionInfo(true) , showMitkVersionInfo(true) , showViewMenuItem(true) , showNewWindowMenuItem(false) , showClosePerspectiveMenuItem(true) , viewNavigatorFound(false) , showMemoryIndicator(true) , dropTargetListener(new QmitkDefaultDropTargetListener) { productName = QCoreApplication::applicationName(); viewExcludeList.push_back("org.mitk.views.viewnavigator"); } QmitkExtWorkbenchWindowAdvisor::~QmitkExtWorkbenchWindowAdvisor() { } berry::ActionBarAdvisor::Pointer QmitkExtWorkbenchWindowAdvisor::CreateActionBarAdvisor(berry::IActionBarConfigurer::Pointer configurer) { if (USE_EXPERIMENTAL_COMMAND_CONTRIBUTIONS) { berry::ActionBarAdvisor::Pointer actionBarAdvisor(new QmitkExtActionBarAdvisor(configurer)); return actionBarAdvisor; } else { return berry::WorkbenchWindowAdvisor::CreateActionBarAdvisor(configurer); } } QWidget* QmitkExtWorkbenchWindowAdvisor::CreateEmptyWindowContents(QWidget* parent) { QWidget* parentWidget = static_cast(parent); auto label = new QLabel(parentWidget); label->setText("No perspectives are open. Open a perspective in the Window->Open Perspective menu."); label->setContentsMargins(10,10,10,10); label->setAlignment(Qt::AlignTop); label->setEnabled(false); parentWidget->layout()->addWidget(label); return label; } void QmitkExtWorkbenchWindowAdvisor::ShowClosePerspectiveMenuItem(bool show) { showClosePerspectiveMenuItem = show; } bool QmitkExtWorkbenchWindowAdvisor::GetShowClosePerspectiveMenuItem() { return showClosePerspectiveMenuItem; } void QmitkExtWorkbenchWindowAdvisor::ShowMemoryIndicator(bool show) { showMemoryIndicator = show; } bool QmitkExtWorkbenchWindowAdvisor::GetShowMemoryIndicator() { return showMemoryIndicator; } void QmitkExtWorkbenchWindowAdvisor::ShowNewWindowMenuItem(bool show) { showNewWindowMenuItem = show; } void QmitkExtWorkbenchWindowAdvisor::ShowViewToolbar(bool show) { showViewToolbar = show; } void QmitkExtWorkbenchWindowAdvisor::ShowViewMenuItem(bool show) { showViewMenuItem = show; } void QmitkExtWorkbenchWindowAdvisor::ShowPerspectiveToolbar(bool show) { showPerspectiveToolbar = show; } void QmitkExtWorkbenchWindowAdvisor::ShowVersionInfo(bool show) { showVersionInfo = show; } void QmitkExtWorkbenchWindowAdvisor::ShowMitkVersionInfo(bool show) { showMitkVersionInfo = show; } void QmitkExtWorkbenchWindowAdvisor::SetProductName(const QString& product) { productName = product; } void QmitkExtWorkbenchWindowAdvisor::SetWindowIcon(const QString& wndIcon) { windowIcon = wndIcon; } void QmitkExtWorkbenchWindowAdvisor::PostWindowCreate() { // very bad hack... berry::IWorkbenchWindow::Pointer window = this->GetWindowConfigurer()->GetWindow(); QMainWindow* mainWindow = qobject_cast (window->GetShell()->GetControl()); if (!windowIcon.isEmpty()) { mainWindow->setWindowIcon(QIcon(windowIcon)); } mainWindow->setContextMenuPolicy(Qt::PreventContextMenu); // Load icon theme QIcon::setThemeSearchPaths(QStringList() << QStringLiteral(":/org_mitk_icons/icons/")); QIcon::setThemeName(QStringLiteral("awesome")); // ==== Application menu ============================ QMenuBar* menuBar = mainWindow->menuBar(); menuBar->setContextMenuPolicy(Qt::PreventContextMenu); #ifdef __APPLE__ menuBar->setNativeMenuBar(true); #else menuBar->setNativeMenuBar(false); #endif auto basePath = QStringLiteral(":/org_mitk_icons/icons/awesome/scalable/actions/"); auto fileOpenAction = new QmitkFileOpenAction(berry::QtStyleManager::ThemeIcon(basePath + "document-open.svg"), window); fileOpenAction->setShortcut(QKeySequence::Open); auto fileSaveAction = new QmitkFileSaveAction(berry::QtStyleManager::ThemeIcon(basePath + "document-save.svg"), window); fileSaveAction->setShortcut(QKeySequence::Save); fileSaveProjectAction = new QmitkExtFileSaveProjectAction(window); fileSaveProjectAction->setIcon(berry::QtStyleManager::ThemeIcon(basePath + "document-save.svg")); closeProjectAction = new QmitkCloseProjectAction(window); closeProjectAction->setIcon(berry::QtStyleManager::ThemeIcon(basePath + "edit-delete.svg")); auto perspGroup = new QActionGroup(menuBar); std::map VDMap; // sort elements (converting vector to map...) QList::const_iterator iter; berry::IViewRegistry* viewRegistry = berry::PlatformUI::GetWorkbench()->GetViewRegistry(); const QList viewDescriptors = viewRegistry->GetViews(); bool skip = false; for (iter = viewDescriptors.begin(); iter != viewDescriptors.end(); ++iter) { // if viewExcludeList is set, it contains the id-strings of view, which // should not appear as an menu-entry in the menu if (viewExcludeList.size() > 0) { for (int i=0; iGetId()) { skip = true; break; } } if (skip) { skip = false; continue; } } if ((*iter)->GetId() == "org.blueberry.ui.internal.introview") continue; if ((*iter)->GetId() == "org.mitk.views.imagenavigator") continue; if ((*iter)->GetId() == "org.mitk.views.viewnavigator") continue; std::pair p((*iter)->GetLabel(), (*iter)); VDMap.insert(p); } std::map::const_iterator MapIter; for (MapIter = VDMap.begin(); MapIter != VDMap.end(); ++MapIter) { berry::QtShowViewAction* viewAction = new berry::QtShowViewAction(window, (*MapIter).second); viewActions.push_back(viewAction); } if (!USE_EXPERIMENTAL_COMMAND_CONTRIBUTIONS) { QMenu* fileMenu = menuBar->addMenu("&File"); fileMenu->setObjectName("FileMenu"); fileMenu->addAction(fileOpenAction); fileMenu->addAction(fileSaveAction); fileMenu->addAction(fileSaveProjectAction); fileMenu->addAction(closeProjectAction); fileMenu->addSeparator(); QAction* fileExitAction = new QmitkFileExitAction(window); fileExitAction->setIcon(berry::QtStyleManager::ThemeIcon(basePath + "system-log-out.svg")); fileExitAction->setShortcut(QKeySequence::Quit); fileExitAction->setObjectName("QmitkFileExitAction"); fileMenu->addAction(fileExitAction); // another bad hack to get an edit/undo menu... QMenu* editMenu = menuBar->addMenu("&Edit"); - undoAction = editMenu->addAction(berry::QtStyleManager::ThemeIcon(basePath + "edit-undo.svg"), + undoAction = editMenu->addAction( + berry::QtStyleManager::ThemeIcon(basePath + "edit-undo.svg"), "&Undo", - QmitkExtWorkbenchWindowAdvisorHack::undohack, SLOT(onUndo()), - QKeySequence("CTRL+Z")); + QKeySequence("CTRL+Z"), + QmitkExtWorkbenchWindowAdvisorHack::undohack, + SLOT(onUndo())); undoAction->setToolTip("Undo the last action (not supported by all modules)"); - redoAction = editMenu->addAction(berry::QtStyleManager::ThemeIcon(basePath + "edit-redo.svg"), + redoAction = editMenu->addAction( + berry::QtStyleManager::ThemeIcon(basePath + "edit-redo.svg"), "&Redo", - QmitkExtWorkbenchWindowAdvisorHack::undohack, SLOT(onRedo()), - QKeySequence("CTRL+Y")); + QKeySequence("CTRL+Y"), + QmitkExtWorkbenchWindowAdvisorHack::undohack, + SLOT(onRedo())); redoAction->setToolTip("execute the last action that was undone again (not supported by all modules)"); // ==== Window Menu ========================== QMenu* windowMenu = menuBar->addMenu("Window"); if (showNewWindowMenuItem) { windowMenu->addAction("&New Window", QmitkExtWorkbenchWindowAdvisorHack::undohack, SLOT(onNewWindow())); windowMenu->addSeparator(); } QMenu* perspMenu = windowMenu->addMenu("&Open Perspective"); QMenu* viewMenu = nullptr; if (showViewMenuItem) { viewMenu = windowMenu->addMenu("Show &View"); viewMenu->setObjectName("Show View"); } windowMenu->addSeparator(); resetPerspAction = windowMenu->addAction("&Reset Perspective", QmitkExtWorkbenchWindowAdvisorHack::undohack, SLOT(onResetPerspective())); if(showClosePerspectiveMenuItem) closePerspAction = windowMenu->addAction("&Close Perspective", QmitkExtWorkbenchWindowAdvisorHack::undohack, SLOT(onClosePerspective())); windowMenu->addSeparator(); - windowMenu->addAction("&Preferences...", - QmitkExtWorkbenchWindowAdvisorHack::undohack, SLOT(onEditPreferences()), - QKeySequence("CTRL+P")); + windowMenu->addAction("&Preferences...", QKeySequence("CTRL+P"), + QmitkExtWorkbenchWindowAdvisorHack::undohack, SLOT(onEditPreferences())); // fill perspective menu berry::IPerspectiveRegistry* perspRegistry = window->GetWorkbench()->GetPerspectiveRegistry(); QList perspectives( perspRegistry->GetPerspectives()); skip = false; for (QList::iterator perspIt = perspectives.begin(); perspIt != perspectives.end(); ++perspIt) { // if perspectiveExcludeList is set, it contains the id-strings of perspectives, which // should not appear as an menu-entry in the perspective menu if (perspectiveExcludeList.size() > 0) { for (int i=0; iGetId()) { skip = true; break; } } if (skip) { skip = false; continue; } } QAction* perspAction = new berry::QtOpenPerspectiveAction(window, *perspIt, perspGroup); mapPerspIdToAction.insert((*perspIt)->GetId(), perspAction); } perspMenu->addActions(perspGroup->actions()); if (showViewMenuItem) { for (auto viewAction : std::as_const(viewActions)) { viewMenu->addAction(viewAction); } } // ===== Help menu ==================================== QMenu* helpMenu = menuBar->addMenu("&Help"); helpMenu->addAction("&Welcome",this, SLOT(onIntro())); helpMenu->addAction("&Open Help Perspective", this, SLOT(onHelpOpenHelpPerspective())); - helpMenu->addAction("&Context Help",this, SLOT(onHelp()), QKeySequence("F1")); + helpMenu->addAction("&Context Help", QKeySequence("F1"), this, SLOT(onHelp())); helpMenu->addAction("&About",this, SLOT(onAbout())); // ===================================================== } else { undoAction = new QmitkUndoAction(berry::QtStyleManager::ThemeIcon(basePath + "edit-undo.svg"), nullptr); undoAction->setShortcut(QKeySequence::Undo); redoAction = new QmitkRedoAction(berry::QtStyleManager::ThemeIcon(basePath + "edit-redo.svg"), nullptr); redoAction->setShortcut(QKeySequence::Redo); } // toolbar for showing file open, undo, redo and other main actions auto mainActionsToolBar = new QToolBar; mainActionsToolBar->setObjectName("mainActionsToolBar"); mainActionsToolBar->setContextMenuPolicy(Qt::PreventContextMenu); #ifdef __APPLE__ mainActionsToolBar->setToolButtonStyle ( Qt::ToolButtonTextUnderIcon ); #else mainActionsToolBar->setToolButtonStyle ( Qt::ToolButtonTextBesideIcon ); #endif basePath = QStringLiteral(":/org.mitk.gui.qt.ext/"); imageNavigatorAction = new QAction(berry::QtStyleManager::ThemeIcon(basePath + "image_navigator.svg"), "&Image Navigator", nullptr); bool imageNavigatorViewFound = window->GetWorkbench()->GetViewRegistry()->Find("org.mitk.views.imagenavigator"); if (this->GetWindowConfigurer()->GetWindow()->GetWorkbench()->GetEditorRegistry()->FindEditor("org.mitk.editors.dicombrowser")) { openDicomEditorAction = new QmitkOpenDicomEditorAction(berry::QtStyleManager::ThemeIcon(basePath + "dicom.svg"), window); } if (this->GetWindowConfigurer()->GetWindow()->GetWorkbench()->GetEditorRegistry()->FindEditor("org.mitk.editors.stdmultiwidget")) { openStdMultiWidgetEditorAction = new QmitkOpenStdMultiWidgetEditorAction(berry::QtStyleManager::ThemeIcon(basePath + "Editor.svg"), window); } if (this->GetWindowConfigurer()->GetWindow()->GetWorkbench()->GetEditorRegistry()->FindEditor("org.mitk.editors.mxnmultiwidget")) { openMxNMultiWidgetEditorAction = new QmitkOpenMxNMultiWidgetEditorAction(berry::QtStyleManager::ThemeIcon(basePath + "Editor.svg"), window); } if (imageNavigatorViewFound) { QObject::connect(imageNavigatorAction, SIGNAL(triggered(bool)), QmitkExtWorkbenchWindowAdvisorHack::undohack, SLOT(onImageNavigator())); imageNavigatorAction->setCheckable(true); // add part listener for image navigator imageNavigatorPartListener.reset(new PartListenerForImageNavigator(imageNavigatorAction)); window->GetPartService()->AddPartListener(imageNavigatorPartListener.data()); berry::IViewPart::Pointer imageNavigatorView = window->GetActivePage()->FindView("org.mitk.views.imagenavigator"); imageNavigatorAction->setChecked(false); if (imageNavigatorView) { bool isImageNavigatorVisible = window->GetActivePage()->IsPartVisible(imageNavigatorView); if (isImageNavigatorVisible) imageNavigatorAction->setChecked(true); } imageNavigatorAction->setToolTip("Toggle image navigator for navigating through image"); } viewNavigatorAction = new QAction(berry::QtStyleManager::ThemeIcon(QStringLiteral(":/org.mitk.gui.qt.ext/view-manager.svg")),"&View Navigator", nullptr); viewNavigatorFound = window->GetWorkbench()->GetViewRegistry()->Find("org.mitk.views.viewnavigator"); if (viewNavigatorFound) { QObject::connect(viewNavigatorAction, SIGNAL(triggered(bool)), QmitkExtWorkbenchWindowAdvisorHack::undohack, SLOT(onViewNavigator())); viewNavigatorAction->setCheckable(true); // add part listener for view navigator viewNavigatorPartListener.reset(new PartListenerForViewNavigator(viewNavigatorAction)); window->GetPartService()->AddPartListener(viewNavigatorPartListener.data()); berry::IViewPart::Pointer viewnavigatorview = window->GetActivePage()->FindView("org.mitk.views.viewnavigator"); viewNavigatorAction->setChecked(false); if (viewnavigatorview) { bool isViewNavigatorVisible = window->GetActivePage()->IsPartVisible(viewnavigatorview); if (isViewNavigatorVisible) viewNavigatorAction->setChecked(true); } viewNavigatorAction->setToolTip("Toggle View Navigator"); } mainActionsToolBar->addAction(fileOpenAction); mainActionsToolBar->addAction(fileSaveProjectAction); mainActionsToolBar->addAction(closeProjectAction); mainActionsToolBar->addAction(undoAction); mainActionsToolBar->addAction(redoAction); if(this->GetWindowConfigurer()->GetWindow()->GetWorkbench()->GetEditorRegistry()->FindEditor("org.mitk.editors.dicombrowser")) { mainActionsToolBar->addAction(openDicomEditorAction); } if (this->GetWindowConfigurer()->GetWindow()->GetWorkbench()->GetEditorRegistry()->FindEditor("org.mitk.editors.stdmultiwidget")) { mainActionsToolBar->addAction(openStdMultiWidgetEditorAction); } if (this->GetWindowConfigurer()->GetWindow()->GetWorkbench()->GetEditorRegistry()->FindEditor("org.mitk.editors.mxnmultiwidget")) { mainActionsToolBar->addAction(openMxNMultiWidgetEditorAction); } if (imageNavigatorViewFound) { mainActionsToolBar->addAction(imageNavigatorAction); } if (viewNavigatorFound) { mainActionsToolBar->addAction(viewNavigatorAction); } mainWindow->addToolBar(mainActionsToolBar); // ==== Perspective Toolbar ================================== auto qPerspectiveToolbar = new QToolBar; qPerspectiveToolbar->setObjectName("perspectiveToolBar"); if (showPerspectiveToolbar) { qPerspectiveToolbar->addActions(perspGroup->actions()); mainWindow->addToolBar(qPerspectiveToolbar); } else delete qPerspectiveToolbar; if (showViewToolbar) { auto* prefService = mitk::CoreServices::GetPreferencesService(); auto* stylePrefs = prefService->GetSystemPreferences()->Node(berry::QtPreferences::QT_STYLES_NODE); bool showCategoryNames = stylePrefs->GetBool(berry::QtPreferences::QT_SHOW_TOOLBAR_CATEGORY_NAMES, true); // Order view descriptors by category QMultiMap categoryViewDescriptorMap; for (const auto &labelViewDescriptorPair : VDMap) { auto viewDescriptor = labelViewDescriptorPair.second; auto category = !viewDescriptor->GetCategoryPath().isEmpty() ? viewDescriptor->GetCategoryPath().back() : QString(); categoryViewDescriptorMap.insert(category, viewDescriptor); } // Create a separate toolbar for each category for (const auto &category : categoryViewDescriptorMap.uniqueKeys()) { auto viewDescriptorsInCurrentCategory = categoryViewDescriptorMap.values(category); if (!viewDescriptorsInCurrentCategory.isEmpty()) { auto toolbar = new QToolBar; toolbar->setObjectName(category + " View Toolbar"); mainWindow->addToolBar(toolbar); if (showCategoryNames && !category.isEmpty()) { auto categoryButton = new QToolButton; categoryButton->setToolButtonStyle(Qt::ToolButtonTextOnly); categoryButton->setText(category); categoryButton->setStyleSheet("background: transparent; margin: 0; padding: 0;"); toolbar->addWidget(categoryButton); connect(categoryButton, &QToolButton::clicked, [toolbar]() { for (QWidget* widget : toolbar->findChildren()) { if (QStringLiteral("qt_toolbar_ext_button") == widget->objectName() && widget->isVisible()) { - QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(0.0f, 0.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); - QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(0.0f, 0.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(0.0f, 0.0f), QCursor::pos(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(0.0f, 0.0f), QCursor::pos(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); QApplication::sendEvent(widget, &pressEvent); QApplication::sendEvent(widget, &releaseEvent); } } }); } for (const auto &viewDescriptor : std::as_const(viewDescriptorsInCurrentCategory)) { auto viewAction = new berry::QtShowViewAction(window, viewDescriptor); toolbar->addAction(viewAction); } } } } QSettings settings(GetQSettingsFile(), QSettings::IniFormat); mainWindow->restoreState(settings.value("ToolbarPosition").toByteArray()); auto qStatusBar = new QStatusBar(); //creating a QmitkStatusBar for Output on the QStatusBar and connecting it with the MainStatusBar auto statusBar = new QmitkStatusBar(qStatusBar); //disabling the SizeGrip in the lower right corner statusBar->SetSizeGripEnabled(false); auto progBar = new QmitkProgressBar(); qStatusBar->addPermanentWidget(progBar, 0); progBar->hide(); // progBar->AddStepsToDo(2); // progBar->Progress(1); mainWindow->setStatusBar(qStatusBar); if (showMemoryIndicator) { auto memoryIndicator = new QmitkMemoryUsageIndicatorView(); qStatusBar->addPermanentWidget(memoryIndicator, 0); } } void QmitkExtWorkbenchWindowAdvisor::PreWindowOpen() { berry::IWorkbenchWindowConfigurer::Pointer configurer = GetWindowConfigurer(); // show the shortcut bar and progress indicator, which are hidden by // default //configurer->SetShowPerspectiveBar(true); //configurer->SetShowFastViewBars(true); //configurer->SetShowProgressIndicator(true); // // add the drag and drop support for the editor area // configurer.addEditorAreaTransfer(EditorInputTransfer.getInstance()); // configurer.addEditorAreaTransfer(ResourceTransfer.getInstance()); // configurer.addEditorAreaTransfer(FileTransfer.getInstance()); // configurer.addEditorAreaTransfer(MarkerTransfer.getInstance()); // configurer.configureEditorAreaDropListener(new EditorAreaDropAdapter( // configurer.getWindow())); this->HookTitleUpdateListeners(configurer); menuPerspectiveListener.reset(new PerspectiveListenerForMenu(this)); configurer->GetWindow()->AddPerspectiveListener(menuPerspectiveListener.data()); configurer->AddEditorAreaTransfer(QStringList("text/uri-list")); configurer->ConfigureEditorAreaDropListener(dropTargetListener.data()); } void QmitkExtWorkbenchWindowAdvisor::PostWindowOpen() { berry::WorkbenchWindowAdvisor::PostWindowOpen(); // Force Rendering Window Creation on startup. berry::IWorkbenchWindowConfigurer::Pointer configurer = GetWindowConfigurer(); ctkPluginContext* context = QmitkCommonExtPlugin::getContext(); ctkServiceReference serviceRef = context->getServiceReference(); if (serviceRef) { mitk::IDataStorageService *dsService = context->getService(serviceRef); if (dsService) { mitk::IDataStorageReference::Pointer dsRef = dsService->GetDataStorage(); mitk::DataStorageEditorInput::Pointer dsInput(new mitk::DataStorageEditorInput(dsRef)); mitk::WorkbenchUtil::OpenEditor(configurer->GetWindow()->GetActivePage(),dsInput); } } auto introPart = configurer->GetWindow()->GetWorkbench()->GetIntroManager()->GetIntro(); if (introPart.IsNotNull()) { configurer->GetWindow()->GetWorkbench()->GetIntroManager()->ShowIntro(GetWindowConfigurer()->GetWindow(), false); } } void QmitkExtWorkbenchWindowAdvisor::onIntro() { QmitkExtWorkbenchWindowAdvisorHack::undohack->onIntro(); } void QmitkExtWorkbenchWindowAdvisor::onHelp() { QmitkExtWorkbenchWindowAdvisorHack::undohack->onHelp(); } void QmitkExtWorkbenchWindowAdvisor::onHelpOpenHelpPerspective() { QmitkExtWorkbenchWindowAdvisorHack::undohack->onHelpOpenHelpPerspective(); } void QmitkExtWorkbenchWindowAdvisor::onAbout() { QmitkExtWorkbenchWindowAdvisorHack::undohack->onAbout(); } //-------------------------------------------------------------------------------- // Ugly hack from here on. Feel free to delete when command framework // and undo buttons are done. //-------------------------------------------------------------------------------- QmitkExtWorkbenchWindowAdvisorHack::QmitkExtWorkbenchWindowAdvisorHack() : QObject() { } QmitkExtWorkbenchWindowAdvisorHack::~QmitkExtWorkbenchWindowAdvisorHack() { } void QmitkExtWorkbenchWindowAdvisorHack::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) { MITK_INFO << "Undo " << descriptions.front().second; } } model->Undo(); } else { MITK_ERROR << "No undo model instantiated"; } } void QmitkExtWorkbenchWindowAdvisorHack::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) { MITK_INFO << "Redo " << descriptions.front().second; } } model->Redo(); } else { MITK_ERROR << "No undo model instantiated"; } } // safe calls to the complete chain // berry::PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow()->GetActivePage()->FindView("org.mitk.views.imagenavigator"); // to cover for all possible cases of closed pages etc. static void SafeHandleNavigatorView(QString view_query_name) { berry::IWorkbench* wbench = berry::PlatformUI::GetWorkbench(); if( wbench == nullptr ) return; berry::IWorkbenchWindow::Pointer wbench_window = wbench->GetActiveWorkbenchWindow(); if( wbench_window.IsNull() ) return; berry::IWorkbenchPage::Pointer wbench_page = wbench_window->GetActivePage(); if( wbench_page.IsNull() ) return; auto wbench_view = wbench_page->FindView( view_query_name ); if( wbench_view.IsNotNull() ) { bool isViewVisible = wbench_page->IsPartVisible( wbench_view ); if( isViewVisible ) { wbench_page->HideView( wbench_view ); return; } } wbench_page->ShowView( view_query_name ); } void QmitkExtWorkbenchWindowAdvisorHack::onImageNavigator() { // show/hide ImageNavigatorView SafeHandleNavigatorView("org.mitk.views.imagenavigator"); } void QmitkExtWorkbenchWindowAdvisorHack::onViewNavigator() { // show/hide viewnavigatorView SafeHandleNavigatorView("org.mitk.views.viewnavigator"); } void QmitkExtWorkbenchWindowAdvisorHack::onEditPreferences() { QmitkPreferencesDialog _PreferencesDialog(QApplication::activeWindow()); _PreferencesDialog.exec(); } void QmitkExtWorkbenchWindowAdvisorHack::onQuit() { berry::PlatformUI::GetWorkbench()->Close(); } void QmitkExtWorkbenchWindowAdvisorHack::onResetPerspective() { berry::PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow()->GetActivePage()->ResetPerspective(); } void QmitkExtWorkbenchWindowAdvisorHack::onClosePerspective() { berry::IWorkbenchPage::Pointer page = berry::PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow()->GetActivePage(); page->ClosePerspective(page->GetPerspective(), true, true); } void QmitkExtWorkbenchWindowAdvisorHack::onNewWindow() { berry::PlatformUI::GetWorkbench()->OpenWorkbenchWindow(nullptr); } void QmitkExtWorkbenchWindowAdvisorHack::onIntro() { - bool hasIntro = - berry::PlatformUI::GetWorkbench()->GetIntroManager()->HasIntro(); - if (!hasIntro) - { - QRegularExpression reg("(.*)(\\n)*"); - QRegularExpression reg2("(\\n)*(.*)"); - QFile file(":/org.mitk.gui.qt.ext/index.html"); - file.open(QIODevice::ReadOnly | QIODevice::Text); //text file only for reading - - QString text = QString(file.readAll()); - - file.close(); - - QString title = text; - title.replace(reg, ""); - title.replace(reg2, ""); - - std::cout << title.toStdString() << std::endl; - - QMessageBox::information(nullptr, title, - text, "Close"); - } - else + if (berry::PlatformUI::GetWorkbench()->GetIntroManager()->HasIntro()) { berry::PlatformUI::GetWorkbench()->GetIntroManager()->ShowIntro( berry::PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow(), false); } } void QmitkExtWorkbenchWindowAdvisorHack::onHelp() { ctkPluginContext* context = QmitkCommonExtPlugin::getContext(); if (context == nullptr) { MITK_WARN << "Plugin context not set, unable to open context help"; return; } // Check if the org.blueberry.ui.qt.help plug-in is installed and started QList > plugins = context->getPlugins(); foreach(QSharedPointer p, plugins) { if (p->getSymbolicName() == "org.blueberry.ui.qt.help") { if (p->getState() != ctkPlugin::ACTIVE) { // try to activate the plug-in explicitly try { p->start(ctkPlugin::START_TRANSIENT); } catch (const ctkPluginException& pe) { MITK_ERROR << "Activating org.blueberry.ui.qt.help failed: " << pe.what(); return; } } } } ctkServiceReference eventAdminRef = context->getServiceReference(); ctkEventAdmin* eventAdmin = nullptr; if (eventAdminRef) { eventAdmin = context->getService(eventAdminRef); } if (eventAdmin == nullptr) { MITK_WARN << "ctkEventAdmin service not found. Unable to open context help"; } else { ctkEvent ev("org/blueberry/ui/help/CONTEXTHELP_REQUESTED"); eventAdmin->postEvent(ev); } } void QmitkExtWorkbenchWindowAdvisorHack::onHelpOpenHelpPerspective() { berry::PlatformUI::GetWorkbench()->ShowPerspective("org.blueberry.perspectives.help", berry::PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow()); } void QmitkExtWorkbenchWindowAdvisorHack::onAbout() { auto aboutDialog = new QmitkAboutDialog(QApplication::activeWindow(), {}); aboutDialog->open(); } void QmitkExtWorkbenchWindowAdvisor::HookTitleUpdateListeners(berry::IWorkbenchWindowConfigurer::Pointer configurer) { // hook up the listeners to update the window title titlePartListener.reset(new PartListenerForTitle(this)); titlePerspectiveListener.reset(new PerspectiveListenerForTitle(this)); editorPropertyListener.reset(new berry::PropertyChangeIntAdapter< QmitkExtWorkbenchWindowAdvisor>(this, &QmitkExtWorkbenchWindowAdvisor::PropertyChange)); // configurer.getWindow().addPageListener(new IPageListener() { // public void pageActivated(IWorkbenchPage page) { // updateTitle(false); // } // // public void pageClosed(IWorkbenchPage page) { // updateTitle(false); // } // // public void pageOpened(IWorkbenchPage page) { // // do nothing // } // }); configurer->GetWindow()->AddPerspectiveListener(titlePerspectiveListener.data()); configurer->GetWindow()->GetPartService()->AddPartListener(titlePartListener.data()); } QString QmitkExtWorkbenchWindowAdvisor::ComputeTitle() { berry::IWorkbenchWindowConfigurer::Pointer configurer = GetWindowConfigurer(); berry::IWorkbenchPage::Pointer currentPage = configurer->GetWindow()->GetActivePage(); berry::IEditorPart::Pointer activeEditor; if (currentPage) { activeEditor = lastActiveEditor.Lock(); } QString title; berry::IProduct::Pointer product = berry::Platform::GetProduct(); if (product.IsNotNull()) { title = product->GetName(); } if (title.isEmpty()) { // instead of the product name, we use a custom variable for now title = productName; } if(showMitkVersionInfo) { QString mitkVersionInfo = MITK_REVISION_DESC; if(mitkVersionInfo.isEmpty()) mitkVersionInfo = MITK_VERSION_STRING; title += " " + mitkVersionInfo; } if (showVersionInfo) { // add version informatioin QString versions = QString(" (ITK %1.%2.%3 | VTK %4.%5.%6 | Qt %7)") .arg(ITK_VERSION_MAJOR).arg(ITK_VERSION_MINOR).arg(ITK_VERSION_PATCH) .arg(VTK_MAJOR_VERSION).arg(VTK_MINOR_VERSION).arg(VTK_BUILD_VERSION) .arg(QT_VERSION_STR); title += versions; } if (currentPage) { if (activeEditor) { lastEditorTitle = activeEditor->GetTitleToolTip(); if (!lastEditorTitle.isEmpty()) title = lastEditorTitle + " - " + title; } berry::IPerspectiveDescriptor::Pointer persp = currentPage->GetPerspective(); QString label = ""; if (persp) { label = persp->GetLabel(); } berry::IAdaptable* input = currentPage->GetInput(); if (input && input != wbAdvisor->GetDefaultPageInput()) { label = currentPage->GetLabel(); } if (!label.isEmpty()) { title = label + " - " + title; } } title += " (Not for use in diagnosis or treatment of patients)"; return title; } void QmitkExtWorkbenchWindowAdvisor::RecomputeTitle() { berry::IWorkbenchWindowConfigurer::Pointer configurer = GetWindowConfigurer(); QString oldTitle = configurer->GetTitle(); QString newTitle = ComputeTitle(); if (newTitle != oldTitle) { configurer->SetTitle(newTitle); } } void QmitkExtWorkbenchWindowAdvisor::UpdateTitle(bool editorHidden) { berry::IWorkbenchWindowConfigurer::Pointer configurer = GetWindowConfigurer(); berry::IWorkbenchWindow::Pointer window = configurer->GetWindow(); berry::IEditorPart::Pointer activeEditor; berry::IWorkbenchPage::Pointer currentPage = window->GetActivePage(); berry::IPerspectiveDescriptor::Pointer persp; berry::IAdaptable* input = nullptr; if (currentPage) { activeEditor = currentPage->GetActiveEditor(); persp = currentPage->GetPerspective(); input = currentPage->GetInput(); } if (editorHidden) { activeEditor = nullptr; } // Nothing to do if the editor hasn't changed if (activeEditor == lastActiveEditor.Lock() && currentPage == lastActivePage.Lock() && persp == lastPerspective.Lock() && input == lastInput) { return; } auto lockedLastActiveEditor = lastActiveEditor.Lock(); if (lockedLastActiveEditor.IsNotNull()) { lockedLastActiveEditor->RemovePropertyListener(editorPropertyListener.data()); } lastActiveEditor = activeEditor; lastActivePage = currentPage; lastPerspective = persp; lastInput = input; if (activeEditor) { activeEditor->AddPropertyListener(editorPropertyListener.data()); } RecomputeTitle(); } void QmitkExtWorkbenchWindowAdvisor::PropertyChange(const berry::Object::Pointer& /*source*/, int propId) { if (propId == berry::IWorkbenchPartConstants::PROP_TITLE) { auto lockedLastActiveEditor = lastActiveEditor.Lock(); if (lockedLastActiveEditor.IsNotNull()) { QString newTitle = lockedLastActiveEditor->GetPartName(); if (lastEditorTitle != newTitle) { RecomputeTitle(); } } } } void QmitkExtWorkbenchWindowAdvisor::SetPerspectiveExcludeList(const QList& v) { this->perspectiveExcludeList = v; } QList QmitkExtWorkbenchWindowAdvisor::GetPerspectiveExcludeList() { return this->perspectiveExcludeList; } void QmitkExtWorkbenchWindowAdvisor::SetViewExcludeList(const QList& v) { this->viewExcludeList = v; } QList QmitkExtWorkbenchWindowAdvisor::GetViewExcludeList() { return this->viewExcludeList; } void QmitkExtWorkbenchWindowAdvisor::PostWindowClose() { berry::IWorkbenchWindow::Pointer window = this->GetWindowConfigurer()->GetWindow(); QMainWindow* mainWindow = static_cast (window->GetShell()->GetControl()); auto fileName = this->GetQSettingsFile(); if (!fileName.isEmpty()) { QSettings settings(fileName, QSettings::IniFormat); settings.setValue("ToolbarPosition", mainWindow->saveState()); } } QString QmitkExtWorkbenchWindowAdvisor::GetQSettingsFile() const { QFileInfo settingsInfo = QmitkCommonExtPlugin::getContext()->getDataFile(QT_SETTINGS_FILENAME); return settingsInfo.canonicalFilePath(); } diff --git a/Plugins/org.mitk.gui.qt.imagecropper/src/internal/QmitkImageCropperView.cpp b/Plugins/org.mitk.gui.qt.imagecropper/src/internal/QmitkImageCropperView.cpp index c8ae768dbd..df501800f1 100644 --- a/Plugins/org.mitk.gui.qt.imagecropper/src/internal/QmitkImageCropperView.cpp +++ b/Plugins/org.mitk.gui.qt.imagecropper/src/internal/QmitkImageCropperView.cpp @@ -1,510 +1,510 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "QmitkImageCropperView.h" #include #include #include #include #include #include #include #include #include #include #include #include #include const std::string QmitkImageCropperView::VIEW_ID = "org.mitk.views.qmitkimagecropper"; QmitkImageCropperView::QmitkImageCropperView(QObject *) : m_ParentWidget(nullptr) , m_BoundingShapeInteractor(nullptr) , m_CropOutsideValue(0) { CreateBoundingShapeInteractor(false); } QmitkImageCropperView::~QmitkImageCropperView() { //disable interactor if (m_BoundingShapeInteractor != nullptr) { m_BoundingShapeInteractor->SetDataNode(nullptr); m_BoundingShapeInteractor->EnableInteraction(false); } } void QmitkImageCropperView::CreateQtPartControl(QWidget *parent) { // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi(parent); m_Controls.imageSelectionWidget->SetDataStorage(GetDataStorage()); m_Controls.imageSelectionWidget->SetNodePredicate( mitk::NodePredicateAnd::New(mitk::TNodePredicateDataType::New(), mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object")))); m_Controls.imageSelectionWidget->SetSelectionIsOptional(true); m_Controls.imageSelectionWidget->SetAutoSelectNewNodes(true); m_Controls.imageSelectionWidget->SetEmptyInfo(QString("Please select an image node")); m_Controls.imageSelectionWidget->SetPopUpTitel(QString("Select image node")); connect(m_Controls.imageSelectionWidget, &QmitkSingleNodeSelectionWidget::CurrentSelectionChanged, this, &QmitkImageCropperView::OnImageSelectionChanged); m_Controls.boundingBoxSelectionWidget->SetDataStorage(GetDataStorage()); m_Controls.boundingBoxSelectionWidget->SetNodePredicate(mitk::NodePredicateAnd::New( mitk::TNodePredicateDataType::New(), mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object")))); m_Controls.boundingBoxSelectionWidget->SetSelectionIsOptional(true); m_Controls.boundingBoxSelectionWidget->SetAutoSelectNewNodes(true); m_Controls.boundingBoxSelectionWidget->SetEmptyInfo(QString("Please select a bounding box")); m_Controls.boundingBoxSelectionWidget->SetPopUpTitel(QString("Select bounding box node")); connect(m_Controls.boundingBoxSelectionWidget, &QmitkSingleNodeSelectionWidget::CurrentSelectionChanged, this, &QmitkImageCropperView::OnBoundingBoxSelectionChanged); connect(m_Controls.buttonCreateNewBoundingBox, SIGNAL(clicked()), this, SLOT(OnCreateNewBoundingBox())); connect(m_Controls.buttonCropping, SIGNAL(clicked()), this, SLOT(OnCropping())); connect(m_Controls.buttonMasking, SIGNAL(clicked()), this, SLOT(OnMasking())); auto lambda = [this]() { m_Controls.groupImageSettings->setVisible(!m_Controls.groupImageSettings->isVisible()); }; connect(m_Controls.buttonAdvancedSettings, &ctkExpandButton::clicked, this, lambda); connect(m_Controls.spinBoxOutsidePixelValue, SIGNAL(valueChanged(int)), this, SLOT(OnSliderValueChanged(int))); SetDefaultGUI(); m_ParentWidget = parent; this->OnImageSelectionChanged(m_Controls.imageSelectionWidget->GetSelectedNodes()); this->OnBoundingBoxSelectionChanged(m_Controls.boundingBoxSelectionWidget->GetSelectedNodes()); } void QmitkImageCropperView::OnImageSelectionChanged(QList) { bool rotationEnabled = false; m_Controls.labelWarningRotation->setVisible(false); auto imageNode = m_Controls.imageSelectionWidget->GetSelectedNode(); if (imageNode.IsNull()) { SetDefaultGUI(); return; } auto image = dynamic_cast(imageNode->GetData()); if (nullptr != image) { if (image->GetDimension() < 3) { QMessageBox::warning(nullptr, tr("Invalid image selected"), tr("ImageCropper only works with 3 or more dimensions."), - QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); + QMessageBox::Ok | QMessageBox::NoButton, QMessageBox::NoButton); SetDefaultGUI(); return; } m_ParentWidget->setEnabled(true); m_Controls.buttonCreateNewBoundingBox->setEnabled(true); vtkSmartPointer imageMat = image->GetGeometry()->GetVtkMatrix(); // check whether the image geometry is rotated; if so, no pixel aligned cropping or masking can be performed if ((imageMat->GetElement(1, 0) == 0.0) && (imageMat->GetElement(0, 1) == 0.0) && (imageMat->GetElement(1, 2) == 0.0) && (imageMat->GetElement(2, 1) == 0.0) && (imageMat->GetElement(2, 0) == 0.0) && (imageMat->GetElement(0, 2) == 0.0)) { rotationEnabled = false; m_Controls.labelWarningRotation->setVisible(false); } else { rotationEnabled = true; m_Controls.labelWarningRotation->setStyleSheet(" QLabel { color: rgb(255, 0, 0) }"); m_Controls.labelWarningRotation->setVisible(true); } this->CreateBoundingShapeInteractor(rotationEnabled); if (itk::IOPixelEnum::SCALAR == image->GetPixelType().GetPixelType()) { // Might be changed with the upcoming new image statistics plugin //(recomputation might be very expensive for large images ;) ) auto statistics = image->GetStatistics(); auto minPixelValue = statistics->GetScalarValueMin(); auto maxPixelValue = statistics->GetScalarValueMax(); if (minPixelValue < std::numeric_limits::min()) { minPixelValue = std::numeric_limits::min(); } if (maxPixelValue > std::numeric_limits::max()) { maxPixelValue = std::numeric_limits::max(); } m_Controls.spinBoxOutsidePixelValue->setEnabled(true); m_Controls.spinBoxOutsidePixelValue->setMaximum(static_cast(maxPixelValue)); m_Controls.spinBoxOutsidePixelValue->setMinimum(static_cast(minPixelValue)); m_Controls.spinBoxOutsidePixelValue->setValue(static_cast(minPixelValue)); } else { m_Controls.spinBoxOutsidePixelValue->setEnabled(false); } unsigned int dim = image->GetDimension(); if (dim < 2 || dim > 4) { m_ParentWidget->setEnabled(false); } if (m_Controls.boundingBoxSelectionWidget->GetSelectedNode().IsNotNull()) { m_Controls.buttonCropping->setEnabled(true); m_Controls.buttonMasking->setEnabled(true); m_Controls.buttonAdvancedSettings->setEnabled(true); m_Controls.groupImageSettings->setEnabled(true); } } } void QmitkImageCropperView::OnBoundingBoxSelectionChanged(QList) { auto boundingBoxNode = m_Controls.boundingBoxSelectionWidget->GetSelectedNode(); if (boundingBoxNode.IsNull()) { SetDefaultGUI(); m_BoundingShapeInteractor->EnableInteraction(false); m_BoundingShapeInteractor->SetDataNode(nullptr); if (m_Controls.imageSelectionWidget->GetSelectedNode().IsNotNull()) { m_Controls.buttonCreateNewBoundingBox->setEnabled(true); } return; } auto boundingBox = dynamic_cast(boundingBoxNode->GetData()); if (nullptr != boundingBox) { // node newly selected boundingBoxNode->SetVisibility(true); m_BoundingShapeInteractor->EnableInteraction(true); m_BoundingShapeInteractor->SetDataNode(boundingBoxNode); mitk::RenderingManager::GetInstance()->InitializeViews(); if (m_Controls.imageSelectionWidget->GetSelectedNode().IsNotNull()) { m_Controls.buttonCropping->setEnabled(true); m_Controls.buttonMasking->setEnabled(true); m_Controls.buttonAdvancedSettings->setEnabled(true); m_Controls.groupImageSettings->setEnabled(true); } } } void QmitkImageCropperView::OnCreateNewBoundingBox() { auto imageNode = m_Controls.imageSelectionWidget->GetSelectedNode(); if (imageNode.IsNull()) { return; } if (nullptr == imageNode->GetData()) { return; } QString name = QString::fromStdString(imageNode->GetName() + " Bounding Box"); auto boundingShape = this->GetDataStorage()->GetNode(mitk::NodePredicateFunction::New([&name](const mitk::DataNode *node) { return 0 == node->GetName().compare(name.toStdString()); })); if (nullptr != boundingShape) { name = this->AdaptBoundingObjectName(name); } // get current timestep to support 3d+t images auto renderWindowPart = this->GetRenderWindowPart(mitk::WorkbenchUtil::IRenderWindowPartStrategy::OPEN); const mitk::TimePointType timePoint = renderWindowPart->GetSelectedTimePoint(); const auto imageGeometry = imageNode->GetData()->GetTimeGeometry()->GetGeometryForTimePoint(timePoint); auto boundingBox = mitk::GeometryData::New(); boundingBox->SetGeometry(static_cast(this->InitializeWithImageGeometry(imageGeometry))); auto boundingBoxNode = mitk::DataNode::New(); boundingBoxNode->SetData(boundingBox); boundingBoxNode->SetProperty("name", mitk::StringProperty::New(name.toStdString())); boundingBoxNode->SetProperty("layer", mitk::IntProperty::New(99)); boundingBoxNode->AddProperty("Bounding Shape.Handle Size Factor", mitk::DoubleProperty::New(0.02)); boundingBoxNode->SetBoolProperty("pickable", true); if (!this->GetDataStorage()->Exists(boundingBoxNode)) { GetDataStorage()->Add(boundingBoxNode, imageNode); } m_Controls.boundingBoxSelectionWidget->SetCurrentSelectedNode(boundingBoxNode); } void QmitkImageCropperView::OnCropping() { this->ProcessImage(false); } void QmitkImageCropperView::OnMasking() { this->ProcessImage(true); } void QmitkImageCropperView::OnSliderValueChanged(int slidervalue) { m_CropOutsideValue = slidervalue; } void QmitkImageCropperView::CreateBoundingShapeInteractor(bool rotationEnabled) { if (m_BoundingShapeInteractor.IsNull()) { m_BoundingShapeInteractor = mitk::BoundingShapeInteractor::New(); m_BoundingShapeInteractor->LoadStateMachine("BoundingShapeInteraction.xml", us::ModuleRegistry::GetModule("MitkBoundingShape")); m_BoundingShapeInteractor->SetEventConfig("BoundingShapeMouseConfig.xml", us::ModuleRegistry::GetModule("MitkBoundingShape")); } m_BoundingShapeInteractor->SetRotationEnabled(rotationEnabled); } mitk::Geometry3D::Pointer QmitkImageCropperView::InitializeWithImageGeometry(const mitk::BaseGeometry* geometry) const { // convert a BaseGeometry into a Geometry3D (otherwise IO is not working properly) if (geometry == nullptr) mitkThrow() << "Geometry is not valid."; auto boundingGeometry = mitk::Geometry3D::New(); boundingGeometry->SetBounds(geometry->GetBounds()); boundingGeometry->SetImageGeometry(geometry->GetImageGeometry()); boundingGeometry->SetOrigin(geometry->GetOrigin()); boundingGeometry->SetSpacing(geometry->GetSpacing()); boundingGeometry->SetIndexToWorldTransform(geometry->GetIndexToWorldTransform()->Clone()); boundingGeometry->Modified(); return boundingGeometry; } void QmitkImageCropperView::ProcessImage(bool mask) { auto renderWindowPart = this->GetRenderWindowPart(mitk::WorkbenchUtil::IRenderWindowPartStrategy::OPEN); const auto timePoint = renderWindowPart->GetSelectedTimePoint(); auto imageNode = m_Controls.imageSelectionWidget->GetSelectedNode(); if (imageNode.IsNull()) { QMessageBox::information(nullptr, "Warning", "Please load and select an image before starting image processing."); return; } auto boundingBoxNode = m_Controls.boundingBoxSelectionWidget->GetSelectedNode(); if (boundingBoxNode.IsNull()) { QMessageBox::information(nullptr, "Warning", "Please load and select a cropping object before starting image processing."); return; } if (!imageNode->GetData()->GetTimeGeometry()->IsValidTimePoint(timePoint)) { QMessageBox::information(nullptr, "Warning", "Please select a time point that is within the time bounds of the selected image."); return; } const auto timeStep = imageNode->GetData()->GetTimeGeometry()->TimePointToTimeStep(timePoint); auto image = dynamic_cast(imageNode->GetData()); auto boundingBox = dynamic_cast(boundingBoxNode->GetData()); if (nullptr != image && nullptr != boundingBox) { // Check if initial node name is already in box name std::string imagePrefix = ""; if (boundingBoxNode->GetName().find(imageNode->GetName()) != 0) { imagePrefix = imageNode->GetName() + "_"; } QString imageName; if (mask) { imageName = QString::fromStdString(imagePrefix + boundingBoxNode->GetName() + "_masked"); } else { imageName = QString::fromStdString(imagePrefix + boundingBoxNode->GetName() + "_cropped"); } if (m_Controls.checkBoxCropTimeStepOnly->isChecked()) { imageName = imageName + "_T" + QString::number(timeStep); } // image and bounding shape ok, set as input auto croppedImageNode = mitk::DataNode::New(); auto cutter = mitk::BoundingShapeCropper::New(); cutter->SetGeometry(boundingBox); // adjustable in advanced settings cutter->SetUseWholeInputRegion(mask); //either mask (mask=true) or crop (mask=false) cutter->SetOutsideValue(m_CropOutsideValue); cutter->SetUseCropTimeStepOnly(m_Controls.checkBoxCropTimeStepOnly->isChecked()); cutter->SetCurrentTimeStep(timeStep); // TODO: Add support for MultiLayer (right now only Mulitlabel support) auto labelsetImageInput = dynamic_cast(image); if (nullptr != labelsetImageInput) { cutter->SetInput(labelsetImageInput); // do the actual cutting try { cutter->Update(); } catch (const itk::ExceptionObject& e) { std::string message = std::string("The Cropping filter could not process because of: \n ") + e.GetDescription(); QMessageBox::warning(nullptr, tr("Cropping not possible!"), tr(message.c_str()), - QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); + QMessageBox::Ok | QMessageBox::NoButton, QMessageBox::NoButton); return; } auto labelSetImage = mitk::LabelSetImage::New(); labelSetImage->InitializeByLabeledImage(cutter->GetOutput()); for (unsigned int i = 0; i < labelsetImageInput->GetNumberOfLayers(); i++) { labelSetImage->AddLabelSetToLayer(i, labelsetImageInput->GetLabelSet(i)); } croppedImageNode->SetData(labelSetImage); croppedImageNode->SetProperty("name", mitk::StringProperty::New(imageName.toStdString())); //add cropping result to the current data storage as child node to the image node if (!m_Controls.checkOverwriteImage->isChecked()) { if (!this->GetDataStorage()->Exists(croppedImageNode)) { this->GetDataStorage()->Add(croppedImageNode, imageNode); } } else // original image will be overwritten by the result image and the bounding box of the result is adjusted { imageNode->SetData(labelSetImage); imageNode->Modified(); // Adjust coordinate system by doing a reinit on auto tempDataStorage = mitk::DataStorage::SetOfObjects::New(); tempDataStorage->InsertElement(0, imageNode); // initialize the views to the bounding geometry auto bounds = this->GetDataStorage()->ComputeBoundingGeometry3D(tempDataStorage); mitk::RenderingManager::GetInstance()->InitializeViews(bounds); } } else { cutter->SetInput(image); // do the actual cutting try { cutter->Update(); } catch (const itk::ExceptionObject& e) { std::string message = std::string("The Cropping filter could not process because of: \n ") + e.GetDescription(); QMessageBox::warning(nullptr, tr("Cropping not possible!"), tr(message.c_str()), - QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); + QMessageBox::Ok | QMessageBox::NoButton, QMessageBox::NoButton); return; } //add cropping result to the current data storage as child node to the image node if (!m_Controls.checkOverwriteImage->isChecked()) { croppedImageNode->SetData(cutter->GetOutput()); croppedImageNode->SetProperty("name", mitk::StringProperty::New(imageName.toStdString())); croppedImageNode->SetProperty("color", mitk::ColorProperty::New(1.0, 1.0, 1.0)); mitk::LevelWindow levelWindow; imageNode->GetLevelWindow(levelWindow); croppedImageNode->SetLevelWindow(levelWindow); if (!this->GetDataStorage()->Exists(croppedImageNode)) { this->GetDataStorage()->Add(croppedImageNode, imageNode); imageNode->SetVisibility(mask); // Give the user a visual clue that something happened when image was cropped } } else // original image will be overwritten by the result image and the bounding box of the result is adjusted { mitk::LevelWindow levelWindow; imageNode->GetLevelWindow(levelWindow); imageNode->SetData(cutter->GetOutput()); imageNode->SetLevelWindow(levelWindow); // Adjust coordinate system by doing a reinit on auto tempDataStorage = mitk::DataStorage::SetOfObjects::New(); tempDataStorage->InsertElement(0, imageNode); // initialize the views to the bounding geometry auto bounds = this->GetDataStorage()->ComputeBoundingGeometry3D(tempDataStorage); mitk::RenderingManager::GetInstance()->InitializeViews(bounds); } } } else { QMessageBox::information(nullptr, "Warning", "Please load and select an image before starting image processing."); } } void QmitkImageCropperView::SetDefaultGUI() { m_Controls.buttonCreateNewBoundingBox->setEnabled(false); m_Controls.buttonCropping->setEnabled(false); m_Controls.buttonMasking->setEnabled(false); m_Controls.buttonAdvancedSettings->setEnabled(false); m_Controls.groupImageSettings->setEnabled(false); m_Controls.groupImageSettings->setVisible(false); m_Controls.checkOverwriteImage->setChecked(false); m_Controls.checkBoxCropTimeStepOnly->setChecked(false); } QString QmitkImageCropperView::AdaptBoundingObjectName(const QString& name) const { unsigned int counter = 2; QString newName = QString("%1 %2").arg(name).arg(counter); while (nullptr != this->GetDataStorage()->GetNode(mitk::NodePredicateFunction::New([&newName](const mitk::DataNode *node) { return 0 == node->GetName().compare(newName.toStdString()); }))) { newName = QString("%1 %2").arg(name).arg(++counter); } return newName; } diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/QmitkNewSegmentationDialog.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/QmitkNewSegmentationDialog.cpp index fce39a51d1..b93bb00172 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/QmitkNewSegmentationDialog.cpp +++ b/Plugins/org.mitk.gui.qt.segmentation/src/QmitkNewSegmentationDialog.cpp @@ -1,406 +1,406 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "QmitkNewSegmentationDialog.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace { // Get standard label name and color suggestions from embedded XML preset file for anatomical structures. QmitkNewSegmentationDialog::SuggestionsType GetStandardSuggestions() { vtkNew presets; presets->LoadPreset(); auto colorPresets = presets->GetColorPresets(); QmitkNewSegmentationDialog::SuggestionsType standardSuggestions; standardSuggestions.reserve(colorPresets.size()); for (const auto& preset : colorPresets) { auto name = QString::fromStdString(preset.first); auto color = QColor::fromRgbF(preset.second.GetRed(), preset.second.GetGreen(), preset.second.GetBlue()); standardSuggestions.emplace_back(name, color); } std::sort(begin(standardSuggestions), end(standardSuggestions), [](const auto& lhs, const auto& rhs) { return lhs.first < rhs.first; }); return standardSuggestions; } // Parse label name and color suggestions from a JSON file. An array of objects is expected, each consisting // of a "name" string and an optional "color" string. If present, the "color" string must follow the conventions // of QColor::setNamedColor(), i.e., #rrggbb or any SVG color keyword name like CornflowerBlue. Everything else // in the JSON file is simply ignored. In case of any error, an empty map is returned. QmitkNewSegmentationDialog::SuggestionsType ParseSuggestions(const std::string& filename) { std::ifstream file(filename); if (!file.is_open()) { MITK_ERROR << "Could not open \"" << filename << "\"!"; return {}; } auto json = nlohmann::json::parse(file, nullptr, false); if (json.is_discarded() || !json.is_array()) { MITK_ERROR << "Could not parse \"" << filename << "\" as JSON array!"; return {}; } QmitkNewSegmentationDialog::SuggestionsType parsedSuggestions; for (const auto& obj : json) { if (!obj.is_object() || !obj.contains("name")) continue; auto name = QString::fromStdString(obj["name"]); QColor color; if (obj.contains("color")) - color.setNamedColor(QString::fromStdString(obj["color"])); + color = QColor::fromString(QString::fromStdString(obj["color"])); auto it = std::find_if(begin(parsedSuggestions), end(parsedSuggestions), [&name](const auto& suggestion) { return name == suggestion.first; }); // Ignore duplicates... if (it != parsedSuggestions.end()) { // unless we can complete the original suggestion with a valid color. if (!it->second.isValid() && color.isValid()) { it->second = color; } else { MITK_WARN << "Ignoring duplicate of suggestion \"" << name.toStdString() << "\"!"; } continue; } parsedSuggestions.emplace_back(name, color); } if (parsedSuggestions.empty()) MITK_WARN << "Could not parse any suggestions from \"" << filename << "\"!"; return parsedSuggestions; } struct Preferences { std::string labelSuggestions; bool replaceStandardSuggestions; bool suggestOnce; std::vector geometry; }; // Get all relevant preferences and consider command-line arguments overrides. Preferences GetPreferences() { auto* nodePrefs = mitk::CoreServices::GetPreferencesService()->GetSystemPreferences()->Node("/org.mitk.views.segmentation"); Preferences prefs; prefs.labelSuggestions = mitk::BaseApplication::instance().config().getString(mitk::BaseApplication::ARG_SEGMENTATION_LABEL_SUGGESTIONS.toStdString(), ""); if (prefs.labelSuggestions.empty()) prefs.labelSuggestions = nodePrefs->Get("label suggestions", ""); prefs.replaceStandardSuggestions = nodePrefs->GetBool("replace standard suggestions", true); prefs.suggestOnce = nodePrefs->GetBool("suggest once", true); prefs.geometry = nodePrefs->GetByteArray("QmitkNewSegmentationDialog geometry", nullptr, 0); return prefs; } void SaveGeometry(const QByteArray& geometry) { auto* nodePrefs = mitk::CoreServices::GetPreferencesService()->GetSystemPreferences()->Node("/org.mitk.views.segmentation"); nodePrefs->PutByteArray("QmitkNewSegmentationDialog geometry", reinterpret_cast(geometry.data()), geometry.size()); } // Get names of all labels in all layers of a LabelSetImage. QStringList GetExistingLabelNames(mitk::LabelSetImage* labelSetImage) { QStringList existingLabelNames; existingLabelNames.reserve(labelSetImage->GetTotalNumberOfLabels()); const auto numLayers = labelSetImage->GetNumberOfLayers(); for (std::remove_const_t layerIndex = 0; layerIndex < numLayers; ++layerIndex) { const auto* labelSet = labelSetImage->GetLabelSet(layerIndex); for (auto labelIter = labelSet->IteratorConstBegin(); labelIter != labelSet->IteratorConstEnd(); ++labelIter) { auto name = QString::fromStdString(labelIter->second->GetName()); if (!name.isEmpty()) // Potential duplicates do not matter for our purpose existingLabelNames.push_back(name); } } return existingLabelNames; } // Remove blacklisted suggestions. QmitkNewSegmentationDialog::SuggestionsType FilterSuggestions(const QmitkNewSegmentationDialog::SuggestionsType& suggestions, const QStringList& blacklist) { QmitkNewSegmentationDialog::SuggestionsType filteredSuggestions; std::remove_copy_if(begin(suggestions), end(suggestions), std::inserter(filteredSuggestions, end(filteredSuggestions)), [&blacklist](const auto& suggestion) { return blacklist.contains(suggestion.first); }); return filteredSuggestions; } } QmitkNewSegmentationDialog::QmitkNewSegmentationDialog(QWidget *parent, mitk::LabelSetImage* labelSetImage, Mode mode) : QDialog(parent), m_Ui(new Ui::QmitkNewSegmentationDialog), m_SuggestOnce(true), m_Color(Qt::red) { m_Ui->setupUi(this); if (RenameLabel == mode) { this->setWindowTitle("Rename Label"); m_Ui->label->setText("New name and color of the label"); m_Ui->buttonBox->button(QDialogButtonBox::Ok)->setText("Rename label"); } else { m_Ui->buttonBox->button(QDialogButtonBox::Ok)->setText("Create label"); } m_Ui->nameLineEdit->setFocus(); connect(this, &QDialog::finished, this, &QmitkNewSegmentationDialog::OnFinished); connect(m_Ui->colorButton, &QToolButton::clicked, this, &QmitkNewSegmentationDialog::OnColorButtonClicked); connect(m_Ui->nameLineEdit, &QLineEdit::textChanged, this, &QmitkNewSegmentationDialog::OnTextChanged); connect(m_Ui->nameList, &QListWidget::itemSelectionChanged, this, &QmitkNewSegmentationDialog::OnSuggestionSelected); connect(m_Ui->nameList, &QListWidget::itemDoubleClicked, this, &QmitkNewSegmentationDialog::OnAccept); connect(m_Ui->buttonBox, &QDialogButtonBox::accepted, this, &QmitkNewSegmentationDialog::OnAccept); this->UpdateColorButtonBackground(); auto prefs = GetPreferences(); if (!prefs.labelSuggestions.empty()) { auto suggestions = ParseSuggestions(prefs.labelSuggestions); this->SetSuggestions(suggestions, prefs.replaceStandardSuggestions && !suggestions.empty()); } else { this->SetSuggestions(GetStandardSuggestions(), true); } if (nullptr != labelSetImage && prefs.suggestOnce) { auto existingLabelNames = GetExistingLabelNames(labelSetImage); m_Suggestions = FilterSuggestions(m_Suggestions, existingLabelNames); this->UpdateNameList(); } if (!(prefs.geometry.empty())) this->restoreGeometry(QByteArray(reinterpret_cast(prefs.geometry.data()), prefs.geometry.size())); } QmitkNewSegmentationDialog::~QmitkNewSegmentationDialog() { } void QmitkNewSegmentationDialog::OnFinished(int) { SaveGeometry(this->saveGeometry()); } void QmitkNewSegmentationDialog::UpdateColorButtonBackground() { m_Ui->colorButton->setStyleSheet("background-color:" + m_Color.name()); } QString QmitkNewSegmentationDialog::GetName() const { return m_Name; } mitk::Color QmitkNewSegmentationDialog::GetColor() const { mitk::Color color; if (m_Color.isValid()) { color.SetRed(m_Color.redF()); color.SetGreen(m_Color.greenF()); color.SetBlue(m_Color.blueF()); } else { color.Set(1.0f, 0.0f, 0.0f); } return color; } void QmitkNewSegmentationDialog::SetName(const QString& name) { m_Ui->nameLineEdit->setText(name); } void QmitkNewSegmentationDialog::SetColor(const mitk::Color& color) { m_Color.setRgbF(color.GetRed(), color.GetGreen(), color.GetBlue()); this->UpdateColorButtonBackground(); } void QmitkNewSegmentationDialog::SetSuggestions(const SuggestionsType& suggestions, bool replaceStandardSuggestions) { m_Suggestions = suggestions; if (!replaceStandardSuggestions) { auto standardSuggestions = GetStandardSuggestions(); // Append all standard suggestions with unique names to the list of custom suggestions std::remove_copy_if(begin(standardSuggestions), end(standardSuggestions), std::inserter(m_Suggestions, end(m_Suggestions)), [this](const auto& suggestion) { return m_Suggestions.end() != std::find_if(begin(m_Suggestions), end(m_Suggestions), [&suggestion](const auto& otherSuggestion) { return suggestion.first == otherSuggestion.first; }); }); } this->UpdateNameList(); } void QmitkNewSegmentationDialog::UpdateNameList() { QStringList names; for (const auto& suggestion : m_Suggestions) names << suggestion.first; m_Ui->nameList->clear(); m_Ui->nameList->addItems(names); } void QmitkNewSegmentationDialog::OnAccept() { m_Name = m_Ui->nameLineEdit->text(); this->accept(); } void QmitkNewSegmentationDialog::OnTextChanged(const QString& text) { auto finding = m_Ui->nameList->findItems(text, Qt::MatchFlag::MatchExactly); if (!finding.isEmpty()) m_Ui->nameList->setCurrentItem(finding.first()); } void QmitkNewSegmentationDialog::OnColorButtonClicked() { auto color = QColorDialog::getColor(m_Color); if (color.isValid()) { m_Color = color; this->UpdateColorButtonBackground(); } } void QmitkNewSegmentationDialog::OnSuggestionSelected() { const auto* currentItem = m_Ui->nameList->currentItem(); if (currentItem == nullptr) return; auto row = m_Ui->nameList->selectionModel()->selectedIndexes().first().row(); m_Ui->nameLineEdit->setText(m_Suggestions[row].first); auto color = m_Suggestions[row].second; if (color.isValid()) { m_Color = color; this->UpdateColorButtonBackground(); } } bool QmitkNewSegmentationDialog::DoRenameLabel(mitk::Label* label, mitk::LabelSetImage* segmentation, QWidget* parent, Mode mode) { if (nullptr == label) mitkThrow() << "Invalid call of QmitkNewSegmentationDialog::RenameLabel. Passed label is null."; const auto labelValue = label->GetValue(); mitk::LabelSetImage::GroupIndexType groupIndex; if (nullptr != segmentation && !segmentation->IsLabelInGroup(labelValue, groupIndex)) mitkThrow() << "Invalid call of QmitkNewSegmentationDialog::RenameLabel. Passed label value does not exist in segmentation."; QmitkNewSegmentationDialog dialog(parent, segmentation, mode); dialog.SetColor(label->GetColor()); dialog.SetName(QString::fromStdString(label->GetName())); if (dialog.exec() == QDialog::Rejected) return false; auto name = dialog.GetName(); if (name.isEmpty()) name = "Unnamed"; if (nullptr != segmentation) { auto group = segmentation->GetLabelSet(groupIndex); group->RenameLabel(labelValue, name.toStdString(), dialog.GetColor()); group->UpdateLookupTable(labelValue); } else { label->SetName(name.toStdString()); label->SetColor(dialog.GetColor()); } return true; } diff --git a/Utilities/qtsingleapplication/qtlocalpeer.cpp b/Utilities/qtsingleapplication/qtlocalpeer.cpp index d52366e56d..99c89a0e99 100644 --- a/Utilities/qtsingleapplication/qtlocalpeer.cpp +++ b/Utilities/qtsingleapplication/qtlocalpeer.cpp @@ -1,203 +1,203 @@ /**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtlocalpeer.h" #include #include #include #include #if defined(Q_OS_WIN) #include #include typedef BOOL(WINAPI *PProcessIdToSessionId)(DWORD, DWORD *); static PProcessIdToSessionId pProcessIdToSessionId = 0; #endif #if defined(Q_OS_UNIX) #include #include #include #endif namespace QtLP_Private { #include "qtlockedfile.cpp" #if defined(Q_OS_WIN) #include "qtlockedfile_win.cpp" #else #include "qtlockedfile_unix.cpp" #endif } const char *QtLocalPeer::ack = "ack"; QtLocalPeer::QtLocalPeer(QObject *parent, const QString &appId) : QObject(parent), id(appId) { QString prefix = id; if (id.isEmpty()) { id = QCoreApplication::applicationFilePath(); #if defined(Q_OS_WIN) id = id.toLower(); #endif prefix = id.section(QLatin1Char('/'), -1); } prefix.remove(QRegularExpression("[^a-zA-Z]")); prefix.truncate(6); QByteArray idc = id.toUtf8(); - quint16 idNum = qChecksum(idc.constData(), idc.size()); + quint16 idNum = qChecksum(idc); socketName = QLatin1String("qtsingleapp-") + prefix + QLatin1Char('-') + QString::number(idNum, 16); #if defined(Q_OS_WIN) if (!pProcessIdToSessionId) { QLibrary lib("kernel32"); pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId"); } if (pProcessIdToSessionId) { DWORD sessionId = 0; pProcessIdToSessionId(GetCurrentProcessId(), &sessionId); socketName += QLatin1Char('-') + QString::number(sessionId, 16); } #else socketName += QLatin1Char('-') + QString::number(::getuid(), 16); #endif server = new QLocalServer(this); QString lockName = QDir(QDir::tempPath()).absolutePath() + QLatin1Char('/') + socketName + QLatin1String("-lockfile"); lockFile.setFileName(lockName); lockFile.open(QIODevice::ReadWrite); } bool QtLocalPeer::isClient() { if (lockFile.isLocked()) return false; if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false)) return true; bool res = server->listen(socketName); #if defined(Q_OS_UNIX) // ### Workaround if (!res && server->serverError() == QAbstractSocket::AddressInUseError) { QFile::remove(QDir::cleanPath(QDir::tempPath()) + QLatin1Char('/') + socketName); res = server->listen(socketName); } #endif if (!res) qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString())); QObject::connect(server, SIGNAL(newConnection()), SLOT(receiveConnection())); return false; } bool QtLocalPeer::sendMessage(const QByteArray &message, int timeout) { if (!isClient()) return false; QLocalSocket socket; bool connOk = false; for (int i = 0; i < 2; i++) { // Try twice, in case the other instance is just starting up socket.connectToServer(socketName); connOk = socket.waitForConnected(timeout / 2); if (connOk || i) break; int ms = 250; #if defined(Q_OS_WIN) Sleep(DWORD(ms)); #else struct timespec ts = {ms / 1000, (ms % 1000) * 1000 * 1000}; nanosleep(&ts, nullptr); #endif } if (!connOk) return false; QDataStream ds(&socket); ds.writeBytes(message.constData(), message.size()); bool res = socket.waitForBytesWritten(timeout); if (res) { res &= socket.waitForReadyRead(timeout); // wait for ack if (res) res &= (socket.read(qstrlen(ack)) == ack); } return res; } void QtLocalPeer::receiveConnection() { QLocalSocket *socket = server->nextPendingConnection(); if (!socket) return; while (socket->bytesAvailable() < (int)sizeof(quint32)) socket->waitForReadyRead(); QDataStream ds(socket); QByteArray uMsg; quint32 remaining; ds >> remaining; uMsg.resize(remaining); int got = 0; char *uMsgBuf = uMsg.data(); do { got = ds.readRawData(uMsgBuf, remaining); remaining -= got; uMsgBuf += got; } while (remaining && got >= 0 && socket->waitForReadyRead(2000)); if (got < 0) { qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData()); delete socket; return; } socket->write(ack, qstrlen(ack)); socket->waitForBytesWritten(1000); socket->waitForDisconnected(1000); // make sure client reads ack delete socket; emit messageReceived(uMsg); //### (might take a long time to return) }