OSDN Git Service

Merge branch 'qmljsinspector'
[qt-creator-jp/qt-creator-jp.git] / src / plugins / qmljsinspector / qmljsinspector.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 **
9 ** Commercial Usage
10 **
11 ** Licensees holding valid Qt Commercial licenses may use this file in
12 ** accordance with the Qt Commercial License Agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and Nokia.
15 **
16 ** GNU Lesser General Public License Usage
17 **
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** If you are unsure which license is appropriate for your use, please
26 ** contact the sales department at http://qt.nokia.com/contact.
27 **
28 **************************************************************************/
29 #include "qmljsinspectorconstants.h"
30 #include "qmljsinspector.h"
31 #include "qmljsclientproxy.h"
32 #include "qmljsinspectorcontext.h"
33 #include "qmljsdelta.h"
34 #include "qmljslivetextpreview.h"
35 #include "qmljsprivateapi.h"
36
37 #include <qmljs/qmljsmodelmanagerinterface.h>
38 #include <qmljs/qmljsdocument.h>
39
40 #include <debugger/debuggerrunner.h>
41 #include <debugger/debuggerconstants.h>
42 #include <debugger/debuggerengine.h>
43 #include <debugger/debuggermainwindow.h>
44 #include <debugger/debuggerplugin.h>
45 #include <debugger/debuggerrunner.h>
46 #include <debugger/debuggeruiswitcher.h>
47 #include <debugger/debuggerconstants.h>
48
49 #include <utils/qtcassert.h>
50 #include <utils/styledbar.h>
51 #include <utils/fancymainwindow.h>
52
53 #include <coreplugin/icontext.h>
54 #include <coreplugin/basemode.h>
55 #include <coreplugin/findplaceholder.h>
56 #include <coreplugin/minisplitter.h>
57 #include <coreplugin/outputpane.h>
58 #include <coreplugin/rightpane.h>
59 #include <coreplugin/navigationwidget.h>
60 #include <coreplugin/icore.h>
61 #include <coreplugin/coreconstants.h>
62 #include <coreplugin/uniqueidmanager.h>
63 #include <coreplugin/actionmanager/actioncontainer.h>
64 #include <coreplugin/actionmanager/actionmanager.h>
65 #include <coreplugin/actionmanager/command.h>
66 #include <coreplugin/editormanager/editormanager.h>
67
68 #include <texteditor/itexteditor.h>
69 #include <texteditor/basetexteditor.h>
70
71 #include <projectexplorer/runconfiguration.h>
72 #include <projectexplorer/projectexplorer.h>
73 #include <projectexplorer/projectexplorerconstants.h>
74 #include <projectexplorer/project.h>
75 #include <projectexplorer/target.h>
76 #include <projectexplorer/applicationrunconfiguration.h>
77 #include <qmlprojectmanager/qmlprojectconstants.h>
78 #include <qmlprojectmanager/qmlprojectrunconfiguration.h>
79
80 #include <extensionsystem/pluginmanager.h>
81
82 #include <QtCore/QDebug>
83 #include <QtCore/QStringList>
84 #include <QtCore/QTimer>
85 #include <QtCore/QtPlugin>
86 #include <QtCore/QDateTime>
87
88 #include <QtGui/QLabel>
89 #include <QtGui/QDockWidget>
90 #include <QtGui/QAction>
91 #include <QtGui/QLineEdit>
92 #include <QtGui/QLabel>
93 #include <QtGui/QSpinBox>
94 #include <QtGui/QMessageBox>
95 #include <QtGui/QTextBlock>
96
97 #include <QtNetwork/QHostAddress>
98
99 using namespace QmlJS;
100 using namespace QmlJS::AST;
101 using namespace QmlJSInspector::Internal;
102 using namespace Debugger::Internal;
103
104
105
106
107
108
109 enum {
110     MaxConnectionAttempts = 50,
111     ConnectionAttemptDefaultInterval = 75,
112
113     // used when debugging with c++ - connection can take a lot of time
114     ConnectionAttemptSimultaneousInterval = 500
115 };
116
117 Inspector::Inspector(QObject *parent)
118     : QObject(parent),
119       m_connectionTimer(new QTimer(this)),
120       m_connectionAttempts(0),
121       m_cppDebuggerState(0),
122       m_simultaneousCppAndQmlDebugMode(false),
123       m_debugMode(StandaloneMode)
124 {
125     m_clientProxy = ClientProxy::instance();
126
127 //#warning set up the context widget
128     QWidget *contextWidget = 0;
129     m_context = new InspectorContext(contextWidget);
130
131     m_textPreview = new QmlJSLiveTextPreview(this);
132
133     connect(m_textPreview,
134             SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>)),
135             SLOT(changeSelectedItems(QList<QDeclarativeDebugObjectReference>)));
136
137     connect(m_clientProxy, SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>)),
138             SLOT(setSelectedItemsByObjectReference(QList<QDeclarativeDebugObjectReference>)));
139
140     connect(m_clientProxy, SIGNAL(connectionStatusMessage(QString)), SIGNAL(statusMessage(QString)));
141     connect(m_clientProxy, SIGNAL(connected(QDeclarativeEngineDebug*)), SLOT(connected(QDeclarativeEngineDebug*)));
142     connect(m_clientProxy, SIGNAL(disconnected()), SLOT(disconnected()));
143     connect(m_clientProxy, SIGNAL(aboutToReloadEngines()), SLOT(aboutToReloadEngines()));
144     connect(m_clientProxy, SIGNAL(enginesChanged()), SLOT(updateEngineList()));
145     connect(m_clientProxy, SIGNAL(aboutToDisconnect()), SLOT(disconnectWidgets()));
146     connect(m_clientProxy, SIGNAL(objectTreeUpdated(QDeclarativeDebugObjectReference)), SLOT(objectTreeUpdated(QDeclarativeDebugObjectReference)));
147
148     connect(Debugger::DebuggerPlugin::instance(),
149             SIGNAL(stateChanged(int)), this, SLOT(debuggerStateChanged(int)));
150
151     connect(m_connectionTimer, SIGNAL(timeout()), SLOT(pollInspector()));
152 }
153
154
155 Inspector::~Inspector()
156 {
157 }
158
159 void Inspector::disconnectWidgets()
160 {
161 }
162
163 void Inspector::disconnected()
164 {
165     resetViews();
166     updateMenuActions();
167 }
168
169 void Inspector::aboutToReloadEngines()
170 {
171 }
172
173 void Inspector::updateEngineList()
174 {
175     const QList<QDeclarativeDebugEngineReference> engines = m_clientProxy->engines();
176
177 //#warning update the QML engines combo
178
179     if (engines.isEmpty())
180         qWarning("qmldebugger: no engines found!");
181     else {
182         const QDeclarativeDebugEngineReference engine = engines.first();
183         m_clientProxy->queryEngineContext(engine.debugId());
184     }
185 }
186
187 void Inspector::changeSelectedItems(const QList<QDeclarativeDebugObjectReference> &objects)
188 {
189     m_clientProxy->setSelectedItemsByObjectId(objects);
190 }
191
192 void Inspector::shutdown()
193 {
194 //#warning save the inspector settings here
195 }
196
197 void Inspector::pollInspector()
198 {
199     ++m_connectionAttempts;
200
201     const QString host = m_runConfigurationDebugData.serverAddress;
202     const quint16 port = quint16(m_runConfigurationDebugData.serverPort);
203
204     if (m_clientProxy->connectToViewer(host, port)) {
205         m_textPreview->updateDocuments();
206         m_connectionTimer->stop();
207         m_connectionAttempts = 0;
208     } else if (m_connectionAttempts == MaxConnectionAttempts) {
209         m_connectionTimer->stop();
210         m_connectionAttempts = 0;
211
212         QMessageBox::critical(0,
213                               tr("Failed to connect to debugger"),
214                               tr("Could not connect to debugger server.") );
215     }
216     updateMenuActions();
217 }
218
219 bool Inspector::setDebugConfigurationDataFromProject(ProjectExplorer::Project *projectToDebug)
220 {
221     if (!projectToDebug) {
222         emit statusMessage(tr("Invalid project, debugging canceled."));
223         return false;
224     }
225
226     QmlProjectManager::QmlProjectRunConfiguration* config =
227             qobject_cast<QmlProjectManager::QmlProjectRunConfiguration*>(projectToDebug->activeTarget()->activeRunConfiguration());
228     if (!config) {
229         emit statusMessage(tr("Cannot find project run configuration, debugging canceled."));
230         return false;
231     }
232     m_runConfigurationDebugData.serverAddress = config->debugServerAddress();
233     m_runConfigurationDebugData.serverPort = config->debugServerPort();
234     m_connectionTimer->setInterval(ConnectionAttemptDefaultInterval);
235
236     return true;
237 }
238
239 void Inspector::startQmlProjectDebugger()
240 {
241     m_simultaneousCppAndQmlDebugMode = false;
242     m_connectionTimer->start();
243 }
244
245 void Inspector::resetViews()
246 {
247 //#warning reset the views here
248 }
249
250 void Inspector::simultaneouslyDebugQmlCppApplication()
251 {
252     QString errorMessage;
253     ProjectExplorer::ProjectExplorerPlugin *pex = ProjectExplorer::ProjectExplorerPlugin::instance();
254     ProjectExplorer::Project *project = pex->startupProject();
255
256     if (!project)
257          errorMessage = tr("No project was found.");
258     else if (project->id() == QLatin1String("QmlProjectManager.QmlProject"))
259         errorMessage = attachToQmlViewerAsExternalApp(project);
260     else
261         errorMessage = attachToExternalCppAppWithQml(project);
262
263     if (!errorMessage.isEmpty())
264         QMessageBox::warning(Core::ICore::instance()->mainWindow(), tr("Failed to debug C++ and QML"), errorMessage);
265 }
266
267 QString Inspector::attachToQmlViewerAsExternalApp(ProjectExplorer::Project *project)
268 {
269     Q_UNUSED(project);
270
271
272 //#warning implement attachToQmlViewerAsExternalApp
273     return QString();
274
275
276 #if 0
277     m_debugMode = QmlProjectWithCppPlugins;
278
279     QmlProjectManager::QmlProjectRunConfiguration* runConfig =
280                 qobject_cast<QmlProjectManager::QmlProjectRunConfiguration*>(project->activeTarget()->activeRunConfiguration());
281
282     if (!runConfig)
283         return tr("No run configurations were found for the project '%1'.").arg(project->displayName());
284
285     Internal::StartExternalQmlDialog dlg(Debugger::DebuggerUISwitcher::instance()->mainWindow());
286
287     QString importPathArgument = "-I";
288     QString execArgs;
289     if (runConfig->viewerArguments().contains(importPathArgument))
290         execArgs = runConfig->viewerArguments().join(" ");
291     else {
292         QFileInfo qmlFileInfo(runConfig->viewerArguments().last());
293         importPathArgument.append(" " + qmlFileInfo.absolutePath() + " ");
294         execArgs = importPathArgument + runConfig->viewerArguments().join(" ");
295     }
296
297
298     dlg.setPort(runConfig->debugServerPort());
299     dlg.setDebuggerUrl(runConfig->debugServerAddress());
300     dlg.setProjectDisplayName(project->displayName());
301     dlg.setDebugMode(Internal::StartExternalQmlDialog::QmlProjectWithCppPlugins);
302     dlg.setQmlViewerArguments(execArgs);
303     dlg.setQmlViewerPath(runConfig->viewerPath());
304
305     if (dlg.exec() != QDialog::Accepted)
306         return QString();
307
308     m_runConfigurationDebugData.serverAddress = dlg.debuggerUrl();
309     m_runConfigurationDebugData.serverPort = dlg.port();
310     m_settings.setExternalPort(dlg.port());
311     m_settings.setExternalUrl(dlg.debuggerUrl());
312
313     ProjectExplorer::Environment customEnv = ProjectExplorer::Environment::systemEnvironment(); // empty env by default
314     customEnv.set(QmlProjectManager::Constants::E_QML_DEBUG_SERVER_PORT, QString::number(m_settings.externalPort()));
315
316     Debugger::DebuggerRunControl *debuggableRunControl =
317      createDebuggerRunControl(runConfig, dlg.qmlViewerPath(), dlg.qmlViewerArguments());
318
319     return executeDebuggerRunControl(debuggableRunControl, &customEnv);
320 #endif
321 }
322
323 QString Inspector::attachToExternalCppAppWithQml(ProjectExplorer::Project *project)
324 {
325     Q_UNUSED(project);
326 //#warning implement attachToExternalCppAppWithQml
327
328     return QString();
329
330 #if 0
331     m_debugMode = CppProjectWithQmlEngines;
332
333     ProjectExplorer::LocalApplicationRunConfiguration* runConfig =
334                 qobject_cast<ProjectExplorer::LocalApplicationRunConfiguration*>(project->activeTarget()->activeRunConfiguration());
335
336     if (!project->activeTarget() || !project->activeTarget()->activeRunConfiguration())
337         return tr("No run configurations were found for the project '%1'.").arg(project->displayName());
338     else if (!runConfig)
339         return tr("No valid run configuration was found for the project %1. "
340                                   "Only locally runnable configurations are supported.\n"
341                                   "Please check your project settings.").arg(project->displayName());
342
343     Internal::StartExternalQmlDialog dlg(Debugger::DebuggerUISwitcher::instance()->mainWindow());
344
345     dlg.setPort(m_settings.externalPort());
346     dlg.setDebuggerUrl(m_settings.externalUrl());
347     dlg.setProjectDisplayName(project->displayName());
348     dlg.setDebugMode(Internal::StartExternalQmlDialog::CppProjectWithQmlEngine);
349     if (dlg.exec() != QDialog::Accepted)
350         return QString();
351
352     m_runConfigurationDebugData.serverAddress = dlg.debuggerUrl();
353     m_runConfigurationDebugData.serverPort = dlg.port();
354     m_settings.setExternalPort(dlg.port());
355     m_settings.setExternalUrl(dlg.debuggerUrl());
356
357     ProjectExplorer::Environment customEnv = runConfig->environment();
358     customEnv.set(QmlProjectManager::Constants::E_QML_DEBUG_SERVER_PORT, QString::number(m_settings.externalPort()));
359     Debugger::DebuggerRunControl *debuggableRunControl = createDebuggerRunControl(runConfig);
360     return executeDebuggerRunControl(debuggableRunControl, &customEnv);
361 #endif
362 }
363
364 QString Inspector::executeDebuggerRunControl(Debugger::DebuggerRunControl *debuggableRunControl,
365                                              ProjectExplorer::Environment *environment)
366 {
367     Q_UNUSED(debuggableRunControl);
368     Q_UNUSED(environment);
369     ProjectExplorer::ProjectExplorerPlugin *pex = ProjectExplorer::ProjectExplorerPlugin::instance();
370
371     // to make sure we have a valid, debuggable run control, find the correct factory for it
372     if (debuggableRunControl) {
373
374         // modify the env
375         debuggableRunControl->setCustomEnvironment(*environment);
376
377         pex->startRunControl(debuggableRunControl, ProjectExplorer::Constants::DEBUGMODE);
378         m_simultaneousCppAndQmlDebugMode = true;
379
380         return QString();
381     }
382     return tr("A valid run control was not registered in Qt Creator for this project run configuration.");
383 }
384
385 Debugger::DebuggerRunControl *Inspector::createDebuggerRunControl(ProjectExplorer::RunConfiguration *runConfig,
386                                                                   const QString &executableFile,
387                                                                   const QString &executableArguments)
388 {
389     ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
390     const QList<Debugger::DebuggerRunControlFactory *> factories = pm->getObjects<Debugger::DebuggerRunControlFactory>();
391     ProjectExplorer::RunControl *runControl = 0;
392
393     if (m_debugMode == QmlProjectWithCppPlugins) {
394         Debugger::DebuggerStartParameters sp;
395         sp.startMode = Debugger::StartExternal;
396         sp.executable = executableFile;
397         sp.processArgs = executableArguments.split(QLatin1Char(' '));
398         runControl = factories.first()->create(sp);
399         return qobject_cast<Debugger::DebuggerRunControl *>(runControl);
400     }
401
402     if (m_debugMode == CppProjectWithQmlEngines) {
403         if (factories.length() && factories.first()->canRun(runConfig, ProjectExplorer::Constants::DEBUGMODE)) {
404             runControl = factories.first()->create(runConfig, ProjectExplorer::Constants::DEBUGMODE);
405             return qobject_cast<Debugger::DebuggerRunControl *>(runControl);
406         }
407     }
408
409     return 0;
410 }
411
412 void Inspector::connected(QDeclarativeEngineDebug *client)
413 {
414     m_client = client;
415     resetViews();
416 }
417
418 void Inspector::updateMenuActions()
419 {
420     bool enabled = true;
421     if (m_simultaneousCppAndQmlDebugMode)
422         enabled = (m_cppDebuggerState == Debugger::DebuggerNotReady && m_clientProxy->isUnconnected());
423     else
424         enabled = m_clientProxy->isUnconnected();
425 }
426
427 void Inspector::debuggerStateChanged(int newState)
428 {
429     if (m_simultaneousCppAndQmlDebugMode) {
430         switch(newState) {
431         case Debugger::EngineStarting:
432             {
433                 m_connectionInitialized = false;
434                 break;
435             }
436         case Debugger::EngineStartFailed:
437         case Debugger::InferiorStartFailed:
438             emit statusMessage(tr("Debugging failed: could not start C++ debugger."));
439             break;
440         case Debugger::InferiorRunningRequested:
441             {
442                 if (m_cppDebuggerState == Debugger::InferiorStopped) {
443                     // re-enable UI again
444 //#warning enable the UI here
445                 }
446                 break;
447             }
448         case Debugger::InferiorRunning:
449             {
450                 if (!m_connectionInitialized) {
451                     m_connectionInitialized = true;
452                     m_connectionTimer->setInterval(ConnectionAttemptSimultaneousInterval);
453                     m_connectionTimer->start();
454                 }
455                 break;
456             }
457         case Debugger::InferiorStopped:
458             {
459 //#warning disable the UI here
460                 break;
461             }
462         case Debugger::EngineShuttingDown:
463             {
464                 m_connectionInitialized = false;
465                 // here it's safe to enable the debugger windows again -
466                 // disabled ones look ugly.
467 //#warning enable the UI here
468                 m_simultaneousCppAndQmlDebugMode = false;
469                 break;
470             }
471         default:
472             break;
473         }
474     }
475
476     m_cppDebuggerState = newState;
477     updateMenuActions();
478 }
479
480 void Inspector::reloadQmlViewer()
481 {
482     m_clientProxy->reloadQmlViewer();
483 }
484
485 void Inspector::setSimpleDockWidgetArrangement()
486 {
487 #if 0
488     Utils::FancyMainWindow *mainWindow = Debugger::DebuggerUISwitcher::instance()->mainWindow();
489
490     mainWindow->setTrackingEnabled(false);
491     QList<QDockWidget *> dockWidgets = mainWindow->dockWidgets();
492     foreach (QDockWidget *dockWidget, dockWidgets) {
493         if (m_dockWidgets.contains(dockWidget)) {
494             dockWidget->setFloating(false);
495             mainWindow->removeDockWidget(dockWidget);
496         }
497     }
498
499     foreach (QDockWidget *dockWidget, dockWidgets) {
500         if (m_dockWidgets.contains(dockWidget)) {
501             mainWindow->addDockWidget(Qt::BottomDockWidgetArea, dockWidget);
502             dockWidget->show();
503         }
504     }
505     mainWindow->splitDockWidget(mainWindow->toolBarDockWidget(), m_propertyWatcherDock, Qt::Vertical);
506     //mainWindow->tabifyDockWidget(m_frameRateDock, m_propertyWatcherDock);
507     mainWindow->tabifyDockWidget(m_propertyWatcherDock, m_expressionQueryDock);
508     mainWindow->tabifyDockWidget(m_propertyWatcherDock, m_inspectorOutputDock);
509     m_propertyWatcherDock->raise();
510
511     m_inspectorOutputDock->setVisible(false);
512
513     mainWindow->setTrackingEnabled(true);
514 #endif
515 }
516
517 void Inspector::setSelectedItemsByObjectReference(QList<QDeclarativeDebugObjectReference> objectReferences)
518 {
519     if (objectReferences.length())
520         gotoObjectReferenceDefinition(objectReferences.first());
521 }
522
523 void Inspector::gotoObjectReferenceDefinition(const QDeclarativeDebugObjectReference &obj)
524 {
525     Q_UNUSED(obj);
526
527     QDeclarativeDebugFileReference source = obj.source();
528     const QString fileName = source.url().toLocalFile();
529
530     if (source.lineNumber() < 0 || !QFile::exists(fileName))
531         return;
532
533     Core::EditorManager *editorManager = Core::EditorManager::instance();
534     Core::IEditor *editor = editorManager->openEditor(fileName, QString(), Core::EditorManager::NoModeSwitch);
535     TextEditor::ITextEditor *textEditor = qobject_cast<TextEditor::ITextEditor*>(editor);
536
537     if (textEditor) {
538         editorManager->addCurrentPositionToNavigationHistory();
539         textEditor->gotoLine(source.lineNumber());
540         textEditor->widget()->setFocus();
541     }
542 }
543
544 QDeclarativeDebugExpressionQuery *Inspector::executeExpression(int objectDebugId, const QString &objectId,
545                                                                const QString &propertyName, const QVariant &value)
546 {
547     if (objectId.length()) {
548         QString quoteWrappedValue = value.toString();
549         if (addQuotesForData(value))
550             quoteWrappedValue = QString("'%1'").arg(quoteWrappedValue); // ### FIXME this code is wrong!
551
552         QString constructedExpression = objectId + "." + propertyName + "=" + quoteWrappedValue;
553         return m_client.data()->queryExpressionResult(objectDebugId, constructedExpression, this);
554     }
555
556     return 0;
557 }
558
559 bool Inspector::addQuotesForData(const QVariant &value) const
560 {
561     switch (value.type()) {
562     case QVariant::String:
563     case QVariant::Color:
564     case QVariant::Date:
565         return true;
566     default:
567         break;
568     }
569
570     return false;
571 }
572
573 /*!
574    Associates the UiObjectMember* to their QDeclarativeDebugObjectReference.
575  */
576 class MapObjectWithDebugReference : public Visitor
577 {
578     public:
579         virtual void endVisit(UiObjectDefinition *ast) ;
580         virtual void endVisit(UiObjectBinding *ast) ;
581
582         QDeclarativeDebugObjectReference root;
583         QString filename;
584         QHash<UiObjectMember *, QList<QDeclarativeDebugObjectReference> > result;
585     private:
586         void processRecursive(const QDeclarativeDebugObjectReference &object, UiObjectMember *ast);
587 };
588
589 void MapObjectWithDebugReference::endVisit(UiObjectDefinition* ast)
590 {
591     if (ast->qualifiedTypeNameId->name->asString().at(0).isUpper())
592         processRecursive(root, ast);
593 }
594 void MapObjectWithDebugReference::endVisit(UiObjectBinding* ast)
595 {
596     if (ast->qualifiedId->name->asString().at(0).isUpper())
597         processRecursive(root, ast);
598 }
599
600 void MapObjectWithDebugReference::processRecursive(const QDeclarativeDebugObjectReference& object, UiObjectMember* ast)
601 {
602     // If this is too slow, it can be speed up by indexing
603     // the QDeclarativeDebugObjectReference by filename/loc in a fist pass
604
605     SourceLocation loc = ast->firstSourceLocation();
606     if (object.source().lineNumber() == int(loc.startLine) && object.source().columnNumber() == int(loc.startColumn) && object.source().url().toLocalFile() == filename) {
607         result[ast] += object;
608     }
609
610     foreach (const QDeclarativeDebugObjectReference &it, object.children()) {
611         processRecursive(it, ast);
612     }
613 }
614
615 void QmlJSInspector::Internal::Inspector::objectTreeUpdated(const QDeclarativeDebugObjectReference &ref)
616 {
617     QmlJS::ModelManagerInterface *m = QmlJS::ModelManagerInterface::instance();
618     Snapshot snapshot = m->snapshot();
619     QHash<QString, QHash<UiObjectMember *, QList< QDeclarativeDebugObjectReference> > > allDebugIds;
620     foreach(const Document::Ptr &doc, snapshot) {
621         if (!doc->qmlProgram())
622             continue;
623         MapObjectWithDebugReference visitor;
624         visitor.root = ref;
625         QString filename = doc->fileName();
626         visitor.filename = filename;
627         doc->qmlProgram()->accept(&visitor);
628         allDebugIds[filename] = visitor.result;
629     }
630
631     //FIXME
632     m_textPreview->m_initialTable = allDebugIds;
633     m_textPreview->m_debugIds.clear();
634 }