summaryrefslogtreecommitdiffstats
path: root/src/Authoring/Qt3DStudio/Palettes/Action/ActionView.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Authoring/Qt3DStudio/Palettes/Action/ActionView.cpp')
-rw-r--r--src/Authoring/Qt3DStudio/Palettes/Action/ActionView.cpp1203
1 files changed, 1203 insertions, 0 deletions
diff --git a/src/Authoring/Qt3DStudio/Palettes/Action/ActionView.cpp b/src/Authoring/Qt3DStudio/Palettes/Action/ActionView.cpp
new file mode 100644
index 00000000..41d67789
--- /dev/null
+++ b/src/Authoring/Qt3DStudio/Palettes/Action/ActionView.cpp
@@ -0,0 +1,1203 @@
+/****************************************************************************
+**
+** 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 "Dialogs.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 "Qt3DSFileTools.h"
+#include "Qt3DSDMActionCore.h"
+#include "Qt3DSDMDataTypes.h"
+#include "Qt3DSDMSlides.h"
+
+#include <QtCore/qcoreapplication.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlengine.h>
+#include <QtCore/qtimer.h>
+#include <QtWidgets/qdesktopwidget.h>
+
+ActionView::ActionView(const QSize &preferredSize, QWidget *parent)
+ : QQuickWidget(parent)
+ , TabNavigable()
+ , m_actionsModel(new ActionModel(this))
+ , m_preferredSize(preferredSize)
+{
+ setResizeMode(QQuickWidget::SizeRootObjectToView);
+ QTimer::singleShot(0, this, &ActionView::initialize);
+
+ g_StudioApp.GetCore()->GetDispatch()->AddPresentationChangeListener(this);
+
+ connect(this, &ActionView::actionChanged, this, [this] {
+ if (!m_itemHandle.Valid())
+ return;
+
+ if (!m_propertyModel)
+ m_propertyModel = new PropertyModel(this);
+
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+ if (actionInfo.m_Handler == L"Set Property") {
+ setPropertyValueInvalid(true);
+ 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);
+ m_currentPropertyIndex = m_propertyModel->defaultPropertyIndex();
+ Q_EMIT propertyChanged();
+ Q_EMIT propertyModelChanged();
+ setPropertyValueInvalid(false);
+ }
+ });
+
+ m_actionChangedCompressionTimer.setInterval(20);
+ m_actionChangedCompressionTimer.setSingleShot(true);
+ connect(&m_actionChangedCompressionTimer, &QTimer::timeout, this, [this] {
+ updateHandlerArguments();
+ updateFiredEvent();
+ Q_EMIT actionChanged();
+ });
+
+ QString ctrlKey(QStringLiteral("Ctrl+"));
+ QString shiftKey(QStringLiteral("Shift+"));
+#ifdef Q_OS_MACOS
+ ctrlKey = "⌘";
+ shiftKey = "⇧";
+#endif
+
+ // These actions will be passed to the context menu. Some of them need to me members, as we
+ // have to change their enabled state based on selection and previous actions.
+ QAction *action = new QAction(tr("New Action\t%1A").arg(shiftKey));
+ action->setShortcut(QKeySequence(Qt::SHIFT + Qt::Key_A));
+ connect(action, &QAction::triggered, this, &ActionView::addAction);
+ QQuickWidget::addAction(action);
+
+ m_actionCopy = new QAction(tr("Copy Action\t%1C").arg(ctrlKey));
+ connect(m_actionCopy, &QAction::triggered, this, &ActionView::copyAction);
+ QQuickWidget::addAction(m_actionCopy);
+
+ m_actionPaste = new QAction(tr("Paste Action\t%1V").arg(ctrlKey));
+ connect(m_actionPaste, &QAction::triggered, this, &ActionView::pasteAction);
+ QQuickWidget::addAction(m_actionPaste);
+
+ m_actionCut = new QAction(tr("Cut Action\t%1X").arg(ctrlKey));
+ connect(m_actionCut, &QAction::triggered, this, &ActionView::cutAction);
+ QQuickWidget::addAction(m_actionCut);
+
+ m_actionDel = new QAction(tr("Delete Action\tDel"));
+ connect(m_actionDel, &QAction::triggered, [=](){ deleteAction(m_currentActionIndex); });
+ QQuickWidget::addAction(m_actionDel);
+}
+
+ActionView::~ActionView()
+{
+}
+
+QSize ActionView::sizeHint() const
+{
+ return m_preferredSize;
+}
+
+void ActionView::focusInEvent(QFocusEvent *event)
+{
+ updateActionStates();
+ QQuickWidget::focusInEvent(event);
+}
+
+void ActionView::mousePressEvent(QMouseEvent *event)
+{
+ g_StudioApp.setLastActiveView(this);
+ QQuickWidget::mousePressEvent(event);
+}
+
+bool ActionView::event(QEvent *event)
+{
+ if (event->type() == QEvent::ShortcutOverride) {
+ QKeyEvent *ke = static_cast<QKeyEvent *>(event);
+ if (m_currentActionIndex >= 0 && (ke->key() == Qt::Key_Delete
+ || (ke->modifiers() == Qt::ControlModifier
+ && (ke->key() == Qt::Key_C || ke->key() == Qt::Key_V
+ || ke->key() == Qt::Key_X)))) {
+ auto focusItem = quickWindow()->activeFocusItem();
+ if (focusItem && (focusItem->objectName() == QStringLiteral("actionListDelegate")
+ || focusItem->objectName() == QStringLiteral("focusEater"))) {
+ if (ke->key() == Qt::Key_Delete) {
+ if (m_actionDel->isEnabled())
+ deleteAction(m_currentActionIndex);
+ } else if (ke->modifiers() == Qt::ControlModifier) {
+ if (ke->key() == Qt::Key_C) {
+ if (m_actionCopy->isEnabled())
+ copyAction();
+ } else if (ke->key() == Qt::Key_V) {
+ if (m_actionPaste->isEnabled())
+ pasteAction();
+ } else if (ke->key() == Qt::Key_X) {
+ if (m_actionCut->isEnabled())
+ cutAction();
+ }
+ }
+ event->accept();
+ return true;
+ }
+ }
+ }
+ return QQuickWidget::event(event);
+}
+
+void ActionView::setItem(const qt3dsdm::Qt3DSDMInstanceHandle &handle)
+{
+ if (!m_activeBrowser.isNull() && m_activeBrowser->isVisible()) {
+ m_activeBrowser->close();
+ m_activeBrowser.clear();
+ }
+
+ m_objRefHelper = GetDoc()->GetDataModelObjectReferenceHelper();
+ m_itemHandle = handle;
+ m_actionsModel->setInstanceHandle(handle);
+ if (m_itemHandle.Valid() != m_hasItem) {
+ m_hasItem = m_itemHandle.Valid();
+ Q_EMIT hasItemChanged();
+ }
+ emitActionChanged();
+ Q_EMIT itemChanged();
+ Q_EMIT itemTextChanged();
+}
+
+QString ActionView::itemIcon() const
+{
+ if (!m_itemHandle.Valid())
+ return QString();
+
+ 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() || !m_itemHandle.Valid())
+ return QString();
+
+ 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() || !m_itemHandle.Valid())
+ return QString();
+
+ 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() || !m_itemHandle.Valid())
+ return QString();
+
+ 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() || !m_itemHandle.Valid())
+ return QString();
+
+ 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);
+}
+
+bool ActionView::isPropertyValueInvalid() const
+{
+ return m_propertyValueInvalid;
+}
+
+void ActionView::setCurrentActionIndex(int index)
+{
+ if (index == m_currentActionIndex)
+ return;
+
+ m_currentActionIndex = index;
+ emitActionChanged();
+
+ updateActionStates();
+}
+
+void ActionView::setCurrentPropertyIndex(int handle, int index)
+{
+ setPropertyValueInvalid(true);
+ // Make sure propertymodel name & value handles are always up-to-date,
+ // even when index is same as before
+ 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);
+ }
+ }
+ }
+
+ if (index == m_currentPropertyIndex)
+ return;
+
+ m_currentPropertyIndex = index;
+
+ // set the property for the handler
+ if (m_propertyModel && handle != 0) {
+ qt3dsdm::SValue sValue(QVariant(m_propertyModel->property(index).m_nameId));
+ qt3dsdm::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();
+ // Clear the value invalid flag asynchronously as the value doesn't actually change until
+ // backend tells us it does
+ QTimer::singleShot(0, this, &ActionView::clearPropertyValueInvalid);
+}
+
+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);
+ }
+ updateActionStates();
+}
+
+void ActionView::deleteAction(int index)
+{
+ if (!m_itemHandle.Valid())
+ return;
+
+ const auto action = m_actionsModel->actionAt(index);
+ if (action.Valid()) {
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*GetDoc(),
+ QObject::tr("Delete Action"))->DeleteAction(action);
+ emitActionChanged();
+ }
+ updateActionStates();
+}
+
+QObject *ActionView::showTriggerObjectBrowser(const QPoint &point)
+{
+ if (!m_itemHandle.Valid())
+ return nullptr;
+
+ if (!m_objectsModel) {
+ m_objectsModel = new ObjectListModel(g_StudioApp.GetCore(),
+ GetDoc()->GetSceneInstance(), this);
+ }
+
+ if (!m_triggerObjectBrowser)
+ m_triggerObjectBrowser = new ObjectBrowserView(this);
+
+ m_triggerObjectBrowser->setModel(m_objectsModel);
+
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+ const auto instanceHandle = GetBridge()->GetInstance(actionInfo.m_Owner,
+ actionInfo.m_TriggerObject);
+ m_triggerObjectBrowser->disconnect();
+ m_triggerObjectBrowser->selectAndExpand(instanceHandle, actionInfo.m_Owner);
+ CDialogs::showWidgetBrowser(this, m_triggerObjectBrowser, point);
+ m_activeBrowser = m_triggerObjectBrowser;
+
+ connect(m_triggerObjectBrowser, &ObjectBrowserView::selectionChanged,
+ this, &ActionView::OnTriggerSelectionChanged);
+ // update also pathtype in the trigger object when changed from UI
+ connect(m_triggerObjectBrowser, &ObjectBrowserView::pathTypeChanged,
+ this, &ActionView::OnTriggerSelectionChanged);
+
+ return m_triggerObjectBrowser;
+}
+
+QObject *ActionView::showTargetObjectBrowser(const QPoint &point)
+{
+ if (!m_itemHandle.Valid())
+ return nullptr;
+
+ if (!m_objectsModel) {
+ m_objectsModel = new ObjectListModel(g_StudioApp.GetCore(),
+ GetDoc()->GetSceneInstance(), this);
+ }
+
+ if (!m_targetObjectBrowser)
+ m_targetObjectBrowser = new ObjectBrowserView(this);
+
+ m_targetObjectBrowser->setModel(m_objectsModel);
+
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+ const auto instanceHandle = GetBridge()->GetInstance(actionInfo.m_Owner,
+ actionInfo.m_TargetObject);
+ m_targetObjectBrowser->disconnect();
+ m_targetObjectBrowser->selectAndExpand(instanceHandle, actionInfo.m_Owner);
+ CDialogs::showWidgetBrowser(this, m_targetObjectBrowser, point);
+ m_activeBrowser = m_targetObjectBrowser;
+
+ connect(m_targetObjectBrowser, &ObjectBrowserView::selectionChanged,
+ this, &ActionView::OnTargetSelectionChanged);
+ // update also pathtype in the target object when changed from UI
+ connect(m_targetObjectBrowser, &ObjectBrowserView::pathTypeChanged,
+ this, &ActionView::OnTargetSelectionChanged);
+
+ return m_targetObjectBrowser;
+}
+
+void ActionView::OnTargetSelectionChanged()
+{
+ auto selectedItem = m_targetObjectBrowser->selectedHandle();
+ setTargetObject(m_objRefHelper->GetAssetRefValue(
+ selectedItem, m_itemHandle,
+ (CRelativePathTools::EPathType)(m_targetObjectBrowser->pathType())));
+ resetFiredEvent();
+}
+
+void ActionView::OnTriggerSelectionChanged()
+{
+ auto selectedItem = m_triggerObjectBrowser->selectedHandle();
+ setTriggerObject(m_objRefHelper->GetAssetRefValue(
+ selectedItem, m_itemHandle,
+ (CRelativePathTools::EPathType)(m_triggerObjectBrowser->pathType())));
+ resetFiredEvent();
+}
+
+void ActionView::showContextMenu(int x, int y)
+{
+ updateActionStates();
+ CActionContextMenu contextMenu(QQuickWidget::actions(), this);
+ contextMenu.exec(mapToGlobal({x, y}));
+}
+
+QObject *ActionView::showEventBrowser(const QPoint &point)
+{
+ if (!m_itemHandle.Valid())
+ return nullptr;
+
+ 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);
+
+ qt3dsdm::TEventHandleList eventList;
+ bridge->GetEvents(instanceHandle, eventList);
+ m_eventsModel->setEventList(eventList);
+
+ if (!m_eventsBrowser)
+ m_eventsBrowser = new EventsBrowserView(this);
+
+ m_eventsBrowser->setModel(m_eventsModel);
+
+ m_eventsBrowser->disconnect();
+ m_eventsBrowser->selectAndExpand(QString::fromStdWString(actionInfo.m_Event));
+ CDialogs::showWidgetBrowser(this, m_eventsBrowser, point);
+ m_activeBrowser = m_eventsBrowser;
+
+ connect(m_eventsBrowser, &EventsBrowserView::selectionChanged,
+ this, [this] {
+ if (m_eventsBrowser->canCommit())
+ setEvent(qt3dsdm::Qt3DSDMEventHandle(m_eventsBrowser->selectedHandle()));
+ });
+
+ return m_eventsBrowser;
+}
+
+QObject *ActionView::showHandlerBrowser(const QPoint &point)
+{
+ if (!m_itemHandle.Valid())
+ return nullptr;
+
+ 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);
+
+ qt3dsdm::THandlerHandleList handlerList;
+ bridge->GetHandlers(instanceHandle, handlerList);
+ m_handlersModel->setHandlerList(handlerList);
+
+ if (!m_handlerBrowser)
+ m_handlerBrowser = new EventsBrowserView(this);
+
+ m_handlerBrowser->setModel(m_handlersModel);
+
+ m_handlerBrowser->disconnect();
+ m_handlerBrowser->selectAndExpand(QString::fromStdWString(actionInfo.m_Handler));
+ CDialogs::showWidgetBrowser(this, m_handlerBrowser, point);
+ m_activeBrowser = m_handlerBrowser;
+
+ connect(m_handlerBrowser, &EventsBrowserView::selectionChanged,
+ this, [this] {
+ if (m_handlerBrowser->canCommit())
+ setHandler(qt3dsdm::Qt3DSDMHandlerHandle(m_handlerBrowser->selectedHandle()));
+ });
+
+ return m_handlerBrowser;
+}
+
+QObject *ActionView::showEventBrowserForArgument(int handle, const QPoint &point)
+{
+ if (!m_itemHandle.Valid())
+ return nullptr;
+
+ 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);
+
+ qt3dsdm::TEventHandleList eventList;
+ bridge->GetEvents(instanceHandle, eventList);
+ m_fireEventsModel->setEventList(eventList);
+
+ if (!m_fireEventsBrowser)
+ m_fireEventsBrowser = new EventsBrowserView(this);
+
+ m_fireEventsBrowser->setModel(m_fireEventsModel);
+ m_fireEventsBrowser->setHandle(handle);
+
+ qt3dsdm::SValue oldValue;
+ GetDoc()->GetStudioSystem()->GetActionCore()->GetHandlerArgumentValue(handle, oldValue);
+
+ QString eventName;
+ for (Qt3DSDMEventHandle eventHandle : eventList) {
+ if (oldValue == eventHandle.GetHandleValue()) {
+ qt3dsdm::SEventInfo eventInfo = bridge->GetEventInfo(eventHandle);
+ eventName = QString::fromWCharArray(eventInfo.m_FormalName.wide_str());
+ if (eventName.isEmpty())
+ eventName = QString::fromWCharArray(eventInfo.m_Name.wide_str());
+ }
+ }
+ m_fireEventsBrowser->disconnect();
+ m_fireEventsBrowser->selectAndExpand(eventName);
+ CDialogs::showWidgetBrowser(this, m_fireEventsBrowser, point);
+ m_activeBrowser = m_fireEventsBrowser;
+
+ connect(m_fireEventsBrowser, &EventsBrowserView::selectionChanged,
+ this, [this, handle] {
+ setArgumentValue(handle, qt3dsdm::Qt3DSDMEventHandle(
+ m_fireEventsBrowser->selectedHandle()).GetHandleValue());
+ });
+
+ return m_fireEventsBrowser;
+}
+
+void ActionView::updateFiredEvent()
+{
+ if (!m_itemHandle.Valid())
+ return;
+
+ 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
+ qt3dsdm::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)));
+ m_connections.push_back(theSignalProvider->ConnectInstanceDeleted(
+ std::bind(&ActionView::OnInstanceDeleted, this,
+ std::placeholders::_1)));
+ CDispatch *theDispatch = g_StudioApp.GetCore()->GetDispatch();
+ m_connections.push_back(theDispatch->ConnectSelectionChange(
+ std::bind(&ActionView::OnSelectionSet, this,
+ std::placeholders::_1)));
+
+ auto assetGraph = g_StudioApp.GetCore()->GetDoc()->GetAssetGraph();
+ m_connections.push_back(assetGraph->ConnectChildAdded(
+ std::bind(&ActionView::onAssetGraphChanged, this)));
+ m_connections.push_back(assetGraph->ConnectChildRemoved(
+ std::bind(&ActionView::onAssetGraphChanged, this)));
+}
+
+void ActionView::OnClosingPresentation()
+{
+ m_connections.clear();
+}
+
+void ActionView::OnSelectionSet(Q3DStudio::SSelectedValue inSelectable)
+{
+ qt3dsdm::Qt3DSDMInstanceHandle theInstance;
+ std::vector<qt3dsdm::Qt3DSDMInstanceHandle> instances;
+
+ switch (inSelectable.getType()) {
+ case Q3DStudio::SelectedValueTypes::Instance:
+ theInstance = inSelectable.getData<qt3dsdm::Qt3DSDMInstanceHandle>();
+ break;
+ case Q3DStudio::SelectedValueTypes::MultipleInstances:
+ instances = inSelectable.getData<std::vector<qt3dsdm::Qt3DSDMInstanceHandle>>();
+ // handling only if we have one selected element.
+ if (instances.size() == 1)
+ theInstance = instances[0];
+ break;
+ case Q3DStudio::SelectedValueTypes::Slide: {
+ qt3dsdm::Qt3DSDMSlideHandle theSlideHandle =
+ inSelectable.getData<Q3DStudio::SSlideInstanceWrapper>().m_Slide;
+ // Get the owning component instance
+ CClientDataModelBridge *theBridge = GetBridge();
+ qt3dsdm::SLong4 theComponentGuid = theBridge->GetComponentGuid(theSlideHandle);
+ Q_ASSERT(theComponentGuid.Valid());
+ theInstance = theBridge->GetInstanceByGUID(theComponentGuid);
+ Q_ASSERT(theInstance.Valid());
+ }
+ break;
+ default:
+ // Clear selection on selecting other types or nothing at all
+ break;
+ };
+
+ setItem(theInstance);
+}
+
+void ActionView::OnActionAdded(qt3dsdm::Qt3DSDMActionHandle inAction,
+ qt3dsdm::Qt3DSDMSlideHandle inSlide,
+ qt3dsdm::Qt3DSDMInstanceHandle inOwner)
+{
+ CDoc *theDoc = GetDoc();
+ qt3dsdm::CStudioSystem *theStudioSystem = theDoc->GetStudioSystem();
+
+ qt3dsdm::Qt3DSDMSlideHandle theCurrentSlide = theDoc->GetActiveSlide();
+ qt3dsdm::Qt3DSDMSlideHandle theMasterSlideOfAction =
+ theStudioSystem->GetSlideSystem()->GetMasterSlide(inSlide);
+ qt3dsdm::Qt3DSDMSlideHandle theMasterOfCurrentSlide =
+ theStudioSystem->GetSlideSystem()->GetMasterSlide(theCurrentSlide);
+
+ if (!m_activeBrowser.isNull() && m_activeBrowser->isVisible()) {
+ m_activeBrowser->close();
+ m_activeBrowser.clear();
+ }
+
+ 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);
+ }
+}
+
+void ActionView::OnActionDeleted(qt3dsdm::Qt3DSDMActionHandle inAction,
+ qt3dsdm::Qt3DSDMSlideHandle inSlide,
+ qt3dsdm::Qt3DSDMInstanceHandle inOwner)
+{
+ Q_UNUSED(inSlide);
+ Q_UNUSED(inOwner);
+
+ if (!m_activeBrowser.isNull() && m_activeBrowser->isVisible()) {
+ m_activeBrowser->close();
+ m_activeBrowser.clear();
+ }
+ m_actionsModel->removeAction(inAction);
+}
+
+void ActionView::OnActionModified(qt3dsdm::Qt3DSDMActionHandle inAction)
+{
+ if (!m_itemHandle.Valid())
+ return;
+
+ if (GetDoc()->GetStudioSystem()->GetActionCore()->HandleValid(inAction)) {
+ if (!m_activeBrowser.isNull() && m_activeBrowser->isVisible()) {
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+ if (!actionInfo.m_Instance.Valid()) {
+ m_activeBrowser->close();
+ m_activeBrowser.clear();
+ } else {
+ // Update the selection in an active browser dialog
+ if (m_activeBrowser == m_triggerObjectBrowser) {
+ const auto instanceHandle = GetBridge()->GetInstance(
+ actionInfo.m_Owner, actionInfo.m_TriggerObject);
+ m_triggerObjectBrowser->selectAndExpand(instanceHandle, actionInfo.m_Owner);
+ } else if (m_activeBrowser == m_targetObjectBrowser) {
+ const auto instanceHandle = GetBridge()->GetInstance(
+ actionInfo.m_Owner, actionInfo.m_TargetObject);
+ m_targetObjectBrowser->selectAndExpand(instanceHandle, actionInfo.m_Owner);
+ } else if (m_activeBrowser == m_eventsBrowser) {
+ m_eventsBrowser->selectAndExpand(QString::fromStdWString(actionInfo.m_Event));
+ } else if (m_activeBrowser == m_handlerBrowser) {
+ m_handlerBrowser->selectAndExpand(
+ QString::fromStdWString(actionInfo.m_Handler));
+ }
+ }
+ }
+ m_actionsModel->updateAction(inAction);
+ emitActionChanged();
+ }
+}
+
+void ActionView::OnHandlerArgumentModified(qt3dsdm::Qt3DSDMHandlerArgHandle inHandlerArgument)
+{
+ if (!m_itemHandle.Valid())
+ return;
+
+ if (!m_fireEventsBrowser.isNull() && m_activeBrowser == m_fireEventsBrowser
+ && m_activeBrowser->isVisible()) {
+ const auto actionInfo = m_actionsModel->actionInfoAt(m_currentActionIndex);
+
+ // m_fireEventsBrowser needs to be closed if another type of target handler is chosen.
+ // Other browsers will remain valid always as long as the action is selected.
+ if (actionInfo.m_Handler != L"Fire Event") {
+ m_activeBrowser->close();
+ m_activeBrowser.clear();
+ } else {
+ // Update the selection in an active browser dialog
+ const auto bridge = GetBridge();
+ const auto instanceHandle = bridge->GetInstance(actionInfo.m_Owner,
+ actionInfo.m_TargetObject);
+ qt3dsdm::TEventHandleList eventList;
+ bridge->GetEvents(instanceHandle, eventList);
+ qt3dsdm::SValue value;
+ GetDoc()->GetStudioSystem()->GetActionCore()->GetHandlerArgumentValue(
+ m_fireEventsBrowser->handle(), value);
+ QString eventName;
+ for (Qt3DSDMEventHandle eventHandle : eventList) {
+ if (value == eventHandle.GetHandleValue()) {
+ qt3dsdm::SEventInfo eventInfo = bridge->GetEventInfo(eventHandle);
+ eventName = QString::fromWCharArray(eventInfo.m_FormalName.wide_str());
+ if (eventName.isEmpty())
+ eventName = QString::fromWCharArray(eventInfo.m_Name.wide_str());
+ }
+ }
+ m_fireEventsBrowser->selectAndExpand(eventName);
+ }
+ }
+ emitActionChanged();
+}
+
+void ActionView::OnInstancePropertyValueChanged(qt3dsdm::Qt3DSDMInstanceHandle inInstance,
+ qt3dsdm::Qt3DSDMPropertyHandle inProperty)
+{
+ if (!m_itemHandle.Valid() || m_itemHandle != inInstance)
+ return;
+
+ auto bridge = g_StudioApp.GetCore()->GetDoc()->GetStudioSystem()->GetClientDataModelBridge();
+ if (inProperty == bridge->GetNameProperty())
+ Q_EMIT itemTextChanged();
+
+ emitActionChanged();
+}
+
+void ActionView::OnInstanceDeleted(qt3dsdm::Qt3DSDMInstanceHandle inInstance)
+{
+ // Clear the model on instance deletion
+ if (inInstance == m_itemHandle) {
+ qt3dsdm::Qt3DSDMInstanceHandle noInstance;
+ setItem(noInstance);
+ }
+}
+
+void ActionView::copyAction()
+{
+ if (!m_itemHandle.Valid())
+ return;
+
+ auto theTempAPFile =
+ GetDoc()->GetDocumentReader().CopyAction(m_actionsModel->actionAt(m_currentActionIndex),
+ GetDoc()->GetActiveSlide());
+ Qt3DSFile theFile(theTempAPFile);
+ CStudioClipboard::CopyActionToClipboard(theFile);
+ updateActionStates();
+}
+
+void ActionView::cutAction()
+{
+ if (!m_itemHandle.Valid())
+ return;
+
+ copyAction();
+ auto action = m_actionsModel->actionAt(m_currentActionIndex);
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*GetDoc(), QObject::tr("Cut Action"))->DeleteAction(action);
+ updateActionStates();
+}
+
+void ActionView::pasteAction()
+{
+ if (!m_itemHandle.Valid())
+ return;
+
+ Qt3DSFile theTempAPFile = CStudioClipboard::GetActionFromClipboard();
+ Q3DStudio::SCOPED_DOCUMENT_EDITOR(*GetDoc(), QObject::tr("Paste Action"))
+ ->PasteAction(theTempAPFile.GetAbsolutePath(), m_itemHandle);
+ updateActionStates();
+}
+
+void ActionView::setTriggerObject(const qt3dsdm::SObjectRefType &object)
+{
+ auto action = m_actionsModel->actionAt(m_currentActionIndex);
+ if (!action.Valid())
+ return;
+
+ if (!m_triggerObjectBrowser.isNull() && m_triggerObjectBrowser->canCommit()) {
+ auto core = g_StudioApp.GetCore();
+ auto theBridge = GetBridge();
+
+ auto theCmd = new CCmdDataModelActionSetTriggerObject(GetDoc(), action, object);
+ const SActionInfo &theActionInfo
+ = GetDoc()->GetStudioSystem()->GetActionCore()->GetActionInfo(action);
+
+ Qt3DSDMInstanceHandle theBaseInstance = theActionInfo.m_Owner;
+ Qt3DSDMInstanceHandle theObjectInstance = theBridge->GetInstance(theBaseInstance, object);
+ Qt3DSDMInstanceHandle 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 qt3dsdm::SObjectRefType &object)
+{
+ auto action = m_actionsModel->actionAt(m_currentActionIndex);
+ if (!action.Valid())
+ return;
+
+ if (!m_targetObjectBrowser.isNull() && m_targetObjectBrowser->canCommit()) {
+ 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);
+
+ Qt3DSDMInstanceHandle theBaseInstance = theActionInfo.m_Owner;
+ Qt3DSDMInstanceHandle theObjectInstance = theBridge->GetInstance(theBaseInstance, object);
+ Qt3DSDMInstanceHandle 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 Qt3DSDMEventHandle &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 Qt3DSDMHandlerHandle &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
+{
+ qt3dsdm::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() || !m_itemHandle.Valid())
+ 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 (!m_itemHandle.Valid())
+ return;
+
+ if (handle == 0)
+ return;
+
+ qt3dsdm::SValue sValue(value);
+ qt3dsdm::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(QStringLiteral("_parentView"), this);
+ rootContext()->setContextProperty(QStringLiteral("_resDir"), StudioUtils::resourceImageUrl());
+ rootContext()->setContextProperty(QStringLiteral("_tabOrderHandler"), tabOrderHandler());
+ rootContext()->setContextProperty(QStringLiteral("_mouseHelper"), &m_mouseHelper);
+ m_mouseHelper.setWidget(this);
+
+ QString shiftKey(QStringLiteral("Shift+"));
+#ifdef Q_OS_MACOS
+ shiftKey = "⇧";
+#endif
+ rootContext()->setContextProperty(QStringLiteral("_shiftKey"), shiftKey);
+ qmlRegisterUncreatableType<qt3dsdm::HandlerArgumentType>(
+ "Qt3DStudio", 1, 0, "HandlerArgumentType",
+ QStringLiteral("HandlerArgumentType is an enum container"));
+ qmlRegisterUncreatableType<qt3dsdm::DataModelDataType>(
+ "Qt3DStudio", 1, 0, "DataModelDataType",
+ QStringLiteral("DataModelDataType is an enum container"));
+ qmlRegisterUncreatableType<qt3dsdm::AdditionalMetaDataType>(
+ "Qt3DStudio", 1, 0, "AdditionalMetaDataType",
+ QStringLiteral("AdditionalMetaDataType is an enum container"));
+ qmlRegisterUncreatableType<PropertyInfo>(
+ "Qt3DStudio", 1, 0, "PropertyInfo",
+ QStringLiteral("PropertyInfo is not creatable in QML"));
+ qmlRegisterUncreatableType<qt3dsdm::CompleteMetaDataType>(
+ "Qt3DStudio", 1, 0, "CompleteMetaDataType",
+ QStringLiteral("CompleteMetaDataType is an enum container"));
+ engine()->addImportPath(StudioUtils::qmlImportPath());
+ setSource(QUrl(QStringLiteral("qrc:/Palettes/Action/ActionView.qml")));
+}
+
+QStringList ActionView::slideNames()
+{
+ if (!m_itemHandle.Valid())
+ return {};
+
+ 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);
+}
+
+bool ActionView::toolTipsEnabled()
+{
+ return CStudioPreferences::ShouldShowTooltips();
+}
+
+void ActionView::updateActionStates()
+{
+ bool hasValidAction = (m_currentActionIndex != -1) && m_itemHandle.Valid();
+ m_actionCopy->setEnabled(hasValidAction);
+ m_actionCut->setEnabled(hasValidAction);
+ m_actionDel->setEnabled(hasValidAction);
+ // Allow paste action even if item is not valid (list of actions is empty)
+ m_actionPaste->setEnabled(CStudioClipboard::CanPasteAction());
+}
+
+// m_propertyValueInvalid flag indicates that property value is changing and
+// may not be valid if queried at the moment. It is used to prevent QML errors
+// about invalid value types when changing property handlers.
+void ActionView::setPropertyValueInvalid(bool invalid)
+{
+ if (invalid != m_propertyValueInvalid) {
+ m_propertyValueInvalid = invalid;
+ Q_EMIT propertyValueInvalidChanged();
+ }
+}
+
+// This is used to set m_propertyValueInvalid to false asynchronously
+void ActionView::clearPropertyValueInvalid()
+{
+ setPropertyValueInvalid(false);
+}
+
+void ActionView::onAssetGraphChanged()
+{
+ // Changes to asset graph invalidate the object browser model, so close it if it is open
+ if (!m_activeBrowser.isNull() && m_activeBrowser->isVisible()
+ && (m_activeBrowser == m_targetObjectBrowser
+ || m_activeBrowser == m_triggerObjectBrowser)) {
+ m_activeBrowser->close();
+ m_activeBrowser.clear();
+ }
+}