diff options
author | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2018-06-28 17:03:55 +0300 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2018-06-29 12:04:24 +0000 |
commit | d2d0866310998b65ea8cf656c3d35d6fb803fbab (patch) | |
tree | f3cd8cc5fb15cd51af1f868fd95a5836c3a6ccf1 | |
parent | 43fa674645ed9ebf5414ec2598858554b4c76c50 (diff) |
Add support for grouping and ungrouping selected items
Ctrl-G will group 2 or more selected items under a newly created group
item. Same shortcut when an single group is selected will move the
group's children up one level and delete the group.
Task-number: QT3DS-1283
Change-Id: Ife0fa6f0c35a4d37f7e76c7233e79c9f38d98a02
Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
16 files changed, 257 insertions, 35 deletions
diff --git a/src/Authoring/Client/Code/Core/Doc/DocumentEditor.cpp b/src/Authoring/Client/Code/Core/Doc/DocumentEditor.cpp index f2441067..d7e18cee 100644 --- a/src/Authoring/Client/Code/Core/Doc/DocumentEditor.cpp +++ b/src/Authoring/Client/Code/Core/Doc/DocumentEditor.cpp @@ -2326,6 +2326,61 @@ public: } } + // Move all children out of a given parent instances and delete the instances. + // Typically the parent instances are groups as the function name implies. + void ungroupObjects(const TInstanceHandleList &inInstances) override + { + for (size_t idx = 0, end = inInstances.size(); idx < end; ++idx) { + TInstanceHandle selected = inInstances[idx]; + if (selected.Valid()) { + TInstanceHandleList childHandles; + CGraphIterator children; + GetAssetChildrenInActiveSlide(selected, children); + for (; !children.IsDone(); ++children) { + TInstanceHandle child = children.GetCurrent(); + childHandles.push_back(child); + } + + // Rename the selected and to-be deleted instance so that it is less likely to cause + // name clash when its children are moved to the same level + CString name = GetName(selected); + name.append("@@to_be_deleted@@"); + SetName(selected, name); + + // Move group's children directly below the group item + RearrangeObjects(childHandles, selected, DocumentEditorInsertType::NextSibling, + true); + + // Delete the group + DeleteInstance(selected); + + // Select ungrouped instances + for (size_t i = 0, end = childHandles.size(); i < end; ++i) { + if (i == 0 && idx == 0) + m_Doc.SelectDataModelObject(childHandles[i]); + else + m_Doc.ToggleDataModelObjectToSelection(childHandles[i]); + } + } + } + } + + // Creates a new group object and moves the specified objects as its children + void groupObjects(const TInstanceHandleList &inInstances) override + { + TInstanceHandleList sortedList(ToGraphOrdering(inInstances)); + + // Create a new group next to the topmost item in the graph + TInstanceHandle sibling = sortedList.front(); + Qt3DSDMSlideHandle slide = GetActiveSlide(sibling); + TInstanceHandle group = CreateSceneGraphInstance(ComposerObjectTypes::Group, sibling, slide, + DocumentEditorInsertType::PreviousSibling, + CPt(), PRIMITIVETYPE_UNKNOWN, -1); + + // Move items into the group + RearrangeObjects(sortedList, group, DocumentEditorInsertType::LastChild, true); + } + Qt3DSDMInstanceHandle MakeComponent(const qt3dsdm::TInstanceHandleList &inInstances) override { if (inInstances.empty()) diff --git a/src/Authoring/Client/Code/Core/Doc/IDocumentEditor.h b/src/Authoring/Client/Code/Core/Doc/IDocumentEditor.h index 3e73cf7b..5ab7b02d 100644 --- a/src/Authoring/Client/Code/Core/Doc/IDocumentEditor.h +++ b/src/Authoring/Client/Code/Core/Doc/IDocumentEditor.h @@ -286,6 +286,9 @@ public: RearrangeObjects(theInstances, inDest, inInsertType, checkUniqueName); } + virtual void ungroupObjects(const qt3dsdm::TInstanceHandleList &inInstances) = 0; + virtual void groupObjects(const qt3dsdm::TInstanceHandleList &inInstances) = 0; + // Returns the new component. virtual TInstanceHandle MakeComponent(const qt3dsdm::TInstanceHandleList &inInstances) = 0; diff --git a/src/Authoring/Studio/Application/StudioApp.cpp b/src/Authoring/Studio/Application/StudioApp.cpp index 53692d5e..afde7d6e 100644 --- a/src/Authoring/Studio/Application/StudioApp.cpp +++ b/src/Authoring/Studio/Application/StudioApp.cpp @@ -996,6 +996,50 @@ QString CStudioApp::getDeleteType() const return {}; } +bool CStudioApp::canGroupSelectedObjects() const +{ + // Grouping is never just one row, we always deal with multiple selected items + qt3dsdm::TInstanceHandleList selected = m_core->GetDoc() + ->GetSelectedValue().GetSelectedInstances(); + return (selected.size() > 1); +} + +bool CStudioApp::canUngroupSelectedObjects() const +{ + qt3dsdm::TInstanceHandleList selected = m_core->GetDoc() + ->GetSelectedValue().GetSelectedInstances(); + if (selected.size() == 1) { + qt3dsdm::Qt3DSDMInstanceHandle first = selected[0]; + return (first.Valid() && m_core->GetDoc()->GetStudioSystem()->GetClientDataModelBridge() + ->GetObjectType(first) == OBJTYPE_GROUP); + } + return false; +} + +bool CStudioApp::groupSelectedObjects() const +{ + if (canGroupSelectedObjects()) { + qt3dsdm::TInstanceHandleList selected = m_core->GetDoc() + ->GetSelectedValue().GetSelectedInstances(); + SCOPED_DOCUMENT_EDITOR(*m_core->GetDoc(), + QObject::tr("Group objects"))->groupObjects(selected); + return true; + } + return false; +} + +bool CStudioApp::ungroupSelectedObjects() const +{ + if (canUngroupSelectedObjects()) { + qt3dsdm::TInstanceHandleList selected = m_core->GetDoc() + ->GetSelectedValue().GetSelectedInstances(); + SCOPED_DOCUMENT_EDITOR(*m_core->GetDoc(), + QObject::tr("Ungroup objects"))->ungroupObjects(selected); + return true; + } + return false; +} + //============================================================================= /** * Cuts the selected object or keys diff --git a/src/Authoring/Studio/Application/StudioApp.h b/src/Authoring/Studio/Application/StudioApp.h index bc6a594b..530be0f4 100644 --- a/src/Authoring/Studio/Application/StudioApp.h +++ b/src/Authoring/Studio/Application/StudioApp.h @@ -165,6 +165,10 @@ public: QString GetCopyType(); QString getDuplicateType() const; QString getDeleteType() const; + bool canGroupSelectedObjects() const; + bool canUngroupSelectedObjects() const; + bool groupSelectedObjects() const; + bool ungroupSelectedObjects() const; void OnCut(); bool CanCut(); void OnPaste(); diff --git a/src/Authoring/Studio/MainFrm.cpp b/src/Authoring/Studio/MainFrm.cpp index 48cd8842..76008d96 100644 --- a/src/Authoring/Studio/MainFrm.cpp +++ b/src/Authoring/Studio/MainFrm.cpp @@ -125,7 +125,7 @@ CMainFrame::CMainFrame() this, &CMainFrame::onEditPasteToMaster); connect(m_ui->action_Duplicate_Object, &QAction::triggered, this, &CMainFrame::OnEditDuplicate); connect(m_ui->actionDelete, &QAction::triggered, this, &CMainFrame::onEditDelete); -// connect(m_ui->actionGroup, &QAction::triggered, this, &CMainFrame::onEditGroup); // TODO: Implement + connect(m_ui->actionGroup, &QAction::triggered, this, &CMainFrame::onEditGroup); // connect(m_ui->actionParent, &QAction::triggered, this, &CMainFrame::onEditParent); // TODO: Implement // connect(m_ui->actionUnparent, &QAction::triggered, this, &CMainFrame::onEditUnparent); // TODO: Implement connect(m_ui->actionStudio_Preferences, &QAction::triggered, @@ -133,7 +133,6 @@ CMainFrame::CMainFrame() connect(m_ui->actionPresentation_Settings, &QAction::triggered, this, &CMainFrame::OnEditPresentationPreferences); connect(m_ui->menu_Edit, &QMenu::aboutToShow, [this]() { - // Enable/disable delete and duplicate QString type = g_StudioApp.getDuplicateType(); QString label = tr("Duplicate %1").arg(type); m_ui->action_Duplicate_Object->setText(label); @@ -143,11 +142,20 @@ CMainFrame::CMainFrame() label = tr("Delete %1").arg(type); m_ui->actionDelete->setText(label); m_ui->actionDelete->setEnabled(!type.isEmpty()); + + if (g_StudioApp.canUngroupSelectedObjects()) { + m_ui->actionGroup->setText(tr("Ungroup Objects")); + m_ui->actionGroup->setEnabled(true); + } else { + m_ui->actionGroup->setText(tr("Group Objects")); + m_ui->actionGroup->setEnabled(g_StudioApp.canGroupSelectedObjects()); + } }); connect(m_ui->menu_Edit, &QMenu::aboutToHide, [this]() { - // Enable delete and duplicate so hotkeys will work + // Enable potentially disabled items so hotkeys will work m_ui->action_Duplicate_Object->setEnabled(true); m_ui->actionDelete->setEnabled(true); + m_ui->actionGroup->setEnabled(true); }); // View Menu @@ -237,7 +245,6 @@ CMainFrame::CMainFrame() // Hide unimplemented menu items m_ui->actionRepeat->setVisible(false); - m_ui->actionGroup->setVisible(false); m_ui->actionParent->setVisible(false); m_ui->actionUnparent->setVisible(false); m_ui->actionFit_all->setVisible(false); @@ -709,6 +716,12 @@ void CMainFrame::onEditDelete() g_StudioApp.DeleteSelectedObject(); } +void CMainFrame::onEditGroup() +{ + if (!g_StudioApp.groupSelectedObjects()) + g_StudioApp.ungroupSelectedObjects(); +} + /** * Command handler for the File Open menu and toolbar options. * This will save the file, if the file has not been saved before this will diff --git a/src/Authoring/Studio/MainFrm.h b/src/Authoring/Studio/MainFrm.h index bf71bf1b..b660dc73 100644 --- a/src/Authoring/Studio/MainFrm.h +++ b/src/Authoring/Studio/MainFrm.h @@ -126,6 +126,7 @@ public: void OnUpdateEditPaste(); void OnEditDuplicate(); void onEditDelete(); + void onEditGroup(); void timerEvent(QTimerEvent *event) override; void showEvent(QShowEvent *event) override; diff --git a/src/Authoring/Studio/MainFrm.ui b/src/Authoring/Studio/MainFrm.ui index 04083c42..570262da 100644 --- a/src/Authoring/Studio/MainFrm.ui +++ b/src/Authoring/Studio/MainFrm.ui @@ -45,7 +45,7 @@ Project palette using Import functionality.</string> <x>0</x> <y>0</y> <width>1400</width> - <height>17</height> + <height>21</height> </rect> </property> <widget class="QMenu" name="menu_File"> @@ -885,7 +885,7 @@ Project palette using Import functionality.</string> </action> <action name="actionGroup"> <property name="enabled"> - <bool>false</bool> + <bool>true</bool> </property> <property name="text"> <string>Group</string> diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/ITimelineItemBinding.h b/src/Authoring/Studio/Palettes/Timeline/Bindings/ITimelineItemBinding.h index 2e804d85..0ee1a0de 100644 --- a/src/Authoring/Studio/Palettes/Timeline/Bindings/ITimelineItemBinding.h +++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/ITimelineItemBinding.h @@ -71,6 +71,8 @@ public: EUserTransaction_Delete, EUserTransaction_MakeComponent, EUserTransaction_EditComponent, + EUserTransaction_Group, + EUserTransaction_Ungroup, }; public: diff --git a/src/Authoring/Studio/Palettes/Timeline/Bindings/Qt3DSDMTimelineItemBinding.cpp b/src/Authoring/Studio/Palettes/Timeline/Bindings/Qt3DSDMTimelineItemBinding.cpp index 8a106d1a..5956c78d 100644 --- a/src/Authoring/Studio/Palettes/Timeline/Bindings/Qt3DSDMTimelineItemBinding.cpp +++ b/src/Authoring/Studio/Palettes/Timeline/Bindings/Qt3DSDMTimelineItemBinding.cpp @@ -576,6 +576,12 @@ bool Qt3DSDMTimelineItemBinding::IsValidTransaction(EUserTransaction inTransacti case EUserTransaction_EditComponent: return (GetObjectType() == OBJTYPE_COMPONENT); + case EUserTransaction_Group: + return g_StudioApp.canGroupSelectedObjects(); + + case EUserTransaction_Ungroup: + return g_StudioApp.canUngroupSelectedObjects(); + default: // not handled break; } @@ -602,6 +608,16 @@ inline void DoMakeComponent(CDoc &inDoc, const qt3dsdm::TInstanceHandleList &inI SCOPED_DOCUMENT_EDITOR(inDoc, QObject::tr("Make Component"))->MakeComponent(inInstances); } +inline void DoGroupObjects(CDoc &inDoc, const qt3dsdm::TInstanceHandleList &inInstances) +{ + g_StudioApp.groupSelectedObjects(); +} + +inline void DoUngroupObjects(CDoc &inDoc, const qt3dsdm::TInstanceHandleList &inInstances) +{ + g_StudioApp.ungroupSelectedObjects(); +} + void Qt3DSDMTimelineItemBinding::PerformTransaction(EUserTransaction inTransaction) { CDoc *theDoc = m_TransMgr->GetDoc(); @@ -638,7 +654,15 @@ void Qt3DSDMTimelineItemBinding::PerformTransaction(EUserTransaction inTransacti case EUserTransaction_MakeComponent: { theDispatch.FireOnAsynchronousCommand( std::bind(DoMakeComponent, std::ref(*theDoc), theInstances)); - } + } break; + case EUserTransaction_Group: { + theDispatch.FireOnAsynchronousCommand( + std::bind(DoGroupObjects, std::ref(*theDoc), theInstances)); + } break; + case EUserTransaction_Ungroup: { + theDispatch.FireOnAsynchronousCommand( + std::bind(DoUngroupObjects, std::ref(*theDoc), theInstances)); + } break; default: // not handled break; } diff --git a/src/Authoring/Studio/Palettes/TimelineGraphicsView/RowManager.cpp b/src/Authoring/Studio/Palettes/TimelineGraphicsView/RowManager.cpp index d78bed7f..6618e218 100644 --- a/src/Authoring/Studio/Palettes/TimelineGraphicsView/RowManager.cpp +++ b/src/Authoring/Studio/Palettes/TimelineGraphicsView/RowManager.cpp @@ -55,6 +55,11 @@ RowManager::RowManager(TimelineGraphicsScene *scene, QGraphicsLinearLayout *layo } +RowManager::~RowManager() +{ + finalizeRowDeletions(); +} + void RowManager::recreateRowsFromBinding(ITimelineItemBinding *rootBinding) { removeAllRows(); @@ -309,32 +314,51 @@ void RowManager::deleteRow(RowTree *row) if (row->parentRow()) row->parentRow()->removeChild(row); - deleteRowRecursive(row); + deleteRowRecursive(row, true); } } -void RowManager::deleteRowRecursive(RowTree *row) +void RowManager::finalizeRowDeletions() { - if (!row->childProps().empty()) { - const auto childProps = row->childProps(); - for (auto child : childProps) - deleteRowRecursive(child); - } + for (auto row : qAsConst(m_deletedRows)) { + // If the row has been reparented, no need to delete it + if (!row->parentRow()) + deleteRowRecursive(row, false); + } + m_deletedRows.clear(); +} - if (!row->childRows().empty()) { - const auto childRows = row->childRows(); - for (auto child : childRows) - deleteRowRecursive(child); - } +void RowManager::deleteRowRecursive(RowTree *row, bool deferChildRows) +{ + if (!row->childProps().empty()) { + const auto childProps = row->childProps(); + for (auto child : childProps) + deleteRowRecursive(child, false); + } + + if (!row->childRows().empty()) { + const auto childRows = row->childRows(); + for (auto child : childRows) { + if (deferChildRows) { + // Let's not delete child rows just yet, there may be a pending move for them. + // This happens when the same transaction contains parent deletion and child row + // move, such as ungrouping items. + child->setParentRow(nullptr); + m_deletedRows.append(child); + } else { + deleteRowRecursive(child, false); + } + } + } - m_selectedRows.removeAll(row); + m_selectedRows.removeAll(row); - m_scene->keyframeManager()->deleteKeyframes(row->rowTimeline(), false); + m_scene->keyframeManager()->deleteKeyframes(row->rowTimeline(), false); - if (row->getBinding()) + if (row->getBinding()) static_cast<Qt3DSDMTimelineItemBinding *>(row->getBinding())->setRowTree(nullptr); - delete row; + delete row; } RowTree *RowManager::selectedRow() const diff --git a/src/Authoring/Studio/Palettes/TimelineGraphicsView/RowManager.h b/src/Authoring/Studio/Palettes/TimelineGraphicsView/RowManager.h index 21b8417e..c7f98423 100644 --- a/src/Authoring/Studio/Palettes/TimelineGraphicsView/RowManager.h +++ b/src/Authoring/Studio/Palettes/TimelineGraphicsView/RowManager.h @@ -46,10 +46,12 @@ class RowManager public: RowManager(TimelineGraphicsScene *scene, QGraphicsLinearLayout *layoutLabels, QGraphicsLinearLayout *layoutTimeline); + ~RowManager(); void selectRow(RowTree *row, bool multiSelect = false); void setRowSelection(RowTree *row, bool selected); void deleteRow(RowTree *row); + void finalizeRowDeletions(); void clearSelection(); void updateFiltering(RowTree *rowTree = nullptr); void recreateRowsFromBinding(ITimelineItemBinding *rootBinding); @@ -72,7 +74,7 @@ public: private: int getLastChildIndex(RowTree *row, int index = -1); - void deleteRowRecursive(RowTree *row); + void deleteRowRecursive(RowTree *row, bool deferChildRows); void updateRowFilterRecursive(RowTree *row); void createRowsFromBindingRecursive(ITimelineItemBinding *binding, RowTree *parentRow = nullptr); @@ -82,6 +84,7 @@ private: TimelineGraphicsScene *m_scene; QGraphicsLinearLayout *m_layoutTree; QGraphicsLinearLayout *m_layoutTimeline; + QVector<RowTree *> m_deletedRows; }; #endif // ROWMANAGER_H diff --git a/src/Authoring/Studio/Palettes/TimelineGraphicsView/TimelineWidget.cpp b/src/Authoring/Studio/Palettes/TimelineGraphicsView/TimelineWidget.cpp index 2f71366d..44f837ac 100644 --- a/src/Authoring/Studio/Palettes/TimelineGraphicsView/TimelineWidget.cpp +++ b/src/Authoring/Studio/Palettes/TimelineGraphicsView/TimelineWidget.cpp @@ -517,6 +517,9 @@ void TimelineWidget::onAssetDeleted(qt3dsdm::Qt3DSDMInstanceHandle inInstance) m_graphicsScene->rowManager()->deleteRow(row); m_handlesMap.remove(inInstance); m_graphicsScene->expandMap().remove(inInstance); + // Ensure row deletions are finalized + if (!m_asyncUpdateTimer.isActive()) + m_asyncUpdateTimer.start(); } } @@ -574,8 +577,10 @@ void TimelineWidget::onAnimationDeleted(qt3dsdm::Qt3DSDMInstanceHandle parentIns if (propBinding && !propAnimated) { m_graphicsScene->rowManager()->deleteRow(propBinding->getRowTree()); - binding->RemovePropertyRow(property); + // Ensure row deletions are finalized + if (!m_asyncUpdateTimer.isActive()) + m_asyncUpdateTimer.start(); } } } @@ -732,6 +737,7 @@ void TimelineWidget::onAsyncUpdate() rowParent->addChildAt(row, indexIt.key()); } } + rowParent->updateExpandStatus(RowTree::ExpandState::Expanded, false); } } // Make sure selections on UI matches bindings @@ -810,6 +816,7 @@ void TimelineWidget::onAsyncUpdate() m_moveMap.clear(); m_actionChanges.clear(); m_keyframeChangesMap.clear(); + m_graphicsScene->rowManager()->finalizeRowDeletions(); } void TimelineWidget::onActionEvent(qt3dsdm::Qt3DSDMActionHandle inAction, diff --git a/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTree.cpp b/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTree.cpp index 8be884f8..8fa51365 100644 --- a/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTree.cpp +++ b/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTree.cpp @@ -417,6 +417,11 @@ void RowTree::setTimelineRow(RowTimeline *rowTimeline) m_rowTimeline = rowTimeline; } +void RowTree::setParentRow(RowTree *parent) +{ + m_parentRow = parent; +} + void RowTree::selectLabel() { m_labelItem.setEnabled(true); diff --git a/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTree.h b/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTree.h index 0b837f96..5e735335 100644 --- a/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTree.h +++ b/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTree.h @@ -85,7 +85,7 @@ public: QWidget *widget = nullptr) override; void setState(State state) override; void setTimelineRow(RowTimeline *rowTimeline); - void setParent(RowTree *parent); + void setParentRow(RowTree *parent); void addChild(RowTree *child); void addChildAt(RowTree *child, int index); void removeChild(RowTree *child); diff --git a/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTreeContextMenu.cpp b/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTreeContextMenu.cpp index 37e2c903..78ceb59d 100644 --- a/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTreeContextMenu.cpp +++ b/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTreeContextMenu.cpp @@ -62,6 +62,12 @@ void RowTreeContextMenu::initialize() connect(m_deleteAction, &QAction::triggered, this, &RowTreeContextMenu::deleteObject); addAction(m_deleteAction); + m_groupAction = new QAction(tr("Group Objects"), this); + m_groupAction->setShortcut(QKeySequence(Qt::ControlModifier | Qt::Key_G)); + m_groupAction->setShortcutVisibleInContextMenu(true); + connect(m_groupAction, &QAction::triggered, this, &RowTreeContextMenu::groupObjects); + addAction(m_groupAction); + addSeparator(); m_copyAction = new QAction(tr("Copy"), this); @@ -113,6 +119,11 @@ void RowTreeContextMenu::showEvent(QShowEvent *event) m_renameAction->setEnabled(canRenameObject()); m_duplicateAction->setEnabled(canDuplicateObject()); m_deleteAction->setEnabled(canDeleteObject()); + m_canGroupObjects = canGroupObjects(); + m_canUngroupObjects = canUngroupObjects(); + m_groupAction->setEnabled(m_canUngroupObjects || m_canGroupObjects); + if (m_canUngroupObjects) + m_groupAction->setText(tr("Ungroup Objects")); m_cutAction->setEnabled(canCutObject()); m_copyAction->setEnabled(canCopyObject()); @@ -152,12 +163,32 @@ bool RowTreeContextMenu::canDeleteObject() ITimelineItemBinding::EUserTransaction_Delete); } +bool RowTreeContextMenu::canGroupObjects() +{ + return m_TimelineItemBinding->IsValidTransaction( + ITimelineItemBinding::EUserTransaction_Group); +} + +bool RowTreeContextMenu::canUngroupObjects() +{ + return m_TimelineItemBinding->IsValidTransaction( + ITimelineItemBinding::EUserTransaction_Ungroup); +} + void RowTreeContextMenu::deleteObject() { m_TimelineItemBinding->PerformTransaction( ITimelineItemBinding::EUserTransaction_Delete); } +void RowTreeContextMenu::groupObjects() +{ + if (m_canGroupObjects) + m_TimelineItemBinding->PerformTransaction(ITimelineItemBinding::EUserTransaction_Group); + else if (m_canUngroupObjects) + m_TimelineItemBinding->PerformTransaction(ITimelineItemBinding::EUserTransaction_Ungroup); +} + bool RowTreeContextMenu::canInspectComponent() { return m_TimelineItemBinding->IsValidTransaction( diff --git a/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTreeContextMenu.h b/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTreeContextMenu.h index 11bcbe72..290257c8 100644 --- a/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTreeContextMenu.h +++ b/src/Authoring/Studio/Palettes/TimelineGraphicsView/ui/RowTreeContextMenu.h @@ -50,6 +50,7 @@ private Q_SLOTS: void renameObject(); void duplicateObject(); void deleteObject(); + void groupObjects(); void inspectComponent(); void makeComponent(); void copyObject(); @@ -62,6 +63,8 @@ private: bool canRenameObject(); bool canDuplicateObject(); bool canDeleteObject(); + bool canGroupObjects(); + bool canUngroupObjects(); bool canInspectComponent(); bool canMakeComponent(); bool canCopyObject(); @@ -70,14 +73,17 @@ private: RowTree *m_RowTree; ITimelineItemBinding *m_TimelineItemBinding; - QAction *m_renameAction; - QAction *m_duplicateAction; - QAction *m_deleteAction; - QAction *m_inspectAction; - QAction *m_makeAction; - QAction *m_copyPathAction; - QAction *m_cutAction; - QAction *m_copyAction; - QAction *m_pasteAction; + QAction *m_renameAction = nullptr; + QAction *m_duplicateAction = nullptr; + QAction *m_deleteAction = nullptr; + QAction *m_groupAction = nullptr; + QAction *m_inspectAction = nullptr; + QAction *m_makeAction = nullptr; + QAction *m_copyPathAction = nullptr; + QAction *m_cutAction = nullptr; + QAction *m_copyAction = nullptr; + QAction *m_pasteAction = nullptr; + bool m_canGroupObjects = false; + bool m_canUngroupObjects = false; }; #endif // ROWTREECONTEXTMENU_H |