summaryrefslogtreecommitdiffstats
path: root/src/Authoring/Studio/Palettes/Action/ActionView.cpp
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@qt.io>2017-10-06 11:49:09 +0000
committerOswald Buddenhagen <oswald.buddenhagen@qt.io>2017-10-06 16:58:43 +0200
commit07840524085bd1785b8f9142b03d942f678c5c51 (patch)
tree499c1674fdd1b3e0c07688d8e4e56748dfea2ca3 /src/Authoring/Studio/Palettes/Action/ActionView.cpp
Initial import
Diffstat (limited to 'src/Authoring/Studio/Palettes/Action/ActionView.cpp')
-rw-r--r--src/Authoring/Studio/Palettes/Action/ActionView.cpp848
1 files changed, 848 insertions, 0 deletions
diff --git a/src/Authoring/Studio/Palettes/Action/ActionView.cpp b/src/Authoring/Studio/Palettes/Action/ActionView.cpp
new file mode 100644
index 00000000..4aace20a
--- /dev/null
+++ b/src/Authoring/Studio/Palettes/Action/ActionView.cpp
@@ -0,0 +1,848 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "ActionView.h"
+#include "ActionContextMenu.h"
+#include "ActionModel.h"
+#include "CmdDataModelActionSetValue.h"
+#include "ClientDataModelBridge.h"
+#include "Core.h"
+#include "Dispatch.h"
+#include "Doc.h"
+#include "IDocumentEditor.h"
+#include "IDocumentReader.h"
+#include "IObjectReferenceHelper.h"
+#include "Literals.h"
+#include "ObjectListModel.h"
+#include "StudioUtils.h"
+#include "StudioApp.h"
+#include "StudioClipboard.h"
+#include "StudioObjectTypes.h"
+#include "StudioPreferences.h"
+#include "UICFileTools.h"
+#include "UICDMActionCore.h"
+#include "UICDMDataTypes.h"
+#include "UICDMSlides.h"
+
+#include <QCoreApplication>
+#include <QQmlContext>
+#include <QQmlEngine>
+#include <QTimer>
+
+ActionView::ActionView(QWidget *parent)
+ : QQuickWidget(parent)
+ , TabNavigable()
+ , m_actionsModel(new ActionModel(this))
+{
+ setResizeMode(QQuickWidget::SizeRootObjectToView);
+ QTimer::singleShot(0, this, &ActionView::initialize);
+
+ g_StudioApp.GetCore()->GetDispatch()->AddPresentationChangeListener(this);
+
+ connect(this, &ActionView::actionChanged, this, [this] {
+ if (!m_propertyModel)
+ m_propertyModel = new PropertyModel(this);
+
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+ if (actionInfo.m_Handler == L"Set Property") {
+ m_currentPropertyNameHandle = actionInfo.m_HandlerArgs.at(0);
+ m_currentPropertyValueHandle = actionInfo.m_HandlerArgs.at(1);
+ m_propertyModel->setAction(m_actionsModel->actionAt(m_currentActionIndex));
+ m_propertyModel->setNameHandle(m_currentPropertyNameHandle);
+ m_propertyModel->setValueHandle(m_currentPropertyValueHandle);
+
+ Q_EMIT propertyModelChanged();
+ }
+
+ });
+
+ m_actionChangedCompressionTimer.setInterval(500);
+ m_actionChangedCompressionTimer.setSingleShot(true);
+ connect(&m_actionChangedCompressionTimer, &QTimer::timeout, this, [this] {
+ updateHandlerArguments();
+ updateFiredEvent();
+ Q_EMIT actionChanged();
+ });
+}
+
+ActionView::~ActionView()
+{
+ m_connections.clear();
+}
+
+QSize ActionView::sizeHint() const
+{
+ return {500, 500};
+}
+
+void ActionView::setItem(const UICDM::CUICDMInstanceHandle &handle)
+{
+ m_objRefHelper = GetDoc()->GetDataModelObjectReferenceHelper();
+ m_itemHandle = handle;
+ m_actionsModel->setInstanceHandle(handle);
+ emitActionChanged();
+ Q_EMIT itemChanged();
+}
+
+QString ActionView::itemIcon() const
+{
+ if (!m_itemHandle.Valid())
+ return {};
+
+ auto info = m_objRefHelper->GetInfo(m_itemHandle);
+ return CStudioObjectTypes::GetNormalIconName(info.m_Type);
+}
+
+QString ActionView::itemText() const
+{
+ if (!m_itemHandle.Valid())
+ return tr("No Object Selected");
+
+ const auto data = m_objRefHelper->GetInfo(m_itemHandle);
+ return data.m_Name.toQString();
+}
+
+QColor ActionView::itemColor() const
+{
+ if (!m_itemHandle.Valid())
+ return Qt::white;
+
+ auto info = m_objRefHelper->GetInfo(m_itemHandle);
+ if (info.m_Master)
+ return CStudioPreferences::masterColor();
+ else
+ return CStudioPreferences::textColor();
+}
+
+QAbstractItemModel *ActionView::actionsModel() const
+{
+ return m_actionsModel;
+}
+
+QAbstractItemModel *ActionView::propertyModel() const
+{
+ return m_propertyModel;
+}
+
+QString ActionView::targetObjectName() const
+{
+ if (!GetDoc()->IsValid())
+ return {};
+
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+
+ const auto targetInstance =
+ GetBridge()->GetInstance(actionInfo.m_Owner, actionInfo.m_TargetObject);
+
+ QString targetName = targetInstance.Valid()
+ ? GetBridge()->GetName(targetInstance).toQString()
+ : tr("[Unknown Target]");
+
+ return targetName;
+}
+
+QString ActionView::triggerObjectName() const
+{
+ if (!GetDoc()->IsValid())
+ return {};
+
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+
+ const auto sourceInstance =
+ GetBridge()->GetInstance(actionInfo.m_Owner, actionInfo.m_TriggerObject);
+
+ QString sourceName = sourceInstance.Valid()
+ ? GetBridge()->GetName(sourceInstance).toQString()
+ : tr("[Unknown Source]");
+
+ return sourceName;
+}
+
+QString ActionView::eventName() const
+{
+ if (!GetDoc()->IsValid())
+ return {};
+
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+ const auto bridge = GetBridge();
+ const auto eventHandle = bridge->ResolveEvent(actionInfo);
+ const auto eventInfo = bridge->GetEventInfo(eventHandle);
+
+ const QString formalName = QString::fromWCharArray(eventInfo.m_FormalName.wide_str());
+ return formalName.isEmpty() ? tr("[Unknown Event]") : formalName;
+}
+
+QString ActionView::handlerName() const
+{
+ if (!GetDoc()->IsValid())
+ return {};
+
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+ const auto bridge = GetBridge();
+ const auto handlerHandle = bridge->ResolveHandler(actionInfo);
+
+ if (handlerHandle.Valid()) {
+ const auto handlerInfo = bridge->GetHandlerInfo(handlerHandle);
+ return QString::fromWCharArray(handlerInfo.m_FormalName.wide_str());
+ }
+
+ return tr("[Unknown Handler]");
+}
+
+QVariantList ActionView::handlerArguments() const
+{
+ return m_handlerArguments;
+}
+
+PropertyInfo ActionView::property() const
+{
+ if (!m_propertyModel)
+ return {};
+ return m_propertyModel->property(m_currentPropertyIndex);
+}
+
+void ActionView::setCurrentActionIndex(int index)
+{
+ if (index == m_currentActionIndex)
+ return;
+
+ m_currentActionIndex = index;
+ emitActionChanged();
+}
+
+void ActionView::setCurrentPropertyIndex(int handle, int index)
+{
+ if (index == m_currentPropertyIndex)
+ return;
+
+ m_currentPropertyValueHandle = 0;
+ m_currentPropertyNameHandle = handle;
+ for (int i = 0; i < m_handlerArguments.size(); ++i) {
+ auto handlerArg = m_handlerArguments[i].value<HandlerArgument>();
+ if (handlerArg.m_handle.GetHandleValue() == handle && i < m_handlerArguments.size() - 1) {
+ m_currentPropertyValueHandle = m_handlerArguments[i + 1].value<HandlerArgument>().m_handle;
+ if (m_propertyModel) {
+ m_propertyModel->setNameHandle(m_currentPropertyNameHandle);
+ m_propertyModel->setValueHandle(m_currentPropertyValueHandle);
+ }
+ }
+ }
+
+ m_currentPropertyIndex = index;
+
+ // set the property for the handler
+ if (m_propertyModel && handle != 0) {
+ UICDM::SValue sValue(QVariant(m_propertyModel->property(index).m_nameId));
+ UICDM::SValue oldValue;
+ GetDoc()->GetStudioSystem()->GetActionCore()->GetHandlerArgumentValue(handle, oldValue);
+
+ if (!Equals(oldValue, sValue)) {
+ CCmd *theCmd =
+ new CCmdDataModelActionSetArgumentValue(GetDoc(), handle, sValue);
+ g_StudioApp.GetCore()->ExecuteCommand(theCmd);
+ }
+ }
+
+ Q_EMIT propertyChanged();
+}
+
+void ActionView::addAction()
+{
+ if (m_itemHandle.Valid()) {
+ // Query data model bridge to see the applicable events and actions for this instance.
+ CClientDataModelBridge *theBridge = GetBridge();
+
+ std::wstring theEventName = theBridge->GetDefaultEvent(m_itemHandle);
+ std::wstring theHandlerName = theBridge->GetDefaultHandler(m_itemHandle);
+
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*GetDoc(), QObject::tr("Add Action"))
+ ->AddAction(GetDoc()->GetActiveSlide(), m_itemHandle, theEventName,
+ theHandlerName);
+ }
+}
+
+void ActionView::deleteAction(int index)
+{
+ const auto action = m_actionsModel->actionAt(index);
+ if (action.Valid()) {
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*GetDoc(), QObject::tr("Delete Action"))->DeleteAction(action);
+ }
+}
+
+QObject *ActionView::showTriggerObjectBrowser(const QPoint &point)
+{
+ if (!m_objectsModel) {
+ m_objectsModel = new ObjectListModel(g_StudioApp.GetCore(),
+ GetDoc()->GetActiveRootInstance(), this);
+ }
+
+ if (!m_triggerObjectBrowser)
+ m_triggerObjectBrowser = new ObjectBrowserView(this);
+
+ m_triggerObjectBrowser->setModel(m_objectsModel);
+
+ showBrowser(m_triggerObjectBrowser, point);
+
+ connect(m_triggerObjectBrowser, &ObjectBrowserView::selectionChanged,
+ this, [this] {
+ auto selectedItem = m_triggerObjectBrowser->selectedHandle();
+ setTriggerObject(m_objRefHelper->GetAssetRefValue(selectedItem,
+ m_itemHandle,
+ (CRelativePathTools::EPathType)(m_triggerObjectBrowser->pathType())));
+ });
+
+ return m_triggerObjectBrowser;
+}
+
+QObject *ActionView::showTargetObjectBrowser(const QPoint &point)
+{
+ if (!m_objectsModel) {
+ m_objectsModel = new ObjectListModel(g_StudioApp.GetCore(),
+ GetDoc()->GetActiveRootInstance(), this);
+ }
+
+ if (!m_targetObjectBrowser)
+ m_targetObjectBrowser = new ObjectBrowserView(this);
+
+ m_targetObjectBrowser->setModel(m_objectsModel);
+
+ showBrowser(m_targetObjectBrowser, point);
+
+ connect(m_targetObjectBrowser, &ObjectBrowserView::selectionChanged,
+ this, [this] {
+ auto selectedItem = m_targetObjectBrowser->selectedHandle();
+ setTargetObject(m_objRefHelper->GetAssetRefValue(selectedItem,
+ m_itemHandle,
+ (CRelativePathTools::EPathType)(m_targetObjectBrowser->pathType())));
+ resetFiredEvent();
+ });
+
+ return m_targetObjectBrowser;
+}
+
+void ActionView::showContextMenu(int x, int y)
+{
+ CActionContextMenu contextMenu(this);
+
+ connect(&contextMenu, &CActionContextMenu::copyAction, this, &ActionView::copyAction);
+ connect(&contextMenu, &CActionContextMenu::pasteAction, this, &ActionView::pasteAction);
+ connect(&contextMenu, &CActionContextMenu::cutAction, this, &ActionView::cutAction);
+ connect(&contextMenu, &CActionContextMenu::deleteAction, this, [this] {
+ deleteAction(m_currentActionIndex);
+ });
+
+ contextMenu.exec(mapToGlobal({x, y}));
+}
+
+QObject *ActionView::showEventBrowser(const QPoint &point)
+{
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+ const auto bridge = GetBridge();
+ const auto instanceHandle = bridge->GetInstance(actionInfo.m_Owner, actionInfo.m_TriggerObject);
+
+ if (!instanceHandle.Valid())
+ return nullptr;
+
+ if (!m_eventsModel) {
+ m_eventsModel = new EventsModel(this);
+ }
+
+ UICDM::TEventHandleList eventList;
+ bridge->GetEvents(instanceHandle, eventList);
+ m_eventsModel->setEventList(eventList);
+
+ if (!m_eventsBrowser)
+ m_eventsBrowser = new EventsBrowserView(this);
+
+ m_eventsBrowser->setModel(m_eventsModel);
+
+ showBrowser(m_eventsBrowser, point);
+
+ connect(m_eventsBrowser, &EventsBrowserView::selectionChanged,
+ this, [this] {
+ setEvent(UICDM::CUICDMEventHandle(m_eventsBrowser->selectedHandle()));
+ });
+
+ return m_eventsBrowser;
+}
+
+QObject *ActionView::showHandlerBrowser(const QPoint &point)
+{
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+ const auto bridge = GetBridge();
+ const auto instanceHandle = bridge->GetInstance(actionInfo.m_Owner, actionInfo.m_TargetObject);
+
+ if (!instanceHandle.Valid())
+ return nullptr;
+
+ if (!m_handlersModel) {
+ m_handlersModel = new EventsModel(this);
+ }
+
+ UICDM::THandlerHandleList handlerList;
+ bridge->GetHandlers(instanceHandle, handlerList);
+ m_handlersModel->setHandlerList(handlerList);
+
+ if (!m_handlerBrowser)
+ m_handlerBrowser = new EventsBrowserView(this);
+
+ m_handlerBrowser->setModel(m_handlersModel);
+
+ showBrowser(m_handlerBrowser, point);
+
+ connect(m_handlerBrowser, &EventsBrowserView::selectionChanged,
+ this, [this] {
+ setHandler(UICDM::CUICDMHandlerHandle(m_handlerBrowser->selectedHandle()));
+ });
+
+ return m_handlerBrowser;
+}
+
+QObject *ActionView::showEventBrowserForArgument(int handle, const QPoint &point)
+{
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+ const auto bridge = GetBridge();
+ const auto instanceHandle = bridge->GetInstance(actionInfo.m_Owner, actionInfo.m_TargetObject);
+
+ if (!instanceHandle.Valid())
+ return nullptr;
+
+ if (!m_fireEventsModel) {
+ m_fireEventsModel = new EventsModel(this);
+ }
+
+ UICDM::TEventHandleList eventList;
+ bridge->GetEvents(instanceHandle, eventList);
+ m_fireEventsModel->setEventList(eventList);
+
+ if (!m_fireEventsBrowser)
+ m_fireEventsBrowser = new EventsBrowserView(this);
+
+ m_fireEventsBrowser->setModel(m_fireEventsModel);
+
+ showBrowser(m_fireEventsBrowser, point);
+
+ connect(m_fireEventsBrowser, &EventsBrowserView::selectionChanged,
+ this, [this, handle] {
+ setArgumentValue(handle, UICDM::CUICDMEventHandle(m_fireEventsBrowser->selectedHandle()).GetHandleValue());
+ });
+
+ return m_fireEventsBrowser;
+}
+
+void ActionView::showBrowser(QQuickWidget *browser, const QPoint &point)
+{
+ QSize popupSize = CStudioPreferences::browserPopupSize();
+ browser->disconnect();
+ browser->resize(popupSize);
+ browser->move(point - QPoint(popupSize.width(), popupSize.height()));
+
+ // Show asynchronously to avoid flashing blank window on first show
+ QTimer::singleShot(0, this, [browser] {
+ browser->show();
+ browser->activateWindow();
+ browser->setFocus();
+ });
+}
+
+void ActionView::updateFiredEvent()
+{
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+ if (actionInfo.m_Handler != L"Fire Event") {
+ m_firedEvent = tr("[Unknown event]");
+ return;
+ }
+
+ const auto doc = GetDoc();
+ if (!doc->IsValid())
+ return;
+
+ const auto bridge = GetBridge();
+ const auto handlerHandle = bridge->ResolveHandler(actionInfo);
+ IActionCore *actionCore = doc->GetStudioSystem()->GetActionCore();
+
+ if (handlerHandle.Valid()) {
+ for (const auto &argHandle: actionInfo.m_HandlerArgs) {
+ const auto &argumentInfo = actionCore->GetHandlerArgumentInfo(argHandle);
+ DataModelDataType::Value theArgType(GetValueType(argumentInfo.m_Value));
+ SValue theArgValue(argumentInfo.m_Value);
+ if (argumentInfo.m_ArgType == HandlerArgumentType::Event) {
+ theArgType = DataModelDataType::String;
+ auto theEventHandle = get<qt3ds::QT3DSI32>(argumentInfo.m_Value);
+ theArgValue = SValue(std::make_shared<CDataStr>(
+ bridge->GetEventInfo(theEventHandle).m_Name.wide_str()));
+ m_firedEvent = theArgValue.toQVariant().toString();
+ Q_EMIT firedEventChanged();
+ }
+ }
+ }
+}
+
+void ActionView::updateFiredEventFromHandle(int handle)
+{
+ m_firedEvent = QString::fromWCharArray(GetBridge()->GetEventInfo(handle).m_FormalName.wide_str());
+ Q_EMIT firedEventChanged();
+}
+
+void ActionView::resetFiredEvent()
+{
+ m_firedEvent = tr("[Unknown Event]");
+ Q_EMIT firedEventChanged();
+}
+
+void ActionView::OnNewPresentation()
+{
+ // Register callback
+ UICDM::IStudioFullSystemSignalProvider *theSignalProvider =
+ g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()->GetFullSystemSignalProvider();
+ m_connections.push_back(theSignalProvider->ConnectActionCreated(
+ std::bind(&ActionView::OnActionAdded, this, std::placeholders::_1,
+ std::placeholders::_2, std::placeholders::_3)));
+ m_connections.push_back(theSignalProvider->ConnectActionDeleted(
+ std::bind(&ActionView::OnActionDeleted, this, std::placeholders::_1,
+ std::placeholders::_2, std::placeholders::_3)));
+ m_connections.push_back(theSignalProvider->ConnectTriggerObjectSet(
+ std::bind(&ActionView::OnActionModified, this, std::placeholders::_1)));
+ m_connections.push_back(theSignalProvider->ConnectTargetObjectSet(
+ std::bind(&ActionView::OnActionModified, this, std::placeholders::_1)));
+ m_connections.push_back(theSignalProvider->ConnectEventSet(
+ std::bind(&ActionView::OnActionModified, this, std::placeholders::_1)));
+ m_connections.push_back(theSignalProvider->ConnectHandlerSet(
+ std::bind(&ActionView::OnActionModified, this, std::placeholders::_1)));
+ m_connections.push_back(theSignalProvider->ConnectHandlerArgumentValueSet(
+ std::bind(&ActionView::OnHandlerArgumentModified, this, std::placeholders::_1)));
+ m_connections.push_back(theSignalProvider->ConnectInstancePropertyValue(
+ std::bind(&ActionView::OnInstancePropertyValueChanged, this, std::placeholders::_1,
+ std::placeholders::_2)));
+ CDispatch *theDispatch = g_StudioApp.GetCore()->GetDispatch();
+ m_connections.push_back(theDispatch->ConnectSelectionChange(
+ std::bind(&ActionView::OnSelectionSet, this,
+ std::placeholders::_1)));
+}
+
+void ActionView::OnSelectionSet(Q3DStudio::SSelectedValue inSelectable)
+{
+ UICDM::CUICDMInstanceHandle theInstance;
+ std::vector<UICDM::CUICDMInstanceHandle> instances;
+
+ switch (inSelectable.getType()) {
+ case Q3DStudio::SelectedValueTypes::Instance:
+ theInstance = inSelectable.getData<UICDM::CUICDMInstanceHandle>();
+ break;
+ case Q3DStudio::SelectedValueTypes::MultipleInstances:
+ instances = inSelectable.getData<std::vector<UICDM::CUICDMInstanceHandle>>();
+ // handling only if we have one selected element.
+ if (instances.size() == 1)
+ theInstance = instances[0];
+ break;
+ case Q3DStudio::SelectedValueTypes::Slide: {
+ UICDM::CUICDMSlideHandle theSlideHandle =
+ inSelectable.getData<Q3DStudio::SSlideInstanceWrapper>().m_Slide;
+ // Get the owning component instance
+ CClientDataModelBridge *theBridge = GetBridge();
+ UICDM::SLong4 theComponentGuid = theBridge->GetComponentGuid(theSlideHandle);
+ Q_ASSERT(GuidValid(theComponentGuid));
+ theInstance = theBridge->GetInstanceByGUID(theComponentGuid);
+ Q_ASSERT(theInstance.Valid());
+ } break;
+ };
+
+ setItem(theInstance);
+}
+
+void ActionView::OnActionAdded(UICDM::CUICDMActionHandle inAction, UICDM::CUICDMSlideHandle inSlide, UICDM::CUICDMInstanceHandle inOwner)
+{
+ CDoc *theDoc = GetDoc();
+ UICDM::CStudioSystem *theStudioSystem = theDoc->GetStudioSystem();
+
+ UICDM::CUICDMSlideHandle theCurrentSlide = theDoc->GetActiveSlide();
+ UICDM::CUICDMSlideHandle theMasterSlideOfAction =
+ theStudioSystem->GetSlideSystem()->GetMasterSlide(inSlide);
+ UICDM::CUICDMSlideHandle theMasterOfCurrentSlide =
+ theStudioSystem->GetSlideSystem()->GetMasterSlide(theCurrentSlide);
+
+ if (inOwner == m_itemHandle && // the action is added to current viewed instance
+ (theCurrentSlide == inSlide || // and is added to the current viewed slide
+ (theMasterSlideOfAction == inSlide
+ && theMasterOfCurrentSlide == theMasterSlideOfAction))) // or it is added to the master of
+ // the current viewed slide
+ {
+ m_actionsModel->addAction(inAction);
+// KDAB_TODO SortActions();
+ }
+}
+
+void ActionView::OnActionDeleted(UICDM::CUICDMActionHandle inAction, UICDM::CUICDMSlideHandle inSlide, UICDM::CUICDMInstanceHandle inOwner)
+{
+ Q_UNUSED(inSlide);
+ Q_UNUSED(inOwner);
+ m_actionsModel->removeAction(inAction);
+}
+
+void ActionView::OnActionModified(UICDM::CUICDMActionHandle inAction)
+{
+ if (GetDoc()->GetStudioSystem()->GetActionCore()->HandleValid(inAction)) {
+ m_actionsModel->updateAction(inAction);
+ emitActionChanged();
+ }
+}
+
+void ActionView::OnHandlerArgumentModified(UICDM::CUICDMHandlerArgHandle inHandlerArgument)
+{
+ emitActionChanged();
+}
+
+void ActionView::OnInstancePropertyValueChanged(UICDM::CUICDMInstanceHandle inInstance, UICDM::CUICDMPropertyHandle inProperty)
+{
+ emitActionChanged();
+}
+
+void ActionView::copyAction()
+{
+ auto theTempAPFile =
+ GetDoc()->GetDocumentReader().CopyAction(m_actionsModel->actionAt(m_currentActionIndex),
+ GetDoc()->GetActiveSlide());
+ CUICFile theFile(theTempAPFile);
+ CStudioClipboard::CopyActionToClipboard(theFile);
+}
+
+void ActionView::cutAction()
+{
+ copyAction();
+ auto action = m_actionsModel->actionAt(m_currentActionIndex);
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*GetDoc(), QObject::tr("Cut Action"))->DeleteAction(action);
+}
+
+void ActionView::pasteAction()
+{
+ CUICFile theTempAPFile = CStudioClipboard::GetActionFromClipboard();
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*GetDoc(), QObject::tr("Paste Action"))
+ ->PasteAction(theTempAPFile.GetAbsolutePath(), m_itemHandle);
+}
+
+void ActionView::setTriggerObject(const UICDM::SObjectRefType &object)
+{
+ auto action = m_actionsModel->actionAt(m_currentActionIndex);
+ if (!action.Valid())
+ return;
+
+ auto core = g_StudioApp.GetCore();
+ auto theBridge = GetBridge();
+
+ auto theCmd = new CCmdDataModelActionSetTriggerObject(GetDoc(), action, object);
+ const SActionInfo &theActionInfo = GetDoc()->GetStudioSystem()->GetActionCore()->GetActionInfo(action);
+
+ CUICDMInstanceHandle theBaseInstance = theActionInfo.m_Owner;
+ CUICDMInstanceHandle theObjectInstance = theBridge->GetInstance(theBaseInstance, object);
+ CUICDMInstanceHandle theOldInstance = theBridge->GetInstance(theBaseInstance, theActionInfo.m_TargetObject);
+ // old instance and object instance could be the same, for example if user changes the type
+ // from Absolute to Path. In this case we don't need to reset handler or event.
+ if (theOldInstance != theObjectInstance)
+ theCmd->ResetEvent(
+ theBridge->GetDefaultEvent(theObjectInstance, theActionInfo.m_Event));
+
+ core->ExecuteCommand(theCmd);
+ emitActionChanged();
+}
+
+void ActionView::setTargetObject(const UICDM::SObjectRefType &object)
+{
+ auto action = m_actionsModel->actionAt(m_currentActionIndex);
+ if (!action.Valid())
+ return;
+
+ auto core = g_StudioApp.GetCore();
+ auto doc = GetDoc();
+ auto theBridge = GetBridge();
+
+ auto theCmd = new CCmdDataModelActionSetTargetObject(doc, action, object);
+ const SActionInfo &theActionInfo = doc->GetStudioSystem()->GetActionCore()->GetActionInfo(action);
+
+ CUICDMInstanceHandle theBaseInstance = theActionInfo.m_Owner;
+ CUICDMInstanceHandle theObjectInstance = theBridge->GetInstance(theBaseInstance, object);
+ CUICDMInstanceHandle theOldInstance = theBridge->GetInstance(theBaseInstance, theActionInfo.m_TargetObject);
+ // old instance and object instance could be the same, for example if user changes the type
+ // from Absolute to Path. In this case we don't need to reset handler or event.
+ if (theOldInstance != theObjectInstance)
+ theCmd->ResetHandler(
+ theBridge->GetDefaultHandler(theObjectInstance, theActionInfo.m_Handler));
+
+ core->ExecuteCommand(theCmd);
+ emitActionChanged();
+}
+
+void ActionView::setEvent(const CUICDMEventHandle &event)
+{
+ if (!event.Valid())
+ return;
+
+ auto doc = GetDoc();
+ const auto action = m_actionsModel->actionAt(m_currentActionIndex);
+ CCmd *theCmd = new CCmdDataModelActionSetEvent(doc, action,
+ doc->GetStudioSystem()
+ ->GetActionMetaData()
+ ->GetEventInfo(event)
+ ->m_Name.wide_str());
+ g_StudioApp.GetCore()->ExecuteCommand(theCmd);
+}
+
+void ActionView::setHandler(const CUICDMHandlerHandle &handler)
+{
+ if (!handler.Valid())
+ return;
+
+ auto doc = GetDoc();
+ const auto action = m_actionsModel->actionAt(m_currentActionIndex);
+ wstring handlerName(doc->GetStudioSystem()->GetActionMetaData()->GetHandlerInfo(handler)
+ ->m_Name.wide_str());
+ CCmdDataModelActionSetHandler *theCmd =
+ new CCmdDataModelActionSetHandler(doc, action, handlerName);
+ theCmd->ResetHandler(handlerName); // reset the handler args
+
+ g_StudioApp.GetCore()->ExecuteCommand(theCmd);
+}
+
+QVariant ActionView::handlerArgumentValue(int handle) const
+{
+ UICDM::SValue value;
+ GetDoc()->GetStudioSystem()->GetActionCore()->GetHandlerArgumentValue(handle, value);
+ return value.toQVariant();
+}
+
+void ActionView::updateHandlerArguments()
+{
+ m_currentPropertyValueHandle = 0;
+ m_currentPropertyNameHandle = 0;
+ m_handlerArguments.clear();
+ const auto doc = GetDoc();
+ if (!doc->IsValid())
+ return;
+
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+ const auto bridge = GetBridge();
+ const auto handlerHandle = bridge->ResolveHandler(actionInfo);
+ IActionCore *actionCore = doc->GetStudioSystem()->GetActionCore();
+
+ if (handlerHandle.Valid()) {
+ auto newMetaData = doc->GetStudioSystem()->GetActionMetaData();
+
+ for (const auto &argHandle: actionInfo.m_HandlerArgs) {
+ const auto &argumentInfo = actionCore->GetHandlerArgumentInfo(argHandle);
+ Option<SMetaDataHandlerArgumentInfo> argMetaData(
+ newMetaData->FindHandlerArgumentByName(handlerHandle, argumentInfo.m_Name));
+
+
+ HandlerArgument argument;
+ argument.m_handle = argHandle;
+ argument.m_type = argMetaData->m_ArgType;
+ argument.m_name = QString::fromWCharArray(argumentInfo.m_Name.wide_str());
+ argument.m_value = argumentInfo.m_Value.toQVariant();
+ argument.m_completeType = argMetaData->m_CompleteType;
+ m_handlerArguments.append(QVariant::fromValue(argument));
+ }
+ }
+}
+
+void ActionView::emitActionChanged()
+{
+ m_actionChangedCompressionTimer.start();
+}
+
+void ActionView::setArgumentValue(int handle, const QVariant &value)
+{
+ if (handle == 0)
+ return;
+
+ UICDM::SValue sValue(value);
+ UICDM::SValue oldValue;
+ GetDoc()->GetStudioSystem()->GetActionCore()->GetHandlerArgumentValue(handle, oldValue);
+
+ if (!Equals(oldValue, sValue)) {
+ CCmd *theCmd =
+ new CCmdDataModelActionSetArgumentValue(GetDoc(), handle, sValue);
+ g_StudioApp.GetCore()->ExecuteCommand(theCmd);
+ }
+
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+ if (actionInfo.m_Handler == L"Fire Event") {
+ if (value.toInt())
+ updateFiredEventFromHandle(value.toInt());
+ }
+}
+
+CDoc *ActionView::GetDoc()
+{
+ return g_StudioApp.GetCore()->GetDoc();
+}
+
+CClientDataModelBridge *ActionView::GetBridge()
+{
+ return GetDoc()->GetStudioSystem()->GetClientDataModelBridge();
+}
+
+void ActionView::initialize()
+{
+ CStudioPreferences::setQmlContextProperties(rootContext());
+ rootContext()->setContextProperty("_actionView"_L1, this);
+ rootContext()->setContextProperty("_resDir"_L1, resourceImageUrl());
+ rootContext()->setContextProperty("_tabOrderHandler"_L1, tabOrderHandler());
+ qmlRegisterUncreatableType<UICDM::HandlerArgumentType>("Qt3DStudio", 1, 0, "HandlerArgumentType",
+ "HandlerArgumentType is an enum container"_L1);
+ qmlRegisterUncreatableType<UICDM::DataModelDataType>("Qt3DStudio", 1, 0, "DataModelDataType",
+ "DataModelDataType is an enum container"_L1);
+ qmlRegisterUncreatableType<UICDM::AdditionalMetaDataType>("Qt3DStudio", 1, 0, "AdditionalMetaDataType",
+ "AdditionalMetaDataType is an enum container"_L1);
+ qmlRegisterUncreatableType<PropertyInfo>("Qt3DStudio", 1, 0, "PropertyInfo",
+ "PropertyInfo is anot creatable in QML"_L1);
+ qmlRegisterUncreatableType<UICDM::CompleteMetaDataType>("Qt3DStudio", 1, 0, "CompleteMetaDataType",
+ "CompleteMetaDataType is an enum container"_L1);
+ engine()->addImportPath(qmlImportPath());
+ setSource(QUrl("qrc:/Studio/Palettes/Action/ActionView.qml"_L1));
+}
+
+QStringList ActionView::slideNames()
+{
+ std::list<Q3DStudio::CString> outSlideNames;
+ QStringList slideNames;
+ CClientDataModelBridge *theBridge = GetBridge();
+ const auto action = m_actionsModel->actionAt(m_currentActionIndex);
+
+ theBridge->GetSlideNamesOfAction(action, outSlideNames);
+
+ for (auto slideName : outSlideNames) {
+ slideNames.append(slideName.toQString());
+ }
+
+ return slideNames;
+}
+
+int ActionView::slideNameToIndex(const QString &name)
+{
+ const auto slides = slideNames(); // KDAB_TODO cache it
+ return slides.indexOf(name);
+}