diff --git a/Plugins/org.mitk.gui.qt.moviemaker2/files.cmake b/Plugins/org.mitk.gui.qt.moviemaker2/files.cmake index 231bea96db..cde7fca7f3 100644 --- a/Plugins/org.mitk.gui.qt.moviemaker2/files.cmake +++ b/Plugins/org.mitk.gui.qt.moviemaker2/files.cmake @@ -1,40 +1,42 @@ set(SRC_CPP_FILES ) set(INTERNAL_CPP_FILES org_mitk_gui_qt_moviemaker2_Activator.cpp QmitkAnimationItem.cpp + QmitkAnimationItemDelegate.cpp QmitkMovieMaker2View.cpp QmitkSliceAnimationWidget.cpp ) set(UI_FILES src/internal/QmitkMovieMaker2View.ui src/internal/QmitkSliceAnimationWidget.ui ) set(MOC_H_FILES src/internal/org_mitk_gui_qt_moviemaker2_Activator.h + src/internal/QmitkAnimationItemDelegate.h src/internal/QmitkMovieMaker2View.h src/internal/QmitkSliceAnimationWidget.h ) set(CACHED_RESOURCE_FILES resources/camera-video.png plugin.xml ) set(QRC_FILES resources/org_mitk_gui_qt_moviemaker2.qrc ) set(CPP_FILES ) foreach(file ${SRC_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/${file}) endforeach() foreach(file ${INTERNAL_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/internal/${file}) endforeach() diff --git a/Plugins/org.mitk.gui.qt.moviemaker2/src/internal/QmitkAnimationItem.cpp b/Plugins/org.mitk.gui.qt.moviemaker2/src/internal/QmitkAnimationItem.cpp index 94655f46ae..c55bb0808a 100644 --- a/Plugins/org.mitk.gui.qt.moviemaker2/src/internal/QmitkAnimationItem.cpp +++ b/Plugins/org.mitk.gui.qt.moviemaker2/src/internal/QmitkAnimationItem.cpp @@ -1,60 +1,71 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkAnimationItem.h" -QmitkAnimationItem::QmitkAnimationItem(double duration, double delay, bool startWithPrevious) +QmitkAnimationItem::QmitkAnimationItem(const QString& widgetKey, double duration, double delay, bool startWithPrevious) { + this->SetWidgetKey(widgetKey); this->SetDuration(duration); this->SetDelay(delay); this->SetStartWithPrevious(startWithPrevious); this->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); } QmitkAnimationItem::~QmitkAnimationItem() { } +QString QmitkAnimationItem::GetWidgetKey() const +{ + return this->data(WidgetKeyRole).toString(); +} + +void QmitkAnimationItem::SetWidgetKey(const QString& widgetKey) +{ + this->setData(widgetKey, WidgetKeyRole); +} + double QmitkAnimationItem::GetDuration() const { return this->data(DurationRole).toDouble(); } void QmitkAnimationItem::SetDuration(double duration) { this->setData(duration, DurationRole); } double QmitkAnimationItem::GetDelay() const { return this->data(DelayRole).toDouble(); } void QmitkAnimationItem::SetDelay(double delay) { this->setData(delay, DelayRole); } bool QmitkAnimationItem::GetStartWithPrevious() const { return this->data(StartWithPreviousRole).toBool(); } void QmitkAnimationItem::SetStartWithPrevious(bool startWithPrevious) { this->setData(startWithPrevious, StartWithPreviousRole); } diff --git a/Plugins/org.mitk.gui.qt.moviemaker2/src/internal/QmitkAnimationItem.h b/Plugins/org.mitk.gui.qt.moviemaker2/src/internal/QmitkAnimationItem.h index 0d3b2b0769..697dbd8dbb 100644 --- a/Plugins/org.mitk.gui.qt.moviemaker2/src/internal/QmitkAnimationItem.h +++ b/Plugins/org.mitk.gui.qt.moviemaker2/src/internal/QmitkAnimationItem.h @@ -1,45 +1,49 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkAnimationItem_h #define QmitkAnimationItem_h #include class QmitkAnimationItem : public QStandardItem { public: enum AnimationItemDataRole { - DurationRole = Qt::UserRole + 2, + WidgetKeyRole = Qt::UserRole + 2, + DurationRole, DelayRole, StartWithPreviousRole }; - explicit QmitkAnimationItem(double duration, double delay = 0.0, bool startWithPrevious = false); + QmitkAnimationItem(const QString& widgetKey, double duration, double delay = 0.0, bool startWithPrevious = false); ~QmitkAnimationItem(); + QString GetWidgetKey() const; + void SetWidgetKey(const QString& widgetKey); + double GetDuration() const; void SetDuration(double duration); double GetDelay() const; void SetDelay(double delay); bool GetStartWithPrevious() const; void SetStartWithPrevious(bool startWithPrevious); }; #endif diff --git a/Plugins/org.mitk.gui.qt.moviemaker2/src/internal/QmitkAnimationItemDelegate.cpp b/Plugins/org.mitk.gui.qt.moviemaker2/src/internal/QmitkAnimationItemDelegate.cpp new file mode 100644 index 0000000000..ba7b22dd1d --- /dev/null +++ b/Plugins/org.mitk.gui.qt.moviemaker2/src/internal/QmitkAnimationItemDelegate.cpp @@ -0,0 +1,99 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkAnimationItem.h" +#include "QmitkAnimationItemDelegate.h" +#include +#include +#include + +QmitkAnimationItemDelegate::QmitkAnimationItemDelegate(QObject* parent) + : QStyledItemDelegate(parent) +{ +} + +QmitkAnimationItemDelegate::~QmitkAnimationItemDelegate() +{ +} + +void QmitkAnimationItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const +{ + const QStandardItemModel* model = dynamic_cast(index.model()); + const QmitkAnimationItem* thisItem = dynamic_cast(model->item(index.row(), 1)); + QList items; + + const int rowCount = model->rowCount(); + + for (int i = 0; i < rowCount; ++i) + items << dynamic_cast(model->item(i, 1)); + + double totalDuration = 0.0; + double previousStart = 0.0; + double thisStart = 0.0; + + Q_FOREACH(const QmitkAnimationItem* item, items) + { + if (item->GetStartWithPrevious()) + { + totalDuration = std::max(totalDuration, previousStart + item->GetDelay() + item->GetDuration()); + } + else + { + previousStart = totalDuration; + totalDuration += item->GetDelay() + item->GetDuration(); + } + + if (item == thisItem) + thisStart = previousStart; + } + + QColor color("DarkKhaki"); + + painter->setBrush(color); + painter->setPen(Qt::NoPen); + + const QRect& rect = option.rect; + const double widthPerSecond = rect.width() / totalDuration; + + painter->drawRect( + rect.x() + static_cast(widthPerSecond * (thisStart + thisItem->GetDelay())), + rect.y() + 1, + static_cast(widthPerSecond * thisItem->GetDuration()), + rect.height() - 2); + + if (thisItem->GetDelay() > std::numeric_limits::min()) + { + QPen pen(color); + painter->setPen(pen); + + painter->drawLine( + rect.x() + static_cast(widthPerSecond * thisStart), + rect.y() + 1, + rect.x() + static_cast(widthPerSecond * thisStart), + rect.y() + rect.height() - 2); + + pen.setStyle(Qt::DashLine); + painter->setPen(pen); + + painter->drawLine( + rect.x() + static_cast(widthPerSecond * thisStart), + rect.y() + rect.height() / 2, + rect.x() + static_cast(widthPerSecond * (thisStart + thisItem->GetDelay())) - 1, + rect.y() + rect.height() / 2); + } + + QStyledItemDelegate::paint(painter, option, index); +} diff --git a/Plugins/org.mitk.gui.qt.moviemaker2/src/internal/QmitkAnimationItemDelegate.h b/Plugins/org.mitk.gui.qt.moviemaker2/src/internal/QmitkAnimationItemDelegate.h new file mode 100644 index 0000000000..b1ad53c99a --- /dev/null +++ b/Plugins/org.mitk.gui.qt.moviemaker2/src/internal/QmitkAnimationItemDelegate.h @@ -0,0 +1,33 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QmitkAnimationItemDelegate_h +#define QmitkAnimationItemDelegate_h + +#include + +class QmitkAnimationItemDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + explicit QmitkAnimationItemDelegate(QObject* parent = NULL); + ~QmitkAnimationItemDelegate(); + + void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.moviemaker2/src/internal/QmitkMovieMaker2View.cpp b/Plugins/org.mitk.gui.qt.moviemaker2/src/internal/QmitkMovieMaker2View.cpp index 1300f7b806..45672d0136 100644 --- a/Plugins/org.mitk.gui.qt.moviemaker2/src/internal/QmitkMovieMaker2View.cpp +++ b/Plugins/org.mitk.gui.qt.moviemaker2/src/internal/QmitkMovieMaker2View.cpp @@ -1,302 +1,328 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkAnimationItem.h" +#include "QmitkAnimationItemDelegate.h" #include "QmitkMovieMaker2View.h" #include "QmitkSliceAnimationWidget.h" #include #include #include const std::string QmitkMovieMaker2View::VIEW_ID = "org.mitk.views.moviemaker2"; QmitkMovieMaker2View::QmitkMovieMaker2View() : m_Ui(new Ui::QmitkMovieMaker2View), m_AnimationModel(NULL), m_AddAnimationMenu(NULL) { } QmitkMovieMaker2View::~QmitkMovieMaker2View() { } void QmitkMovieMaker2View::CreateQtPartControl(QWidget* parent) { m_Ui->setupUi(parent); this->InitializeAnimationWidgets(); this->InitializeAnimationTreeViewWidgets(); m_Ui->animationWidgetGroupBox->setVisible(false); } void QmitkMovieMaker2View::InitializeAnimationWidgets() { m_AnimationWidgets["Orbit"] = NULL; m_AnimationWidgets["Slice"] = new QmitkSliceAnimationWidget; Q_FOREACH(QWidget* widget, m_AnimationWidgets.values()) { if (widget != NULL) { widget->setVisible(false); m_Ui->animationWidgetGroupBoxLayout->addWidget(widget); } } this->ConnectAnimationWidgets(); } void QmitkMovieMaker2View::InitializeAnimationTreeViewWidgets() { this->InitializeAnimationModel(); this->InitializeAddAnimationMenu(); this->ConnectAnimationTreeViewWidgets(); } void QmitkMovieMaker2View::InitializeAnimationModel() { m_AnimationModel = new QStandardItemModel(m_Ui->animationTreeView); m_AnimationModel->setHorizontalHeaderLabels(QStringList() << "Animation" << "Timeline"); m_Ui->animationTreeView->setModel(m_AnimationModel); - // TODO: Either make first column not editable or derive according animation widget from second column + m_Ui->animationTreeView->setItemDelegateForColumn(1, new QmitkAnimationItemDelegate(m_Ui->animationTreeView)); } void QmitkMovieMaker2View::InitializeAddAnimationMenu() { m_AddAnimationMenu = new QMenu(m_Ui->addAnimationButton); Q_FOREACH(const QString& key, m_AnimationWidgets.keys()) { m_AddAnimationMenu->addAction(key); } } void QmitkMovieMaker2View::ConnectAnimationTreeViewWidgets() { this->connect(m_AnimationModel, SIGNAL(rowsInserted(const QModelIndex&, int, int)), this, SLOT(OnAnimationTreeViewRowsInserted(const QModelIndex&, int, int))); this->connect(m_AnimationModel, SIGNAL(rowsRemoved(const QModelIndex&, int, int)), this, SLOT(OnAnimationTreeViewRowsRemoved(const QModelIndex&, int, int))); this->connect(m_Ui->animationTreeView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), this, SLOT(OnAnimationTreeViewSelectionChanged(const QItemSelection&, const QItemSelection&))); this->connect(m_Ui->moveAnimationUpButton, SIGNAL(clicked()), this, SLOT(OnMoveAnimationUpButtonClicked())); this->connect(m_Ui->moveAnimationDownButton, SIGNAL(clicked()), this, SLOT(OnMoveAnimationDownButtonClicked())); this->connect(m_Ui->addAnimationButton, SIGNAL(clicked()), this, SLOT(OnAddAnimationButtonClicked())); this->connect(m_Ui->removeAnimationButton, SIGNAL(clicked()), this, SLOT(OnRemoveAnimationButtonClicked())); } void QmitkMovieMaker2View::ConnectAnimationWidgets() { this->connect(m_Ui->startComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnStartComboBoxCurrentIndexChanged(int))); this->connect(m_Ui->durationSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnDurationSpinBoxValueChanged(double))); this->connect(m_Ui->delaySpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnDelaySpinBoxValueChanged(double))); } void QmitkMovieMaker2View::SetFocus() { m_Ui->addAnimationButton->setFocus(); } void QmitkMovieMaker2View::OnMoveAnimationUpButtonClicked() { const QItemSelection selection = m_Ui->animationTreeView->selectionModel()->selection(); if (!selection.isEmpty()) { const int selectedRow = selection[0].top(); if (selectedRow > 0) m_AnimationModel->insertRow(selectedRow - 1, m_AnimationModel->takeRow(selectedRow)); } } void QmitkMovieMaker2View::OnMoveAnimationDownButtonClicked() { const QItemSelection selection = m_Ui->animationTreeView->selectionModel()->selection(); if (!selection.isEmpty()) { const int rowCount = m_AnimationModel->rowCount(); const int selectedRow = selection[0].top(); if (selectedRow < rowCount - 1) m_AnimationModel->insertRow(selectedRow + 1, m_AnimationModel->takeRow(selectedRow)); } } void QmitkMovieMaker2View::OnAddAnimationButtonClicked() { QAction* action = m_AddAnimationMenu->exec(QCursor::pos()); if (action != NULL) - m_AnimationModel->appendRow(QList() << new QStandardItem(action->text()) << new QmitkAnimationItem(2.0)); + { + const QString widgetKey = action->text(); + + m_AnimationModel->appendRow(QList() + << new QStandardItem(widgetKey) + << new QmitkAnimationItem(widgetKey, 2.0)); + } } void QmitkMovieMaker2View::OnRemoveAnimationButtonClicked() { const QItemSelection selection = m_Ui->animationTreeView->selectionModel()->selection(); if (!selection.isEmpty()) m_AnimationModel->removeRow(selection[0].top()); } void QmitkMovieMaker2View::OnAnimationTreeViewRowsInserted(const QModelIndex& parent, int start, int) { m_Ui->animationTreeView->selectionModel()->select( m_AnimationModel->index(start, 0, parent), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); } void QmitkMovieMaker2View::OnAnimationTreeViewRowsRemoved(const QModelIndex&, int, int) { this->UpdateWidgets(); } void QmitkMovieMaker2View::OnAnimationTreeViewSelectionChanged(const QItemSelection&, const QItemSelection&) { this->UpdateWidgets(); } void QmitkMovieMaker2View::OnStartComboBoxCurrentIndexChanged(int index) { QmitkAnimationItem* item = this->GetSelectedAnimationItem(); if (item != NULL) + { item->SetStartWithPrevious(index); + this->RedrawTimeline(); + } } void QmitkMovieMaker2View::OnDurationSpinBoxValueChanged(double value) { QmitkAnimationItem* item = this->GetSelectedAnimationItem(); if (item != NULL) + { item->SetDuration(value); + this->RedrawTimeline(); + } } void QmitkMovieMaker2View::OnDelaySpinBoxValueChanged(double value) { QmitkAnimationItem* item = this->GetSelectedAnimationItem(); if (item != NULL) + { item->SetDelay(value); + this->RedrawTimeline(); + } } void QmitkMovieMaker2View::UpdateWidgets() { const QItemSelection selection = m_Ui->animationTreeView->selectionModel()->selection(); if (selection.isEmpty()) { m_Ui->moveAnimationUpButton->setEnabled(false); m_Ui->moveAnimationDownButton->setEnabled(false); m_Ui->removeAnimationButton->setEnabled(false); this->HideCurrentAnimationWidget(); } else { const int rowCount = m_AnimationModel->rowCount(); const int selectedRow = selection[0].top(); m_Ui->moveAnimationUpButton->setEnabled(rowCount > 1 && selectedRow != 0); m_Ui->moveAnimationDownButton->setEnabled(rowCount > 1 && selectedRow < rowCount - 1); m_Ui->removeAnimationButton->setEnabled(true); - this->ShowAnimationWidget(m_AnimationModel->item(selectedRow)->text()); + this->ShowAnimationWidget(m_AnimationModel->item(selectedRow, 1)->data(QmitkAnimationItem::WidgetKeyRole).toString()); } this->UpdateAnimationWidgets(); } void QmitkMovieMaker2View::UpdateAnimationWidgets() { QmitkAnimationItem* item = this->GetSelectedAnimationItem(); if (item != NULL) { m_Ui->startComboBox->setCurrentIndex(item->GetStartWithPrevious()); m_Ui->durationSpinBox->setValue(item->GetDuration()); m_Ui->delaySpinBox->setValue(item->GetDelay()); m_Ui->animationGroupBox->setEnabled(true); } else { m_Ui->animationGroupBox->setEnabled(false); } } void QmitkMovieMaker2View::HideCurrentAnimationWidget() { if (m_Ui->animationWidgetGroupBox->isVisible()) { m_Ui->animationWidgetGroupBox->setVisible(false); if (m_Ui->animationWidgetGroupBoxLayout->count() > 0) m_Ui->animationWidgetGroupBoxLayout->itemAt(0)->widget()->setVisible(false); } } void QmitkMovieMaker2View::ShowAnimationWidget(const QString& key) { if (m_Ui->animationWidgetGroupBox->isVisible()) { if (m_Ui->animationWidgetGroupBoxLayout->count() > 0) m_Ui->animationWidgetGroupBoxLayout->itemAt(0)->widget()->setVisible(false); } QWidget* widget = NULL; if (m_AnimationWidgets.contains(key)) { widget = m_AnimationWidgets[key]; if (widget != NULL) { m_Ui->animationWidgetGroupBox->setTitle(key); widget->setVisible(true); } } m_Ui->animationWidgetGroupBox->setVisible(widget != NULL); } +void QmitkMovieMaker2View::RedrawTimeline() +{ + if (m_AnimationModel->rowCount() > 1) + { + m_Ui->animationTreeView->dataChanged( + m_AnimationModel->index(0, 1), + m_AnimationModel->index(m_AnimationModel->rowCount() - 1, 1)); + } +} + QmitkAnimationItem* QmitkMovieMaker2View::GetSelectedAnimationItem() const { const QItemSelection selection = m_Ui->animationTreeView->selectionModel()->selection(); return !selection.isEmpty() ? dynamic_cast(m_AnimationModel->item(selection[0].top(), 1)) : NULL; } diff --git a/Plugins/org.mitk.gui.qt.moviemaker2/src/internal/QmitkMovieMaker2View.h b/Plugins/org.mitk.gui.qt.moviemaker2/src/internal/QmitkMovieMaker2View.h index c5ef10e196..be66d262af 100644 --- a/Plugins/org.mitk.gui.qt.moviemaker2/src/internal/QmitkMovieMaker2View.h +++ b/Plugins/org.mitk.gui.qt.moviemaker2/src/internal/QmitkMovieMaker2View.h @@ -1,75 +1,76 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkMovieMaker2View_h #define QmitkMovieMaker2View_h #include class QmitkAnimationItem; class QMenu; class QStandardItemModel; namespace Ui { class QmitkMovieMaker2View; } class QmitkMovieMaker2View : public QmitkAbstractView { Q_OBJECT public: static const std::string VIEW_ID; QmitkMovieMaker2View(); ~QmitkMovieMaker2View(); void CreateQtPartControl(QWidget* parent); void SetFocus(); private slots: void OnMoveAnimationUpButtonClicked(); void OnMoveAnimationDownButtonClicked(); void OnAddAnimationButtonClicked(); void OnRemoveAnimationButtonClicked(); void OnAnimationTreeViewRowsInserted(const QModelIndex& parent, int start, int end); void OnAnimationTreeViewRowsRemoved(const QModelIndex& parent, int start, int end); void OnAnimationTreeViewSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected); void OnStartComboBoxCurrentIndexChanged(int index); void OnDurationSpinBoxValueChanged(double value); void OnDelaySpinBoxValueChanged(double value); private: void InitializeAnimationWidgets(); void InitializeAnimationTreeViewWidgets(); void InitializeAnimationModel(); void InitializeAddAnimationMenu(); void ConnectAnimationTreeViewWidgets(); void ConnectAnimationWidgets(); void UpdateWidgets(); void UpdateAnimationWidgets(); void HideCurrentAnimationWidget(); void ShowAnimationWidget(const QString& key); + void RedrawTimeline(); QmitkAnimationItem* GetSelectedAnimationItem() const; Ui::QmitkMovieMaker2View* m_Ui; QStandardItemModel* m_AnimationModel; QMap m_AnimationWidgets; QMenu* m_AddAnimationMenu; }; #endif