<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (<EMAIL>)
**
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at <EMAIL>.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "private/qdeclarativeloader_p_p.h"

#include <qdeclarativeinfo.h>
#include <qdeclarativeengine_p.h>
#include <qdeclarativeglobal_p.h>

QT_BEGIN_NAMESPACE

QDeclarativeLoaderPrivate::QDeclarativeLoaderPrivate()
    : item(0), component(0), ownComponent(false)
    , resizeMode(QDeclarativeLoader::SizeLoaderToItem)
{
}

QDeclarativeLoaderPrivate::~QDeclarativeLoaderPrivate()
{
}

void QDeclarativeLoaderPrivate::itemGeometryChanged(QDeclarativeItem *resizeItem, const QRectF &newGeometry, const QRectF &oldGeometry)
{
    if (resizeItem == item && resizeMode == QDeclarativeLoader::SizeLoaderToItem) {
        _q_updateSize();
    }
    QDeclarativeItemChangeListener::itemGeometryChanged(resizeItem, newGeometry, oldGeometry);
}

void QDeclarativeLoaderPrivate::clear()
{
    if (ownComponent) {
        component->deleteLater();
        component = 0;
        ownComponent = false;
    }
    source = QUrl();

    if (item) {
        if (QDeclarativeItem *qmlItem = qobject_cast<QDeclarativeItem*>(item)) {
            if (resizeMode == QDeclarativeLoader::SizeLoaderToItem) {
                QDeclarativeItemPrivate *p =
                    static_cast<QDeclarativeItemPrivate *>(QGraphicsItemPrivate::get(qmlItem));
                p->removeItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
            }
        }

        // We can't delete immediately because our item may have triggered
        // the Loader to load a different item.
        item->setVisible(false);
        item->setParentItem(0);
        item->deleteLater();
        item = 0;
    }
}

void QDeclarativeLoaderPrivate::initResize()
{
    Q_Q(QDeclarativeLoader);
    if (QDeclarativeItem *qmlItem = qobject_cast<QDeclarativeItem*>(item)) {
        if (resizeMode == QDeclarativeLoader::SizeLoaderToItem) {
            QDeclarativeItemPrivate *p =
                static_cast<QDeclarativeItemPrivate *>(QGraphicsItemPrivate::get(qmlItem));
            p->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
        }
    } else if (item && item->isWidget()) {
        QGraphicsWidget *widget = static_cast<QGraphicsWidget*>(item);
        if (resizeMode == QDeclarativeLoader::SizeLoaderToItem) {
            widget->installEventFilter(q);
        }
    }
    _q_updateSize();
}

/*!
    \qmlclass Loader QDeclarativeLoader
    \since 4.7
    \inherits Item

    \brief The Loader item allows dynamically loading an Item-based
    subtree from a QML URL or Component.

    Loader instantiates an item from a component. The component to
    instantiate may be specified directly by the \c sourceComponent
    property, or loaded from a URL via the \c source property.

    It is also an effective means of delaying the creation of a component
    until it is required:
    \code
    Loader { id: pageLoader }
    Rectangle {
        MouseArea { anchors.fill: parent; onClicked: pageLoader.source = "Page1.qml" }
    }
    \endcode

    If the Loader source is changed, any previous items instantiated
    will be destroyed.  Setting \c source to an empty string
    will destroy the currently instantiated items, freeing resources
    and leaving the Loader empty.  For example:

    \code
    pageLoader.source = ""
    \endcode

    unloads "Page1.qml" and frees resources consumed by it.

    \sa {dynamic-object-creation}{Dynamic Object Creation}
*/

/*!
    \internal
    \class QDeclarativeLoader
    \qmlclass Loader
 */

/*!
    Create a new QDeclarativeLoader instance.
 */
QDeclarativeLoader::QDeclarativeLoader(QDeclarativeItem *parent)
  : QDeclarativeItem(*(new QDeclarativeLoaderPrivate), parent)
{
    Q_D(QDeclarativeItem);
    d->flags |= QGraphicsItem::ItemIsFocusScope;
}

/*!
    Destroy the loader instance.
 */
QDeclarativeLoader::~QDeclarativeLoader()
{
}

/*!
    \qmlproperty url Loader::source
    This property holds the URL of the QML component to
    instantiate.

    \sa sourceComponent, status, progress
*/
QUrl QDeclarativeLoader::source() const
{
    Q_D(const QDeclarativeLoader);
    return d->source;
}

void QDeclarativeLoader::setSource(const QUrl &url)
{
    Q_D(QDeclarativeLoader);
    if (d->source == url)
        return;

    d->clear();

    d->source = url;
    if (d->source.isEmpty()) {
        emit sourceChanged();
        emit statusChanged();
        emit progressChanged();
        emit itemChanged();
        return;
    }

    d->component = new QDeclarativeComponent(qmlEngine(this), d->source, this);
    d->ownComponent = true;
    if (!d->component->isLoading()) {
        d->_q_sourceLoaded();
    } else {
        connect(d->component, SIGNAL(statusChanged(QDeclarativeComponent::Status)),
                this, SLOT(_q_sourceLoaded()));
        connect(d->component, SIGNAL(progressChanged(qreal)),
                this, SIGNAL(progressChanged()));
        emit statusChanged();
        emit progressChanged();
        emit sourceChanged();
        emit itemChanged();
    }
}

/*!
    \qmlproperty Component Loader::sourceComponent
    The sourceComponent property holds the \l{Component} to instantiate.

    \qml
    Item {
        Component {
            id: redSquare
            Rectangle { color: "red"; width: 10; height: 10 }
        }

        Loader { sourceComponent: redSquare }
        Loader { sourceComponent: redSquare; x: 10 }
    }
    \endqml

    \sa source, progress
*/

QDeclarativeComponent *QDeclarativeLoader::sourceComponent() const
{
    Q_D(const QDeclarativeLoader);
    return d->component;
}

void QDeclarativeLoader::setSourceComponent(QDeclarativeComponent *comp)
{
    Q_D(QDeclarativeLoader);
    if (comp == d->component)
        return;

    d->clear();

    d->component = comp;
    d->ownComponent = false;
    if (!d->component) {
        emit sourceChanged();
        emit statusChanged();
        emit progressChanged();
        emit itemChanged();
        return;
    }

    if (!d->component->isLoading()) {
        d->_q_sourceLoaded();
    } else {
        connect(d->component, SIGNAL(statusChanged(QDeclarativeComponent::Status)),
                this, SLOT(_q_sourceLoaded()));
        connect(d->component, SIGNAL(progressChanged(qreal)),
                this, SIGNAL(progressChanged()));
        emit progressChanged();
        emit sourceChanged();
        emit statusChanged();
        emit itemChanged();
    }
}

void QDeclarativeLoaderPrivate::_q_sourceLoaded()
{
    Q_Q(QDeclarativeLoader);

    if (component) {
        QDeclarativeContext *ctxt = new QDeclarativeContext(qmlContext(q));
        ctxt->setContextObject(q);

        if (!component->errors().isEmpty()) {
            qWarning() << component->errors();
            emit q->sourceChanged();
            emit q->statusChanged();
            emit q->progressChanged();
            return;
        }

        QDeclarativeComponent *c = component;
        QObject *obj = component->create(ctxt);
        if (component != c) {
            // component->create could trigger a change in source that causes
            // component to be set to something else. In that case we just
            // need to cleanup.
            delete obj;
            delete ctxt;
            return;
        }
        if (obj) {
            item = qobject_cast<QGraphicsObject *>(obj);
            if (item) {
                QDeclarative_setParent_noEvent(ctxt, obj);
                QDeclarative_setParent_noEvent(item, q);
                item->setParentItem(q);
//                item->setFocus(true);
                initResize();
            } else {<commit_msg>Make sure Loader doesn't leak when component has errors.<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (<EMAIL>)
**
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at <EMAIL>.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "private/qdeclarativeloader_p_p.h"

#include <qdeclarativeinfo.h>
#include <qdeclarativeengine_p.h>
#include <qdeclarativeglobal_p.h>

QT_BEGIN_NAMESPACE

QDeclarativeLoaderPrivate::QDeclarativeLoaderPrivate()
    : item(0), component(0), ownComponent(false)
    , resizeMode(QDeclarativeLoader::SizeLoaderToItem)
{
}

QDeclarativeLoaderPrivate::~QDeclarativeLoaderPrivate()
{
}

void QDeclarativeLoaderPrivate::itemGeometryChanged(QDeclarativeItem *resizeItem, const QRectF &newGeometry, const QRectF &oldGeometry)
{
    if (resizeItem == item && resizeMode == QDeclarativeLoader::SizeLoaderToItem) {
        _q_updateSize();
    }
    QDeclarativeItemChangeListener::itemGeometryChanged(resizeItem, newGeometry, oldGeometry);
}

void QDeclarativeLoaderPrivate::clear()
{
    if (ownComponent) {
        component->deleteLater();
        component = 0;
        ownComponent = false;
    }
    source = QUrl();

    if (item) {
        if (QDeclarativeItem *qmlItem = qobject_cast<QDeclarativeItem*>(item)) {
            if (resizeMode == QDeclarativeLoader::SizeLoaderToItem) {
                QDeclarativeItemPrivate *p =
                    static_cast<QDeclarativeItemPrivate *>(QGraphicsItemPrivate::get(qmlItem));
                p->removeItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
            }
        }

        // We can't delete immediately because our item may have triggered
        // the Loader to load a different item.
        item->setVisible(false);
        item->setParentItem(0);
        item->deleteLater();
        item = 0;
    }
}

void QDeclarativeLoaderPrivate::initResize()
{
    Q_Q(QDeclarativeLoader);
    if (QDeclarativeItem *qmlItem = qobject_cast<QDeclarativeItem*>(item)) {
        if (resizeMode == QDeclarativeLoader::SizeLoaderToItem) {
            QDeclarativeItemPrivate *p =
                static_cast<QDeclarativeItemPrivate *>(QGraphicsItemPrivate::get(qmlItem));
            p->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
        }
    } else if (item && item->isWidget()) {
        QGraphicsWidget *widget = static_cast<QGraphicsWidget*>(item);
        if (resizeMode == QDeclarativeLoader::SizeLoaderToItem) {
            widget->installEventFilter(q);
        }
    }
    _q_updateSize();
}

/*!
    \qmlclass Loader QDeclarativeLoader
    \since 4.7
    \inherits Item

    \brief The Loader item allows dynamically loading an Item-based
    subtree from a QML URL or Component.

    Loader instantiates an item from a component. The component to
    instantiate may be specified directly by the \c sourceComponent
    property, or loaded from a URL via the \c source property.

    It is also an effective means of delaying the creation of a component
    until it is required:
    \code
    Loader { id: pageLoader }
    Rectangle {
        MouseArea { anchors.fill: parent; onClicked: pageLoader.source = "Page1.qml" }
    }
    \endcode

    If the Loader source is changed, any previous items instantiated
    will be destroyed.  Setting \c source to an empty string
    will destroy the currently instantiated items, freeing resources
    and leaving the Loader empty.  For example:

    \code
    pageLoader.source = ""
    \endcode

    unloads "Page1.qml" and frees resources consumed by it.

    \sa {dynamic-object-creation}{Dynamic Object Creation}
*/

/*!
    \internal
    \class QDeclarativeLoader
    \qmlclass Loader
 */

/*!
    Create a new QDeclarativeLoader instance.
 */
QDeclarativeLoader::QDeclarativeLoader(QDeclarativeItem *parent)
  : QDeclarativeItem(*(new QDeclarativeLoaderPrivate), parent)
{
    Q_D(QDeclarativeItem);
    d->flags |= QGraphicsItem::ItemIsFocusScope;
}

/*!
    Destroy the loader instance.
 */
QDeclarativeLoader::~QDeclarativeLoader()
{
}

/*!
    \qmlproperty url Loader::source
    This property holds the URL of the QML component to
    instantiate.

    \sa sourceComponent, status, progress
*/
QUrl QDeclarativeLoader::source() const
{
    Q_D(const QDeclarativeLoader);
    return d->source;
}

void QDeclarativeLoader::setSource(const QUrl &url)
{
    Q_D(QDeclarativeLoader);
    if (d->source == url)
        return;

    d->clear();

    d->source = url;
    if (d->source.isEmpty()) {
        emit sourceChanged();
        emit statusChanged();
        emit progressChanged();
        emit itemChanged();
        return;
    }

    d->component = new QDeclarativeComponent(qmlEngine(this), d->source, this);
    d->ownComponent = true;
    if (!d->component->isLoading()) {
        d->_q_sourceLoaded();
    } else {
        connect(d->component, SIGNAL(statusChanged(QDeclarativeComponent::Status)),
                this, SLOT(_q_sourceLoaded()));
        connect(d->component, SIGNAL(progressChanged(qreal)),
                this, SIGNAL(progressChanged()));
        emit statusChanged();
        emit progressChanged();
        emit sourceChanged();
        emit itemChanged();
    }
}

/*!
    \qmlproperty Component Loader::sourceComponent
    The sourceComponent property holds the \l{Component} to instantiate.

    \qml
    Item {
        Component {
            id: redSquare
            Rectangle { color: "red"; width: 10; height: 10 }
        }

        Loader { sourceComponent: redSquare }
        Loader { sourceComponent: redSquare; x: 10 }
    }
    \endqml

    \sa source, progress
*/

QDeclarativeComponent *QDeclarativeLoader::sourceComponent() const
{
    Q_D(const QDeclarativeLoader);
    return d->component;
}

void QDeclarativeLoader::setSourceComponent(QDeclarativeComponent *comp)
{
    Q_D(QDeclarativeLoader);
    if (comp == d->component)
        return;

    d->clear();

    d->component = comp;
    d->ownComponent = false;
    if (!d->component) {
        emit sourceChanged();
        emit statusChanged();
        emit progressChanged();
        emit itemChanged();
        return;
    }

    if (!d->component->isLoading()) {
        d->_q_sourceLoaded();
    } else {
        connect(d->component, SIGNAL(statusChanged(QDeclarativeComponent::Status)),
                this, SLOT(_q_sourceLoaded()));
        connect(d->component, SIGNAL(progressChanged(qreal)),
                this, SIGNAL(progressChanged()));
        emit progressChanged();
        emit sourceChanged();
        emit statusChanged();
        emit itemChanged();
    }
}

void QDeclarativeLoaderPrivate::_q_sourceLoaded()
{
    Q_Q(QDeclarativeLoader);

    if (component) {
        if (!component->errors().isEmpty()) {
            qWarning() << component->errors();
            emit q->sourceChanged();
            emit q->statusChanged();
            emit q->progressChanged();
            return;
        }

        QDeclarativeContext *ctxt = new QDeclarativeContext(qmlContext(q));
        ctxt->setContextObject(q);

        QDeclarativeComponent *c = component;
        QObject *obj = component->create(ctxt);
        if (component != c) {
            // component->create could trigger a change in source that causes
            // component to be set to something else. In that case we just
            // need to cleanup.
            delete obj;
            delete ctxt;
            return;
        }
        if (obj) {
            item = qobject_cast<QGraphicsObject *>(obj);
            if (item) {
                QDeclarative_setParent_noEvent(ctxt, obj);
                QDeclarative_setParent_noEvent(item, q);
                item->setParentItem(q);
//                item->setFocus(true);
                initResize();
            } else {
{'fraction_non_alphanumeric': 0.12016124578938649, 'fraction_numerical': 0.0029819426804351427, 'mean_word_length': 2.931828050369084, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 111, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6982237', 'n_tokens_mistral': 5206, 'n_tokens_neox': 5008, 'n_words': 1358}