Commit 9324737b authored by Marco Bubke's avatar Marco Bubke Committed by Thomas Hartmann
Browse files

Stop animations and timers in the components

parent cbaccf13
......@@ -77,8 +77,6 @@ public:
bool isValid() const;
MetaInfo metaInfo() const;
QObject *createInstance(QDeclarativeContext *parentContext) const;
PropertyMetaInfo property(const QString &propertyName, bool resolveDotSyntax = false) const;
QList<NodeMetaInfo> superClasses() const;
......@@ -99,6 +97,7 @@ public:
bool isComponent() const;
bool isSubclassOf(const QString& type, int majorVersion, int minorVersio) const;
QString componentString() const;
QIcon icon() const;
private:
......
......@@ -66,6 +66,9 @@
#include <private/qdeclarativevaluetype_p.h>
#include <private/qdeclarativetext_p.h>
#include <private/qdeclarativetext_p_p.h>
#include <private/qdeclarativetransition_p.h>
#include <private/qdeclarativeanimation_p.h>
#include <private/qdeclarativetimer_p.h>
namespace QmlDesigner {
namespace Internal {
......@@ -661,13 +664,135 @@ ObjectNodeInstance::Pointer ObjectNodeInstance::create(const NodeMetaInfo &nodeM
return instance;
}
static void stopAnimation(QObject *object, QObjectList &inspectedObjectList)
{
if (object == 0)
return;
QDeclarativeTransition *transition = qobject_cast<QDeclarativeTransition*>(object);
QDeclarativeAbstractAnimation *animation = qobject_cast<QDeclarativeAbstractAnimation*>(object);
QDeclarativeScriptAction *scriptAimation = qobject_cast<QDeclarativeScriptAction*>(object);
QDeclarativeTimer *timer = qobject_cast<QDeclarativeTimer*>(object);
if(transition) {
transition->setFromState("");
transition->setToState("");
} else if (animation) {
if (scriptAimation) {
scriptAimation->setScript(QDeclarativeScriptString());
animation->setLoops(1);
animation->complete();
animation->setDisableUserControl();
}
} else if (timer) {
timer->blockSignals(true);
}
ObjectNodeInstance::removeAnimationsFromComponents(object, inspectedObjectList);
}
void ObjectNodeInstance::removeAnimationsFromComponents(QObject *object, QObjectList &inspectedObjectList)
{
if (inspectedObjectList.contains(object)) // prevent cycles
return;
inspectedObjectList.append(object);
for (int index = QObject::staticMetaObject.propertyOffset();
index < object->metaObject()->propertyCount();
index++) {
QMetaProperty metaProperty = object->metaObject()->property(index);
// search recursive in objects
if (metaProperty.isReadable()
&& metaProperty.isWritable()
&& QDeclarativeMetaType::isQObject(metaProperty.userType())) {
QObject *propertyObject = QDeclarativeMetaType::toQObject(metaProperty.read(object));
if (propertyObject) {
stopAnimation(object, inspectedObjectList);
}
}
// search recursive in objects list
if (metaProperty.isReadable()
&& QDeclarativeMetaType::isList(metaProperty.userType())) {
QDeclarativeListReference list(object, metaProperty.name());
if (list.canCount() && list.canAt()) {
for (int i = 0; i < list.count(); i++) {
QObject *propertyObject = list.at(i);
if (propertyObject) {
stopAnimation(object, inspectedObjectList);
}
}
}
}
}
foreach(QObject *object, object->children()) {
stopAnimation(object, inspectedObjectList);
}
QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject*>(object);
if (graphicsObject) {
foreach(QGraphicsItem *item, graphicsObject->childItems()) {
stopAnimation(item->toGraphicsObject(), inspectedObjectList);
}
}
}
/*!
\brief Creates an instance of the qml type in the given qml context.
\throws InvalidArgumentException when the context argument is a null pointer
\throws InvalidMetaInfoException if the object is not valid
*/
QObject *ObjectNodeInstance::createInstance(const NodeMetaInfo &metaInfo, QDeclarativeContext *context)
{
if (!metaInfo.isValid()) {
qWarning() << "NodeMetaInfo is invalid";
return 0; // maybe we should return a new QObject?
}
QObject *object = 0;
if (metaInfo.isComponent()) {
// qml component
// TODO: This is maybe expensive ...
QDeclarativeComponent component(context->engine(), QUrl::fromLocalFile(metaInfo.componentString()));
QDeclarativeContext *newContext = new QDeclarativeContext(context);
object = component.beginCreate(newContext);
QObjectList inspectedObjectList;
removeAnimationsFromComponents(object, inspectedObjectList);
component.completeCreate();
newContext->setParent(object);
} else {
// primitive
QDeclarativeType *type = QDeclarativeMetaType::qmlType(metaInfo.typeName().toAscii(), metaInfo.majorVersion(), metaInfo.minorVersion());
if (type) {
object = type->create();
} else {
qWarning() << "QuickDesigner: Cannot create an object of type"
<< QString("%1 %2,%3").arg(metaInfo.typeName(), metaInfo.majorVersion(), metaInfo.minorVersion())
<< "- type isn't known to declarative meta type system";
}
if (object && context)
QDeclarativeEngine::setContextForObject(object, context);
}
return object;
}
QObject* ObjectNodeInstance::createObject(const NodeMetaInfo &metaInfo, QDeclarativeContext *context)
{
QObject *object = metaInfo.createInstance(context);
QObject *object = createInstance(metaInfo, context);
if (object == 0)
throw InvalidNodeInstanceException(__LINE__, __FUNCTION__, __FILE__);
if (metaInfo.isComponent()) {
QObjectList inspectedObjectList;
removeAnimationsFromComponents(object, inspectedObjectList);
}
return object;
}
......
......@@ -173,7 +173,11 @@ public:
virtual bool updateStateBinding(const NodeInstance &target, const QString &propertyName, const QString &expression);
virtual bool resetStateProperty(const NodeInstance &target, const QString &propertyName, const QVariant &resetValue);
static void removeAnimationsFromComponents(QObject *object, QObjectList &inspectedObjectList);
protected:
static QObject *createInstance(const NodeMetaInfo &metaInfo, QDeclarativeContext *parentContext);
static QObject* createObject(const NodeMetaInfo &metaInfo, QDeclarativeContext *context);
void doResetProperty(const QString &propertyName);
......
......@@ -156,49 +156,6 @@ MetaInfo NodeMetaInfo::metaInfo() const
return m_data->metaInfo;
}
/*!
\brief Creates an instance of the qml type in the given qml context.
\throws InvalidArgumentException when the context argument is a null pointer
\throws InvalidMetaInfoException if the object is not valid
*/
QObject *NodeMetaInfo::createInstance(QDeclarativeContext *context) const
{
if (!context) {
Q_ASSERT_X(0, Q_FUNC_INFO, "Context cannot be null");
throw InvalidArgumentException(__LINE__, __FUNCTION__, __FILE__, "context");
}
if (!isValid()) {
qWarning() << "NodeMetaInfo is invalid";
return 0; // maybe we should return a new QObject?
}
QObject *object = 0;
if (isComponent()) {
// qml component
// TODO: This is maybe expensive ...
QDeclarativeComponent component(context->engine(), QUrl::fromLocalFile(m_data->qmlFile));
QDeclarativeContext *newContext = new QDeclarativeContext(context);
object = component.create(newContext);
newContext->setParent(object);
} else {
// primitive
QDeclarativeType *type = QDeclarativeMetaType::qmlType(typeName().toAscii(), majorVersion(), minorVersion());
if (type) {
object = type->create();
} else {
qWarning() << "QuickDesigner: Cannot create an object of type"
<< QString("%1 %2,%3").arg(typeName(), majorVersion(), minorVersion())
<< "- type isn't known to declarative meta type system";
}
if (object && context)
QDeclarativeEngine::setContextForObject(object, context);
}
return object;
}
/*!
\brief Returns all (direct and indirect) ancestor types.
......@@ -592,6 +549,15 @@ void NodeMetaInfo::setIsContainer(bool isContainer)
m_data->isContainer = isContainer;
}
QString NodeMetaInfo::componentString() const
{
if (!isValid()) {
qWarning() << "NodeMetaInfo is invalid";
return QString();
}
return m_data->qmlFile;
}
QIcon NodeMetaInfo::icon() const
{
if (!isValid()) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment