summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@qt.io>2017-11-21 15:59:19 +0200
committerMiikka Heikkinen <miikka.heikkinen@qt.io>2017-11-23 08:21:45 +0000
commit77d7e220dafbf8a76e26a0dbe87c7fbe9bf5b07b (patch)
treeecf70f63b53a606fe25d3b1276b563e0043cff28
parentba9e92cd089d06b837b231ed777f7ade45c751c1 (diff)
Fix slide manipulation undo/redo
Now slide add, delete, rearrange, duplicate, and rename can be undone and redone. Task-number: QT3DS-480 Change-Id: I1256c954b0a478e095d3431c8b61e9c41aed5895 Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
-rw-r--r--src/Authoring/Studio/Palettes/Slide/SlideModel.cpp174
-rw-r--r--src/Authoring/Studio/Palettes/Slide/SlideModel.h16
-rw-r--r--src/Authoring/Studio/Palettes/Slide/SlideView.cpp41
-rw-r--r--src/Authoring/Studio/Palettes/Slide/SlideView.h2
-rw-r--r--src/Authoring/Studio/Palettes/Slide/SlideView.qml12
5 files changed, 197 insertions, 48 deletions
diff --git a/src/Authoring/Studio/Palettes/Slide/SlideModel.cpp b/src/Authoring/Studio/Palettes/Slide/SlideModel.cpp
index f97c621c..f31ae51f 100644
--- a/src/Authoring/Studio/Palettes/Slide/SlideModel.cpp
+++ b/src/Authoring/Studio/Palettes/Slide/SlideModel.cpp
@@ -32,7 +32,7 @@
#include "Core.h"
#include "Doc.h"
#include "StudioApp.h"
-
+#include "SlideSystem.h"
#include "IDocumentEditor.h"
#include "ClientDataModelBridge.h"
@@ -42,7 +42,6 @@
SlideModel::SlideModel(int slideCount, QObject *parent) : QAbstractListModel(parent)
, m_slides(slideCount)
{
-
}
QVariant SlideModel::data(const QModelIndex &index, int role) const
@@ -77,6 +76,9 @@ bool SlideModel::setData(const QModelIndex &index, const QVariant &value, int ro
}
case HandleRole: {
slideHandle = value.value<qt3dsdm::Qt3DSDMSlideHandle>();
+ qt3dsdm::Qt3DSDMInstanceHandle instanceHandle
+ = GetDoc()->GetStudioSystem()->GetSlideSystem()->GetSlideInstance(slideHandle);
+ m_slideLookupHash.insert(instanceHandle, slideHandle);
Q_EMIT dataChanged(index, index, {HandleRole, NameRole});
break;
}
@@ -121,7 +123,7 @@ bool SlideModel::insertRows(int row, int count, const QModelIndex &parent)
return false;
beginInsertRows(parent, row, row + count - 1);
- for (int i = 0; i < count; i++)
+ for (int i = 0; i < count; ++i)
m_slides.insert(row, {});
endInsertRows();
@@ -136,7 +138,7 @@ bool SlideModel::removeRows(int row, int count, const QModelIndex &parent)
bool selectionRemoved = false;
beginRemoveRows(parent, row, row + count - 1);
- for (int i = 0; i < count; i++) {
+ for (int i = 0; i < count; ++i) {
if (m_selectedRow == row)
selectionRemoved = true;
m_slides.removeAt(row);
@@ -161,15 +163,14 @@ bool SlideModel::removeRows(int row, int count, const QModelIndex &parent)
void SlideModel::duplicateRow(int row)
{
const auto handle = m_slides[row];
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*GetDoc(), QObject::tr("Duplicate Slide"))
+ ->DuplicateSlide(handle);
+}
- beginInsertRows({}, row, row);
- m_slides.insert(row + 1, Q3DStudio::SCOPED_DOCUMENT_EDITOR(*GetDoc(),
- QObject::tr("Duplicate Slide"))
- ->DuplicateSlide(handle));
- endInsertRows();
- setData(index(row + 1), true, SelectedRole);
-
- Q_EMIT dataChanged(index(row, 0), index(row + 1, 0), {});
+void SlideModel::startRearrange(int row)
+{
+ m_rearrangeStartRow = row;
+ m_rearrangeEndRow = -1;
}
void SlideModel::move(int fromRow, int toRow)
@@ -177,40 +178,44 @@ void SlideModel::move(int fromRow, int toRow)
if (fromRow == toRow)
return;
- auto handle = m_slides[fromRow];
- // toRow + 1 as DocumentEditor uses 1 based indexes for slides
- Q3DStudio::SCOPED_DOCUMENT_EDITOR(*GetDoc(), QObject::tr("Rearrange Slide"))
- ->RearrangeSlide(handle, toRow + 1);
+ onSlideRearranged({}, fromRow + 1, toRow + 1);
+}
- if (fromRow > toRow)
- beginMoveRows({}, fromRow, fromRow, {}, toRow);
- else
- beginMoveRows({}, fromRow, fromRow, {}, toRow + 1);
- m_slides.move(fromRow, toRow);
- endMoveRows();
+void SlideModel::finishRearrange(bool commit)
+{
+ if (m_rearrangeEndRow != m_rearrangeStartRow
+ && m_rearrangeEndRow >= 0 && m_rearrangeStartRow >= 0) {
+ // Restore state before committing the actual change
+ // +1 added as DocumentEditor uses 1 based indexes for slides
+ int endRow = m_rearrangeEndRow + 1;
+ onSlideRearranged({}, endRow, m_rearrangeStartRow + 1);
+
+ if (commit) {
+ auto handle = m_slides[m_rearrangeStartRow];
+ m_rearrangeStartRow = -1;
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*GetDoc(), QObject::tr("Rearrange Slide"))
+ ->RearrangeSlide(handle, endRow);
+ }
+ }
+ m_rearrangeEndRow = -1;
+ m_rearrangeStartRow = -1;
}
void SlideModel::clear()
{
beginResetModel();
m_slides.clear();
+ m_slideLookupHash.clear();
endResetModel();
}
void SlideModel::addNewSlide(int row)
{
const auto handle = (row < m_slides.size()) ? m_slides[row] : m_slides.last();
-
const auto instanceHandle = GetBridge()->GetOwningComponentInstance(handle);
qt3dsdm::Qt3DSDMSlideHandle theMasterSlide = GetBridge()->GetComponentSlide(instanceHandle, 0);
-
- beginInsertRows({}, row, row);
- m_slides.insert(row, Q3DStudio::SCOPED_DOCUMENT_EDITOR(*GetDoc(),
- QObject::tr("Create Slide"))
- ->AddSlide(theMasterSlide, row + 1));
- endInsertRows();
-
- setData(index(row), true, SelectedRole);
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*GetDoc(), QObject::tr("Create Slide"))
+ ->AddSlide(theMasterSlide, row + 1);
}
void SlideModel::removeSlide(int row)
@@ -218,13 +223,94 @@ void SlideModel::removeSlide(int row)
// Don't allow deleting of the last slide
if (m_slides.size() > 1) {
const auto handle = m_slides[row];
-
Q3DStudio::SCOPED_DOCUMENT_EDITOR(*GetDoc(), QObject::tr("Delete Slide"))->DeleteSlide(
handle);
- removeRows(row, 1);
}
}
+void SlideModel::onNewSlide(const qt3dsdm::Qt3DSDMSlideHandle &inSlide)
+{
+ qt3dsdm::ISlideSystem &theSlideSystem(*GetDoc()->GetStudioSystem()->GetSlideSystem());
+
+ // Ignore new slides added to random different components
+ if (m_slides.size() && theSlideSystem.GetMasterSlide(inSlide)
+ != theSlideSystem.GetMasterSlide(m_slides[0])) {
+ return;
+ }
+
+ finishRearrange(false); // Cancel any uncommitted rearrange
+
+ // Find the slide index
+ int row = int(slideIndex(inSlide));
+
+ // Slide index zero indicates master slide. We can't add master slides
+ Q_ASSERT(row > 0);
+
+ --row;
+
+ beginInsertRows({}, row, row);
+ m_slides.insert(row, inSlide);
+ qt3dsdm::Qt3DSDMInstanceHandle instanceHandle
+ = GetDoc()->GetStudioSystem()->GetSlideSystem()->GetSlideInstance(inSlide);
+ m_slideLookupHash.insert(instanceHandle, inSlide);
+ endInsertRows();
+
+ setData(index(row), true, SelectedRole);
+}
+
+void SlideModel::onDeleteSlide(const qt3dsdm::Qt3DSDMSlideHandle &inSlide)
+{
+ for (int i = 0; i < m_slides.size(); ++i) {
+ if (m_slides[i] == inSlide) {
+ if (m_rearrangeStartRow >= 0) {
+ finishRearrange(false); // Cancel any uncommitted rearrange
+ // We need to re-resolve the index after rearrange cancel
+ for (int j = 0; j < m_slides.size(); ++j) {
+ if (m_slides[j] == inSlide) {
+ i = j;
+ break;
+ }
+ }
+ }
+ QList<qt3dsdm::Qt3DSDMInstanceHandle> keys = m_slideLookupHash.keys(inSlide);
+ for (auto key : keys)
+ m_slideLookupHash.remove(key);
+ removeRows(i, 1);
+ break;
+ }
+ }
+}
+
+void SlideModel::onSlideRearranged(const qt3dsdm::Qt3DSDMSlideHandle &inMaster, int fromRow,
+ int toRow)
+{
+ if (inMaster.Valid()) {
+ // If imMaster is valid, this was triggered by either a rearrange commit or
+ // undo/redo of a rearrange, so we need to cancel any uncommitted rearrange.
+ finishRearrange(false);
+ // Check we are working on correct slide set
+ qt3dsdm::ISlideSystem &theSlideSystem(*GetDoc()->GetStudioSystem()->GetSlideSystem());
+ if (fromRow - 1 >= m_slides.size()
+ || inMaster != theSlideSystem.GetMasterSlide(m_slides[fromRow - 1]))
+ return;
+ } else {
+ // Do not do uncommitted rearranges if we haven't started a rearrange (or more likely
+ // an uncommitted rearrange was canceled while in progress by undo/redo operation)
+ if (m_rearrangeStartRow < 0)
+ return;
+ }
+
+ // -1 because internal slide model has 1-based indexing for non-master slides
+ if (fromRow > toRow)
+ beginMoveRows({}, fromRow - 1, fromRow - 1, {}, toRow - 1);
+ else
+ beginMoveRows({}, fromRow - 1, fromRow - 1, {}, toRow);
+ m_slides.move(fromRow - 1, toRow - 1);
+ m_rearrangeEndRow = toRow - 1;
+
+ endMoveRows();
+}
+
bool SlideModel::hasSlideWithName(const QString &name) const
{
for (const auto &slide: m_slides) {
@@ -266,6 +352,11 @@ CDoc *SlideModel::GetDoc() const
return g_StudioApp.GetCore()->GetDoc();
}
+long SlideModel::slideIndex(const qt3dsdm::Qt3DSDMSlideHandle &handle)
+{
+ return GetDoc()->GetStudioSystem()->GetSlideSystem()->GetSlideIndex(handle);
+}
+
CClientDataModelBridge *SlideModel::GetBridge() const
{
auto doc = GetDoc();
@@ -274,4 +365,21 @@ CClientDataModelBridge *SlideModel::GetBridge() const
return doc->GetStudioSystem()->GetClientDataModelBridge();
}
+void SlideModel::refreshSlideLabel(qt3dsdm::Qt3DSDMInstanceHandle instanceHandle,
+ qt3dsdm::Qt3DSDMPropertyHandle propertyHandle)
+{
+ if (m_slideLookupHash.contains(instanceHandle)
+ && propertyHandle == GetBridge()->GetNameProperty()) {
+ qt3dsdm::Qt3DSDMSlideHandle slideHandle = m_slideLookupHash.value(instanceHandle);
+ for (int i = 0; i < m_slides.size(); ++i) {
+ if (m_slides[i] == slideHandle) {
+ setData(index(i, 0), GetBridge()->GetName(instanceHandle).toQString(),
+ SlideModel::NameRole);
+ }
+ }
+ }
+
+}
+
+
diff --git a/src/Authoring/Studio/Palettes/Slide/SlideModel.h b/src/Authoring/Studio/Palettes/Slide/SlideModel.h
index b5da9670..da44c1c7 100644
--- a/src/Authoring/Studio/Palettes/Slide/SlideModel.h
+++ b/src/Authoring/Studio/Palettes/Slide/SlideModel.h
@@ -29,7 +29,8 @@
#ifndef SLIDEMODEL_H
#define SLIDEMODEL_H
-#include <QAbstractListModel>
+#include <QtCore/qabstractitemmodel.h>
+#include <QtCore/qhash.h>
#include "Qt3DSDMHandles.h"
@@ -60,21 +61,34 @@ public:
bool removeRows(int row, int count,
const QModelIndex &parent = QModelIndex()) override;
void duplicateRow(int row);
+ void startRearrange(int row);
void move(int fromRow, int toRow);
+ void finishRearrange(bool commit);
void clear();
void addNewSlide(int row);
void removeSlide(int row);
+ void onNewSlide(const qt3dsdm::Qt3DSDMSlideHandle &inSlide);
+ void onDeleteSlide(const qt3dsdm::Qt3DSDMSlideHandle &inSlide);
+ void onSlideRearranged(const qt3dsdm::Qt3DSDMSlideHandle &inMaster, int inOldIndex,
+ int toRow);
+ void refreshSlideLabel(qt3dsdm::Qt3DSDMInstanceHandle instanceHandle,
+ qt3dsdm::Qt3DSDMPropertyHandle propertyHandle);
+
private:
bool hasSlideWithName(const QString &name) const;
QString slideName(const qt3dsdm::Qt3DSDMSlideHandle &handle) const;
void setSlideName(const qt3dsdm::Qt3DSDMSlideHandle &handle, const QString &name);
inline CDoc *GetDoc() const;
+ inline long slideIndex(const qt3dsdm::Qt3DSDMSlideHandle &handle);
inline CClientDataModelBridge *GetBridge() const;
QVector<qt3dsdm::Qt3DSDMSlideHandle> m_slides;
int m_selectedRow = -1;
+ int m_rearrangeStartRow = -1;
+ int m_rearrangeEndRow = -1;
+ QHash<qt3dsdm::Qt3DSDMInstanceHandle, qt3dsdm::Qt3DSDMSlideHandle> m_slideLookupHash;
};
diff --git a/src/Authoring/Studio/Palettes/Slide/SlideView.cpp b/src/Authoring/Studio/Palettes/Slide/SlideView.cpp
index eb803874..c6c188f3 100644
--- a/src/Authoring/Studio/Palettes/Slide/SlideView.cpp
+++ b/src/Authoring/Studio/Palettes/Slide/SlideView.cpp
@@ -136,11 +136,21 @@ void SlideView::duplicateSlide(int row)
m_SlidesModel->duplicateRow(row);
}
+void SlideView::startSlideRearrange(int row)
+{
+ m_SlidesModel->startRearrange(row);
+}
+
void SlideView::moveSlide(int from, int to)
{
m_SlidesModel->move(from, to);
}
+void SlideView::finishSlideRearrange(bool commit)
+{
+ m_SlidesModel->finishRearrange(commit);
+}
+
void SlideView::showContextMenu(int x, int y, int row)
{
SlideContextMenu contextMenu(this, row, m_SlidesModel->rowCount(),
@@ -159,9 +169,7 @@ void SlideView::OnNewPresentation()
std::bind(&SlideView::OnActiveSlide, this, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3)));
- // KDAB_TODO We most probably don't need to listen to the below signals,
- // as the functionality is done in the model already. Remove after it is confirmed
- // it works as desired when the rendering works.
+ // Needed for undo/redo functionality to work properly
m_Connections.push_back(theSignalProvider->ConnectSlideCreated(
std::bind(&SlideView::OnNewSlide, this, std::placeholders::_1)));
m_Connections.push_back(theSignalProvider->ConnectSlideDeleted(
@@ -169,6 +177,12 @@ void SlideView::OnNewPresentation()
m_Connections.push_back(theSignalProvider->ConnectSlideRearranged(
std::bind(&SlideView::OnSlideRearranged, this, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3)));
+
+ // Set up listener for the name changes to slide
+ m_Connections.push_back(theSignalProvider->ConnectInstancePropertyValue(
+ std::bind(&SlideModel::refreshSlideLabel, m_SlidesModel,
+ std::placeholders::_1, std::placeholders::_2)));
+
}
void SlideView::OnClosingPresentation()
@@ -180,26 +194,29 @@ void SlideView::OnClosingPresentation()
void SlideView::OnActiveSlide(const qt3dsdm::Qt3DSDMSlideHandle &inMaster, int inIndex,
const qt3dsdm::Qt3DSDMSlideHandle &inSlide)
{
- // When the active slide changes, we need to update our button and mode
- if (inMaster.Valid()) {
- // if inIndex is 0, it means that we are activating master slide
- setShowMasterSlide(inIndex == 0);
- setActiveSlide(inSlide);
- }
+ // Don't use inIndex because inIndex might have been changed due to deletion
+ Q_UNUSED(inIndex);
+ Q_UNUSED(inMaster);
+
+ qt3dsdm::ISlideSystem &theSlideSystem(*GetDoc()->GetStudioSystem()->GetSlideSystem());
+ setShowMasterSlide(theSlideSystem.GetSlideIndex(inSlide) == 0);
+ setActiveSlide(inSlide);
}
void SlideView::OnNewSlide(const qt3dsdm::Qt3DSDMSlideHandle &inSlide)
{
-
+ m_SlidesModel->onNewSlide(inSlide);
}
void SlideView::OnDeleteSlide(const qt3dsdm::Qt3DSDMSlideHandle &inSlide)
{
-
+ m_SlidesModel->onDeleteSlide(inSlide);
}
-void SlideView::OnSlideRearranged(const qt3dsdm::Qt3DSDMSlideHandle &inMaster, int inOldIndex, int inNewIndex)
+void SlideView::OnSlideRearranged(const qt3dsdm::Qt3DSDMSlideHandle &inMaster, int inOldIndex,
+ int inNewIndex)
{
+ m_SlidesModel->onSlideRearranged(inMaster, inOldIndex, inNewIndex);
}
void SlideView::initialize()
diff --git a/src/Authoring/Studio/Palettes/Slide/SlideView.h b/src/Authoring/Studio/Palettes/Slide/SlideView.h
index d818c745..b8f6d01d 100644
--- a/src/Authoring/Studio/Palettes/Slide/SlideView.h
+++ b/src/Authoring/Studio/Palettes/Slide/SlideView.h
@@ -62,7 +62,9 @@ public:
Q_INVOKABLE void addNewSlide(int row);
Q_INVOKABLE void removeSlide(int row);
Q_INVOKABLE void duplicateSlide(int row);
+ Q_INVOKABLE void startSlideRearrange(int row);
Q_INVOKABLE void moveSlide(int from, int to);
+ Q_INVOKABLE void finishSlideRearrange(bool commit);
Q_INVOKABLE void showContextMenu(int x, int y, int row);
// Presentation Change Listener
diff --git a/src/Authoring/Studio/Palettes/Slide/SlideView.qml b/src/Authoring/Studio/Palettes/Slide/SlideView.qml
index 4fb00eb3..1d9e5cc7 100644
--- a/src/Authoring/Studio/Palettes/Slide/SlideView.qml
+++ b/src/Authoring/Studio/Palettes/Slide/SlideView.qml
@@ -151,14 +151,22 @@ Rectangle {
drag.target: held ? delegateItem : null
drag.axis: Drag.YAxis
-
onPressed: {
dragIndex = model.index;
+ _slideView.startSlideRearrange(model.index);
if (mouse.x > delegateItem.x && mouse.x < delegateItem.x + delegateItem.width)
held = true;
}
- onReleased: held = false
+ onReleased: {
+ held = false;
+ _slideView.finishSlideRearrange(true);
+ }
+
+ onCanceled: {
+ held = false;
+ _slideView.finishSlideRearrange(false);
+ }
onClicked: {
_slideView.deselectAll();