/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "qmlinspectorconstants.h"
#include "qmlinspector.h"
#include "inspectoroutputwidget.h"
#include "inspectorcontext.h"
#include "startexternalqmldialog.h"
#include "components/objecttree.h"
#include "components/watchtable.h"
#include "components/canvasframerate.h"
#include "components/expressionquerywidget.h"
#include "components/objectpropertiesview.h"

#include <debugger/debuggerrunner.h>
#include <debugger/debuggermainwindow.h>
#include <debugger/debuggeruiswitcher.h>
#include <debugger/debuggerconstants.h>

#include <utils/styledbar.h>
#include <utils/fancymainwindow.h>

#include <coreplugin/icontext.h>
#include <coreplugin/basemode.h>
#include <coreplugin/findplaceholder.h>
#include <coreplugin/minisplitter.h>
#include <coreplugin/outputpane.h>
#include <coreplugin/rightpane.h>
#include <coreplugin/navigationwidget.h>
#include <coreplugin/icore.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/uniqueidmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/editormanager/editormanager.h>

#include <texteditor/itexteditor.h>

#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/project.h>
#include <projectexplorer/target.h>
#include <projectexplorer/applicationrunconfiguration.h>
#include <qmlprojectmanager/qmlprojectconstants.h>
#include <qmlprojectmanager/qmlprojectrunconfiguration.h>

#include <extensionsystem/pluginmanager.h>

#include <QtCore/QDebug>
#include <QtCore/QStringList>
#include <QtCore/QTimer>
#include <QtCore/QtPlugin>

#include <QtGui/QToolButton>
#include <QtGui/QToolBar>
#include <QtGui/QBoxLayout>
#include <QtGui/QLabel>
#include <QtGui/QDockWidget>
#include <QtGui/QAction>
#include <QtGui/QLineEdit>
#include <QtGui/QLabel>
#include <QtGui/QSpinBox>
#include <QtGui/QMessageBox>

#include <QtNetwork/QHostAddress>

using namespace Qml;

namespace Qml {

namespace Internal {
class EngineSpinBox : public QSpinBox
{
    Q_OBJECT
public:
    struct EngineInfo
    {
        QString name;
        int id;
    };

    EngineSpinBox(QWidget *parent = 0);

    void addEngine(int engine, const QString &name);
    void clearEngines();

protected:
    virtual QString textFromValue(int value) const;
    virtual int valueFromText(const QString &text) const;

private:
    QList<EngineInfo> m_engines;
};

EngineSpinBox::EngineSpinBox(QWidget *parent)
    : QSpinBox(parent)
{
    setEnabled(false);
    setReadOnly(true);
    setRange(0, 0);
}

void EngineSpinBox::addEngine(int engine, const QString &name)
{
    EngineInfo info;
    info.id = engine;
    if (name.isEmpty())
        info.name = tr("Engine %1", "engine number").arg(engine);
    else
        info.name = name;
    m_engines << info;

    setRange(0, m_engines.count()-1);
}

void EngineSpinBox::clearEngines()
{
    m_engines.clear();
}

QString EngineSpinBox::textFromValue(int value) const
{
    for (int i=0; i<m_engines.count(); ++i) {
        if (m_engines[i].id == value)
            return m_engines[i].name;
    }
    return QLatin1String("<None>");
}

int EngineSpinBox::valueFromText(const QString &text) const
{
    for (int i=0; i<m_engines.count(); ++i) {
        if (m_engines[i].name == text)
            return m_engines[i].id;
    }
    return -1;
}

} // Internal


QmlInspector::QmlInspector(QObject *parent)
  : QObject(parent),
    m_conn(0),
    m_client(0),
    m_engineQuery(0),
    m_contextQuery(0),
    m_objectTreeDock(0),
    m_frameRateDock(0),
    m_propertyWatcherDock(0),
    m_inspectorOutputDock(0),
    m_connectionTimer(new QTimer(this)),
    m_connectionAttempts(0)
{
    m_watchTableModel = new Internal::WatchTableModel(0, this);

    m_objectTreeWidget = new Internal::ObjectTree;
    m_propertiesWidget = new Internal::ObjectPropertiesView;
    m_watchTableView = new Internal::WatchTableView(m_watchTableModel);
    m_frameRateWidget = new Internal::CanvasFrameRate;
    m_frameRateWidget->setObjectName(QLatin1String("QmlDebugFrameRate"));
    m_expressionWidget = new Internal::ExpressionQueryWidget(Internal::ExpressionQueryWidget::SeparateEntryMode);

    connect(m_connectionTimer, SIGNAL(timeout()), SLOT(pollInspector()));
}

QmlInspector::~QmlInspector()
{
    m_settings.saveSettings(Core::ICore::instance()->settings());
}

void QmlInspector::pollInspector()
{
    ++m_connectionAttempts;
    if (connectToViewer()) {
        m_connectionTimer->stop();
        m_connectionAttempts = 0;
    } else if (m_connectionAttempts == MaxConnectionAttempts) {
        m_connectionTimer->stop();
        m_connectionAttempts = 0;

        QMessageBox::critical(0,
                              tr("Failed to connect to debugger"),
                              tr("Could not connect to debugger server.") );
    }
}

bool QmlInspector::setDebugConfigurationDataFromProject(ProjectExplorer::Project *projectToDebug)
{
    //ProjectExplorer::Project *project = ProjectExplorer::ProjectExplorerPlugin::instance()->startupProject();
    if (!projectToDebug) {
        emit statusMessage(tr("Invalid project, debugging canceled."));
        return false;
    }

    QmlProjectManager::QmlProjectRunConfiguration* config =
            qobject_cast<QmlProjectManager::QmlProjectRunConfiguration*>(projectToDebug->activeTarget()->activeRunConfiguration());
    if (!config) {
        emit statusMessage(tr("Cannot find project run configuration, debugging canceled."));
        return false;
    }
    m_runConfigurationDebugData.serverAddress = config->debugServerAddress();
    m_runConfigurationDebugData.serverPort = config->debugServerPort();
    m_connectionTimer->setInterval(ConnectionAttemptDefaultInterval);

    return true;
}

void QmlInspector::startConnectionTimer()
{
    m_connectionTimer->start();
}

bool QmlInspector::connectToViewer()
{
    if (m_conn && m_conn->state() != QAbstractSocket::UnconnectedState)
        return false;

    delete m_client; m_client = 0;

    if (m_conn) {
        m_conn->disconnectFromHost();
        delete m_conn;
        m_conn = 0;
    }

    QString host = m_runConfigurationDebugData.serverAddress;
    quint16 port = quint16(m_runConfigurationDebugData.serverPort);

    m_conn = new QDeclarativeDebugConnection(this);
    connect(m_conn, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
            SLOT(connectionStateChanged()));
    connect(m_conn, SIGNAL(error(QAbstractSocket::SocketError)),
            SLOT(connectionError()));

    emit statusMessage(tr("[Inspector] set to connect to debug server %1:%2").arg(host).arg(port));
    m_conn->connectToHost(host, port);
    // blocks until connected; if no connection is available, will fail immediately
    if (m_conn->waitForConnected())
        return true;

    return false;
}

void QmlInspector::disconnectFromViewer()
{
    m_conn->disconnectFromHost();
}

void QmlInspector::connectionStateChanged()
{
    switch (m_conn->state()) {
        case QAbstractSocket::UnconnectedState:
        {
            emit statusMessage(tr("[Inspector] disconnected.\n\n"));

            delete m_engineQuery;
            m_engineQuery = 0;
            delete m_contextQuery;
            m_contextQuery = 0;

            resetViews();

            break;
        }
        case QAbstractSocket::HostLookupState:
            emit statusMessage(tr("[Inspector] resolving host..."));
            break;
        case QAbstractSocket::ConnectingState:
            emit statusMessage(tr("[Inspector] connecting to debug server..."));
            break;
        case QAbstractSocket::ConnectedState:
        {
            emit statusMessage(tr("[Inspector] connected.\n"));

            if (!m_client) {
                m_client = new QDeclarativeEngineDebug(m_conn, this);
                m_objectTreeWidget->setEngineDebug(m_client);
                m_propertiesWidget->setEngineDebug(m_client);
                m_watchTableModel->setEngineDebug(m_client);
                m_expressionWidget->setEngineDebug(m_client);
            }

            resetViews();
            m_frameRateWidget->reset(m_conn);

            reloadEngines();
            break;
        }
        case QAbstractSocket::ClosingState:
            emit statusMessage(tr("[Inspector] closing..."));
            break;
        case QAbstractSocket::BoundState:
        case QAbstractSocket::ListeningState:
            break;
    }
}

void QmlInspector::resetViews()
{
    m_objectTreeWidget->clear();
    m_propertiesWidget->clear();
    m_expressionWidget->clear();
    m_watchTableModel->removeAllWatches();
}

Core::IContext *QmlInspector::context() const
{
    return m_context;
}

void QmlInspector::connectionError()
{
    emit statusMessage(tr("[Inspector] error: (%1) %2", "%1=error code, %2=error message")
            .arg(m_conn->error()).arg(m_conn->errorString()));
}

void QmlInspector::createDockWidgets()
{

    m_engineSpinBox = new Internal::EngineSpinBox;
    m_engineSpinBox->setEnabled(false);
    connect(m_engineSpinBox, SIGNAL(valueChanged(int)),
            SLOT(queryEngineContext(int)));

    // FancyMainWindow uses widgets' window titles for tab labels
    m_frameRateWidget->setWindowTitle(tr("Frame rate"));

    Utils::StyledBar *treeOptionBar = new Utils::StyledBar;
    QHBoxLayout *treeOptionBarLayout = new QHBoxLayout(treeOptionBar);
    treeOptionBarLayout->setContentsMargins(5, 0, 5, 0);
    treeOptionBarLayout->setSpacing(5);
    treeOptionBarLayout->addWidget(new QLabel(tr("QML engine:")));
    treeOptionBarLayout->addWidget(m_engineSpinBox);

    QWidget *treeWindow = new QWidget;
    treeWindow->setObjectName(QLatin1String("QmlDebugTree"));
    treeWindow->setWindowTitle(tr("Object Tree"));
    QVBoxLayout *treeWindowLayout = new QVBoxLayout(treeWindow);
    treeWindowLayout->setMargin(0);
    treeWindowLayout->setSpacing(0);
    treeWindowLayout->addWidget(treeOptionBar);
    treeWindowLayout->addWidget(m_objectTreeWidget);

    m_watchTableView->setModel(m_watchTableModel);
    Internal::WatchTableHeaderView *header = new Internal::WatchTableHeaderView(m_watchTableModel);
    m_watchTableView->setHorizontalHeader(header);

    connect(m_objectTreeWidget, SIGNAL(activated(QDeclarativeDebugObjectReference)),
            this, SLOT(treeObjectActivated(QDeclarativeDebugObjectReference)));

    connect(m_objectTreeWidget, SIGNAL(currentObjectChanged(QDeclarativeDebugObjectReference)),
            m_propertiesWidget, SLOT(reload(QDeclarativeDebugObjectReference)));

    connect(m_objectTreeWidget, SIGNAL(expressionWatchRequested(QDeclarativeDebugObjectReference,QString)),
            m_watchTableModel, SLOT(expressionWatchRequested(QDeclarativeDebugObjectReference,QString)));

    connect(m_propertiesWidget, SIGNAL(activated(QDeclarativeDebugObjectReference,QDeclarativeDebugPropertyReference)),
            m_watchTableModel, SLOT(togglePropertyWatch(QDeclarativeDebugObjectReference,QDeclarativeDebugPropertyReference)));

    connect(m_watchTableModel, SIGNAL(watchCreated(QDeclarativeDebugWatch*)),
            m_propertiesWidget, SLOT(watchCreated(QDeclarativeDebugWatch*)));

    connect(m_watchTableModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
            m_watchTableView, SLOT(scrollToBottom()));

    connect(m_watchTableView, SIGNAL(objectActivated(int)),
            m_objectTreeWidget, SLOT(setCurrentObject(int)));

    connect(m_objectTreeWidget, SIGNAL(currentObjectChanged(QDeclarativeDebugObjectReference)),
            m_expressionWidget, SLOT(setCurrentObject(QDeclarativeDebugObjectReference)));


    Core::MiniSplitter *leftSplitter = new Core::MiniSplitter(Qt::Vertical);
    leftSplitter->addWidget(m_propertiesWidget);
    leftSplitter->addWidget(m_watchTableView);
    leftSplitter->setStretchFactor(0, 2);
    leftSplitter->setStretchFactor(1, 1);

    Core::MiniSplitter *propSplitter = new Core::MiniSplitter(Qt::Horizontal);
    propSplitter->setObjectName(QLatin1String("QmlDebugProperties"));
    propSplitter->addWidget(leftSplitter);
    propSplitter->addWidget(m_expressionWidget);
    propSplitter->setStretchFactor(0, 2);
    propSplitter->setStretchFactor(1, 1);
    propSplitter->setWindowTitle(tr("Properties and Watchers"));



    InspectorOutputWidget *inspectorOutput = new InspectorOutputWidget();
    inspectorOutput->setObjectName(QLatin1String("QmlDebugInspectorOutput"));
    connect(this, SIGNAL(statusMessage(QString)),
            inspectorOutput, SLOT(addInspectorStatus(QString)));

    m_objectTreeDock = Debugger::DebuggerUISwitcher::instance()->createDockWidget(Qml::Constants::LANG_QML,
                                                            treeWindow, Qt::BottomDockWidgetArea);
    m_frameRateDock = Debugger::DebuggerUISwitcher::instance()->createDockWidget(Qml::Constants::LANG_QML,
                                                            m_frameRateWidget, Qt::BottomDockWidgetArea);
    m_propertyWatcherDock = Debugger::DebuggerUISwitcher::instance()->createDockWidget(Qml::Constants::LANG_QML,
                                                            propSplitter, Qt::BottomDockWidgetArea);
    m_inspectorOutputDock = Debugger::DebuggerUISwitcher::instance()->createDockWidget(Qml::Constants::LANG_QML,
                                                            inspectorOutput, Qt::BottomDockWidgetArea);

    m_objectTreeDock->setToolTip(tr("Contents of the scene."));
    m_frameRateDock->setToolTip(tr("Frame rate graph for analyzing performance."));
    m_propertyWatcherDock->setToolTip(tr("Properties of the selected item."));
    m_inspectorOutputDock->setToolTip(tr("Output of the QML inspector, such as information on connecting to the server."));

    m_dockWidgets << m_objectTreeDock << m_frameRateDock << m_propertyWatcherDock << m_inspectorOutputDock;

    m_context = new Internal::InspectorContext(m_objectTreeDock);
    m_propWatcherContext = new Internal::InspectorContext(m_propertyWatcherDock);

    Core::ICore *core = Core::ICore::instance();
    core->addContextObject(m_propWatcherContext);
    core->addContextObject(m_context);

    QAction *attachToExternalAction = new QAction(this);
    attachToExternalAction->setText(tr("Start Debugging C++ and QML Simultaneously..."));
    connect(attachToExternalAction, SIGNAL(triggered()),
        this, SLOT(attachToExternalQmlApplication()));

    Core::ActionManager *am = core->actionManager();
    Core::ActionContainer *mstart = am->actionContainer(ProjectExplorer::Constants::M_DEBUG_STARTDEBUGGING);
    Core::Command *cmd = am->registerAction(attachToExternalAction, Constants::M_ATTACH_TO_EXTERNAL,
                                            QList<int>() << m_context->context());
    cmd->setAttribute(Core::Command::CA_Hide);
    mstart->addAction(cmd, Core::Constants::G_DEFAULT_ONE);

    m_settings.readSettings(core->settings());

    connect(m_objectTreeWidget, SIGNAL(contextHelpIdChanged(QString)), m_context,
            SLOT(setContextHelpId(QString)));
    connect(m_watchTableView, SIGNAL(contextHelpIdChanged(QString)), m_propWatcherContext,
            SLOT(setContextHelpId(QString)));
    connect(m_propertiesWidget, SIGNAL(contextHelpIdChanged(QString)), m_propWatcherContext,
            SLOT(setContextHelpId(QString)));
    connect(m_expressionWidget, SIGNAL(contextHelpIdChanged(QString)), m_propWatcherContext,
            SLOT(setContextHelpId(QString)));
}

void QmlInspector::attachToExternalQmlApplication()
{
    ProjectExplorer::ProjectExplorerPlugin *pex = ProjectExplorer::ProjectExplorerPlugin::instance();
    ProjectExplorer::Project *project = pex->startupProject();
    ProjectExplorer::LocalApplicationRunConfiguration* runConfig =
                qobject_cast<ProjectExplorer::LocalApplicationRunConfiguration*>(project->activeTarget()->activeRunConfiguration());

    QString errorMessage;

    if (!project)
        errorMessage = QString(tr("No project was found."));
    else if (!project->activeTarget() || !project->activeTarget()->activeRunConfiguration())
        errorMessage = QString(tr("No run configurations were found for the project '%1'.").arg(project->displayName()));
    else if (!runConfig)
        errorMessage = QString(tr("No valid run configuration was found for the project %1. "
                                  "Only locally runnable configurations are supported.\n"
                                  "Please check your project settings.").arg(project->displayName()));


    if (errorMessage.isEmpty()) {

        Internal::StartExternalQmlDialog dlg(Debugger::DebuggerUISwitcher::instance()->mainWindow());

        dlg.setPort(m_settings.externalPort());
        dlg.setDebuggerUrl(m_settings.externalUrl());
        dlg.setProjectDisplayName(project->displayName());
        if (dlg.exec() != QDialog::Accepted)
            return;

        m_runConfigurationDebugData.serverAddress = dlg.debuggerUrl();
        m_runConfigurationDebugData.serverPort = dlg.port();
        m_settings.setExternalPort(dlg.port());
        m_settings.setExternalUrl(dlg.debuggerUrl());

        ProjectExplorer::Environment customEnv = runConfig->environment();
        customEnv.set(QmlProjectManager::Constants::E_QML_DEBUG_SERVER_PORT, QString::number(m_settings.externalPort()));

        ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
        const QList<Debugger::Internal::DebuggerRunControlFactory *> factories = pm->getObjects<Debugger::Internal::DebuggerRunControlFactory>();
        // to make sure we have a valid, debuggable run control, find the correct factory for it
        if (factories.length() && factories.first()->canRun(runConfig, ProjectExplorer::Constants::DEBUGMODE)) {


            ProjectExplorer::RunControl *runControl = factories.first()->create(runConfig, ProjectExplorer::Constants::DEBUGMODE);
            Debugger::Internal::DebuggerRunControl *debuggableRunControl = qobject_cast<Debugger::Internal::DebuggerRunControl *>(runControl);
            // modify the env
            debuggableRunControl->setCustomEnvironment(customEnv);

            Debugger::DebuggerManager *debugManager = Debugger::DebuggerManager::instance();
            connect(debugManager, SIGNAL(stateChanged(int)), this, SLOT(debuggerStateChanged(int)));

            pex->startRunControl(debuggableRunControl, ProjectExplorer::Constants::DEBUGMODE);

        } else {
            errorMessage = QString(tr("A valid run control was not registered in Qt Creator for this project run configuration."));
        }


    }

    if (!errorMessage.isEmpty())
        QMessageBox::warning(Core::ICore::instance()->mainWindow(), "Failed to debug C++ and QML", errorMessage);
}

void QmlInspector::debuggerStateChanged(int newState)
{
    switch(newState) {
    case Debugger::AdapterStartFailed:
    case Debugger::InferiorStartFailed:
        disconnect(Debugger::DebuggerManager::instance(), SIGNAL(stateChanged(int)), this, SLOT(debuggerStateChanged(int)));
        emit statusMessage(QString(tr("Debugging failed: could not start C++ debugger.")));
        break;
    default:
        break;
    }

    if (newState == Debugger::InferiorRunning) {
        disconnect(Debugger::DebuggerManager::instance(), SIGNAL(stateChanged(int)), this, SLOT(debuggerStateChanged(int)));
        m_connectionTimer->setInterval(ConnectionAttemptSimultaneousInterval);
        startConnectionTimer();
    }

}


void QmlInspector::setSimpleDockWidgetArrangement()
{
    Utils::FancyMainWindow *mainWindow = Debugger::DebuggerUISwitcher::instance()->mainWindow();

    mainWindow->setTrackingEnabled(false);
    QList<QDockWidget *> dockWidgets = mainWindow->dockWidgets();
    foreach (QDockWidget *dockWidget, dockWidgets) {
        if (m_dockWidgets.contains(dockWidget)) {
            dockWidget->setFloating(false);
            mainWindow->removeDockWidget(dockWidget);
        }
    }

    foreach (QDockWidget *dockWidget, dockWidgets) {
        if (m_dockWidgets.contains(dockWidget)) {
            if (dockWidget == m_objectTreeDock)
                mainWindow->addDockWidget(Qt::RightDockWidgetArea, dockWidget);
            else
                mainWindow->addDockWidget(Qt::BottomDockWidgetArea, dockWidget);
            dockWidget->show();
            // dockwidget is not actually visible during init because debugger is
            // not visible, either. we can use isVisibleTo(), though.
        }
    }

    mainWindow->tabifyDockWidget(m_frameRateDock, m_propertyWatcherDock);
    mainWindow->tabifyDockWidget(m_propertyWatcherDock, m_inspectorOutputDock);

    m_inspectorOutputDock->setVisible(false);

    mainWindow->setTrackingEnabled(true);
}

void QmlInspector::reloadEngines()
{
    if (m_engineQuery) {
        emit statusMessage("[Inspector] Waiting for response to previous engine query");
        return;
    }

    m_engineSpinBox->setEnabled(false);

    m_engineQuery = m_client->queryAvailableEngines(this);
    if (!m_engineQuery->isWaiting())
        enginesChanged();
    else
        QObject::connect(m_engineQuery, SIGNAL(stateChanged(QDeclarativeDebugQuery::State)),
                         this, SLOT(enginesChanged()));
}

void QmlInspector::enginesChanged()
{
    m_engineSpinBox->clearEngines();

    QList<QDeclarativeDebugEngineReference> engines = m_engineQuery->engines();
    delete m_engineQuery; m_engineQuery = 0;

    if (engines.isEmpty())
        qWarning("qmldebugger: no engines found!");

    m_engineSpinBox->setEnabled(true);

    for (int i=0; i<engines.count(); ++i)
        m_engineSpinBox->addEngine(engines.at(i).debugId(), engines.at(i).name());

    if (engines.count() > 0) {
        m_engineSpinBox->setValue(engines.at(0).debugId());
        queryEngineContext(engines.at(0).debugId());
    }
}

void QmlInspector::queryEngineContext(int id)
{
    if (id < 0)
        return;

    if (m_contextQuery) {
        delete m_contextQuery;
        m_contextQuery = 0;
    }

    m_contextQuery = m_client->queryRootContexts(QDeclarativeDebugEngineReference(id), this);
    if (!m_contextQuery->isWaiting())
        contextChanged();
    else
        QObject::connect(m_contextQuery, SIGNAL(stateChanged(QDeclarativeDebugQuery::State)),
                         this, SLOT(contextChanged()));
}

void QmlInspector::contextChanged()
{
    //dump(m_contextQuery->rootContext(), 0);

    foreach (const QDeclarativeDebugObjectReference &object, m_contextQuery->rootContext().objects())
        m_objectTreeWidget->reload(object.debugId());

    delete m_contextQuery; m_contextQuery = 0;
}

void QmlInspector::treeObjectActivated(const QDeclarativeDebugObjectReference &obj)
{
    QDeclarativeDebugFileReference source = obj.source();
    QString fileName = source.url().toLocalFile();

    if (source.lineNumber() < 0 || !QFile::exists(fileName))
        return;

    Core::EditorManager *editorManager = Core::EditorManager::instance();
    Core::IEditor *editor = editorManager->openEditor(fileName, QString(), Core::EditorManager::NoModeSwitch);
    TextEditor::ITextEditor *textEditor = qobject_cast<TextEditor::ITextEditor*>(editor);

    if (textEditor) {
        editorManager->addCurrentPositionToNavigationHistory();
        textEditor->gotoLine(source.lineNumber());
        textEditor->widget()->setFocus();
    }
}

} // Qml

#include "qmlinspector.moc"