diff options
author | Kai Koehne <kai.koehne@nokia.com> | 2012-04-18 14:20:54 +0200 |
---|---|---|
committer | Kai Koehne <kai.koehne@nokia.com> | 2012-05-09 12:42:44 +0200 |
commit | 7f09d0b756ff3f9bb52737d4aaf65ed84d751316 (patch) | |
tree | 7469486e35fd0b6a3e7c4e7e8775f75784c414fd /src/plugins | |
parent | d201c681daae42b005c9ea4f3a1e272ea9cc5ef5 (diff) | |
download | qt-creator-7f09d0b756ff3f9bb52737d4aaf65ed84d751316.tar.gz |
Merge QML inspector into debugger plugin
Merge QmlJSInspector plugin into the debugger. Also merge the
extra Inspector window with the Locals & Watchers: It now shows
the QML object tree in the running state.
Change-Id: I59ae0c1b970a48ba10ecda92ed3ba765d94b1d9c
Reviewed-by: Aurindam Jana <aurindam.jana@nokia.com>
Diffstat (limited to 'src/plugins')
75 files changed, 2484 insertions, 6233 deletions
diff --git a/src/plugins/debugger/Debugger.pluginspec.in b/src/plugins/debugger/Debugger.pluginspec.in index 77d13834f8..a2b6521ae6 100644 --- a/src/plugins/debugger/Debugger.pluginspec.in +++ b/src/plugins/debugger/Debugger.pluginspec.in @@ -18,6 +18,7 @@ Alternatively, this plugin may be used under the terms of the GNU Lesser General <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/> <dependency name=\"Find\" version=\"$$QTCREATOR_VERSION\"/> <dependency name=\"CppTools\" version=\"$$QTCREATOR_VERSION\"/> + <dependency name=\"QmlJSTools\" version=\"$$QTCREATOR_VERSION\"/> <!-- Debugger plugin adds items to the editor\'s context menu --> <dependency name=\"CppEditor\" version=\"$$QTCREATOR_VERSION\" type=\"optional\"/> </dependencyList> diff --git a/src/plugins/debugger/commonoptionspage.cpp b/src/plugins/debugger/commonoptionspage.cpp index f8eb6db6b7..4bd4512b9a 100644 --- a/src/plugins/debugger/commonoptionspage.cpp +++ b/src/plugins/debugger/commonoptionspage.cpp @@ -74,6 +74,8 @@ CommonOptionsPageWidget::CommonOptionsPageWidget m_ui.checkBoxSwitchModeOnExit); m_group->insert(dc->action(RaiseOnInterrupt), m_ui.checkBoxBringToForegroundOnInterrrupt); + m_group->insert(dc->action(ShowQmlObjectTree), + m_ui.checkBoxShowQmlObjectTree); m_group->insert(dc->action(FontSizeFollowsEditor), m_ui.checkBoxFontSizeFollowsEditor); m_group->insert(dc->action(AutoDerefPointers), 0); @@ -123,6 +125,7 @@ QString CommonOptionsPageWidget::searchKeyWords() const << sep << m_ui.checkBoxSwitchModeOnExit->text() << sep << m_ui.labelMaximalStackDepth->text() << sep << m_ui.checkBoxBringToForegroundOnInterrrupt->text() + << sep << m_ui.checkBoxShowQmlObjectTree->text() ; rc.remove(QLatin1Char('&')); return rc; diff --git a/src/plugins/debugger/commonoptionspage.ui b/src/plugins/debugger/commonoptionspage.ui index b44f2f36cb..548ed122da 100644 --- a/src/plugins/debugger/commonoptionspage.ui +++ b/src/plugins/debugger/commonoptionspage.ui @@ -120,7 +120,14 @@ </item> </layout> </item> - <item row="3" column="1"> + <item row="3" column="0"> + <widget class="QCheckBox" name="checkBoxBringToForegroundOnInterrrupt"> + <property name="text"> + <string>Bring Qt Creator to foreground when application interrupts</string> + </property> + </widget> + </item> + <item row="4" column="1"> <widget class="QCheckBox" name="checkBoxRegisterForPostMortem"> <property name="toolTip"> <string>Register Qt Creator for debugging crashed applications.</string> @@ -130,10 +137,13 @@ </property> </widget> </item> - <item row="3" column="0"> - <widget class="QCheckBox" name="checkBoxBringToForegroundOnInterrrupt"> + <item row="3" column="1"> + <widget class="QCheckBox" name="checkBoxShowQmlObjectTree"> + <property name="toolTip"> + <string>Show QML object tree in Locals & Expressions when connected and not stepping.</string> + </property> <property name="text"> - <string>Bring Qt Creator to foreground when application interrupts</string> + <string>Show QML object tree</string> </property> </widget> </item> diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro index 733253a984..9a5775678f 100644 --- a/src/plugins/debugger/debugger.pro +++ b/src/plugins/debugger/debugger.pro @@ -72,7 +72,8 @@ HEADERS += \ qtmessagelogview.h \ qtmessagelogproxymodel.h \ qtmessagelogitemdelegate.h \ - qtmessageloghandler.h + qtmessageloghandler.h \ + localsandwatcherswindow.h SOURCES += \ basewindow.cpp \ @@ -123,7 +124,8 @@ SOURCES += \ qtmessagelogview.cpp \ qtmessagelogitemdelegate.cpp \ qtmessageloghandler.cpp \ - qtmessagelogeditor.cpp + qtmessagelogeditor.cpp \ + localsandwatcherswindow.cpp FORMS += attachexternaldialog.ui \ attachcoredialog.ui \ diff --git a/src/plugins/debugger/debugger.qbs b/src/plugins/debugger/debugger.qbs index 3f4bb75a11..7ef41a72fe 100644 --- a/src/plugins/debugger/debugger.qbs +++ b/src/plugins/debugger/debugger.qbs @@ -8,6 +8,7 @@ QtcPlugin { Depends { name: "qt"; submodules: ['widgets', 'network', 'script'] } Depends { name: "Core" } Depends { name: "CppTools" } + Depends { name: "QmlJSTools" } Depends { name: "Find" } Depends { name: "ProjectExplorer" } Depends { name: "TextEditor" } @@ -75,6 +76,8 @@ QtcPlugin { "disassemblerlines.cpp", "disassemblerlines.h", "dumperoptionpage.ui", + "localsandwatcherswindow.cpp", + "localsandwatcherswindow.h", "logwindow.cpp", "logwindow.h", "memoryagent.cpp", @@ -243,6 +246,12 @@ QtcPlugin { "qml/qscriptdebuggerclient.cpp", "qml/qmlv8debuggerclient.cpp", "qml/interactiveinterpreter.cpp", + "qml/qmlinspectoradapter.cpp", + "qml/qmlinspectoradapter.h", + "qml/qmlinspectoragent.cpp", + "qml/qmlinspectoragent.h", + "qml/qmllivetextpreview.cpp", + "qml/qmllivetextpreview.h", "script/scriptengine.cpp", "script/scriptengine.h", "shared/backtrace.cpp", diff --git a/src/plugins/debugger/debugger.qrc b/src/plugins/debugger/debugger.qrc index e1bf571107..a75fb1625e 100644 --- a/src/plugins/debugger/debugger.qrc +++ b/src/plugins/debugger/debugger.qrc @@ -36,5 +36,9 @@ <file>images/log.png</file> <file>images/prompt.png</file> <file>images/warning.png</file> + <file>images/qml/zoom.png</file> + <file>images/qml/select.png</file> + <file>images/qml/app-on-top.png</file> + <file>images/qml/apply-on-save.png</file> </qresource> </RCC> diff --git a/src/plugins/debugger/debugger_dependencies.pri b/src/plugins/debugger/debugger_dependencies.pri index 699f3d3ece..0fcdf49d33 100644 --- a/src/plugins/debugger/debugger_dependencies.pri +++ b/src/plugins/debugger/debugger_dependencies.pri @@ -3,6 +3,7 @@ include(../../plugins/cpptools/cpptools.pri) include(../../plugins/find/find.pri) include(../../plugins/projectexplorer/projectexplorer.pri) include(../../plugins/texteditor/texteditor.pri) +include(../../plugins/qmljstools/qmljstools.pri) include(../../libs/cplusplus/cplusplus.pri) include(../../libs/utils/utils.pri) include(../../libs/symbianutils/symbianutils.pri) diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp index 7095ee809a..5b76a71b0e 100644 --- a/src/plugins/debugger/debuggeractions.cpp +++ b/src/plugins/debugger/debuggeractions.cpp @@ -549,6 +549,30 @@ DebuggerSettings::DebuggerSettings(QSettings *settings) item->setSettingsKey(debugModeGroup, QLatin1String("WatchdogTimeout")); item->setDefaultValue(20); insertItem(GdbWatchdogTimeout, item); + + // + // QML Tools + // + item = new SavedAction(this); + item->setSettingsKey(debugModeGroup, QLatin1String("ShowQmlObjectTree")); + item->setDefaultValue(true); + insertItem(ShowQmlObjectTree, item); + + item = new SavedAction(this); + item->setSettingsKey("QML.Inspector", QLatin1String("QmlInspector.ShowAppOnTop")); + item->setText(tr("Show Application On Top")); + item->setCheckable(true); + item->setDefaultValue(false); + item->setIcon(QIcon(QLatin1String(":/debugger/images/qml/app-on-top.png"))); + insertItem(ShowAppOnTop, item); + + item = new SavedAction(this); + item->setSettingsKey("QML.Inspector", QLatin1String("QmlInspector.FromQml")); + item->setText(tr("Apply Changes on Save")); + item->setCheckable(true); + item->setDefaultValue(false); + item->setIcon(QIcon(QLatin1String(":/debugger/images/qml/apply-on-save.png"))); + insertItem(QmlUpdateOnSave, item); } DebuggerSettings::~DebuggerSettings() diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h index 13f5135792..29ff7217c3 100644 --- a/src/plugins/debugger/debuggeractions.h +++ b/src/plugins/debugger/debuggeractions.h @@ -169,7 +169,12 @@ enum DebuggerActionCode AlwaysAdjustThreadsColumnWidths, // Modules - AlwaysAdjustModulesColumnWidths + AlwaysAdjustModulesColumnWidths, + + // QML Tools + ShowQmlObjectTree, + ShowAppOnTop, + QmlUpdateOnSave }; } // namespace Internal diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h index efd766b598..0bae1cc79e 100644 --- a/src/plugins/debugger/debuggerconstants.h +++ b/src/plugins/debugger/debuggerconstants.h @@ -52,7 +52,7 @@ const char G_MANUAL_REMOTE[] = "Debugger.Group.Manual.Remote"; const char G_AUTOMATIC_REMOTE[] = "Debugger.Group.Automatic.Remote"; const char G_START_QML[] = "Debugger.Group.Start.Qml"; -// Common actions (accessed by QML inspector) +// Common actions const char INTERRUPT[] = "Debugger.Interrupt"; const char CONTINUE[] = "Debugger.Continue"; const char STOP[] = "Debugger.Stop"; @@ -63,6 +63,8 @@ const char STEPOUT[] = "Debugger.StepOut"; const char NEXT[] = "Debugger.NextLine"; const char REVERSE[] = "Debugger.ReverseDirection"; const char OPERATE_BY_INSTRUCTION[] = "Debugger.OperateByInstruction"; +const char QML_SELECTTOOL[] = "Debugger.QmlSelectTool"; +const char QML_ZOOMTOOL[] = "Debugger.QmlZoomTool"; // DebuggerMainWindow dock widget names const char DOCKWIDGET_BREAK[] = "Debugger.Docks.Break"; diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index 563b5d248e..e838dbed96 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -513,6 +513,14 @@ QAbstractItemModel *DebuggerEngine::returnModel() const return model; } +QAbstractItemModel *DebuggerEngine::inspectorModel() const +{ + QAbstractItemModel *model = watchHandler()->model(InspectWatch); + if (model->objectName().isEmpty()) // Make debugging easier. + model->setObjectName(objectName() + QLatin1String("InspectorModel")); + return model; +} + QAbstractItemModel *DebuggerEngine::toolTipsModel() const { QAbstractItemModel *model = watchHandler()->model(TooltipsWatch); diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h index 13141e606a..76089e425b 100644 --- a/src/plugins/debugger/debuggerengine.h +++ b/src/plugins/debugger/debuggerengine.h @@ -75,6 +75,7 @@ class SourceFilesHandler; class ThreadsHandler; class WatchHandler; class BreakpointParameters; +class QmlAdapter; class QmlCppEngine; class DebuggerToolTipContext; class MemoryMarkup; @@ -231,6 +232,7 @@ public: virtual QAbstractItemModel *localsModel() const; virtual QAbstractItemModel *watchersModel() const; virtual QAbstractItemModel *returnModel() const; + virtual QAbstractItemModel *inspectorModel() const; virtual QAbstractItemModel *toolTipsModel() const; virtual QAbstractItemModel *sourceFilesModel() const; virtual QAbstractItemModel *qtMessageLogModel() const; @@ -408,7 +410,7 @@ private: // Wrapper engine needs access to state of its subengines. friend class Internal::QmlCppEngine; friend class Internal::DebuggerPluginPrivate; - friend class QmlAdapter; + friend class Internal::QmlAdapter; virtual void setState(DebuggerState state, bool forced = false); diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index fc42b270a1..74a6489b3f 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -62,6 +62,7 @@ #include "watchwindow.h" #include "watchutils.h" #include "debuggertooltipmanager.h" +#include "localsandwatcherswindow.h" #include "snapshothandler.h" #include "threadshandler.h" @@ -1119,6 +1120,10 @@ public slots: void attachedToProcess(const QString &channel, const QString &sysroot, const QString &remoteCommandLine, const QString &remoteExecutable); + void updateQmlActions() { + action(QmlUpdateOnSave)->setEnabled(boolSetting(ShowQmlObjectTree)); + } + public: DebuggerMainWindow *m_mainWindow; DebuggerRunControlFactory *m_debuggerRunControlFactory; @@ -1177,6 +1182,7 @@ public: WatchWindow *m_returnWindow; WatchWindow *m_localsWindow; WatchWindow *m_watchersWindow; + WatchWindow *m_inspectorWindow; BaseWindow *m_registerWindow; BaseWindow *m_modulesWindow; BaseWindow *m_snapshotWindow; @@ -1184,6 +1190,7 @@ public: BaseWindow *m_stackWindow; BaseWindow *m_threadsWindow; LogWindow *m_logWindow; + LocalsAndWatchersWindow *m_localsAndWatchersWindow; bool m_busy; QString m_lastPermanentStatusMessage; @@ -1230,6 +1237,7 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(DebuggerPlugin *plugin) : m_returnWindow = 0; m_localsWindow = 0; m_watchersWindow = 0; + m_inspectorWindow = 0; m_registerWindow = 0; m_modulesWindow = 0; m_snapshotWindow = 0; @@ -1237,6 +1245,7 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(DebuggerPlugin *plugin) : m_stackWindow = 0; m_threadsWindow = 0; m_logWindow = 0; + m_localsAndWatchersWindow = 0; m_qtMessageLogWindow = 0; m_mainWindow = 0; @@ -2130,6 +2139,7 @@ void DebuggerPluginPrivate::connectEngine(DebuggerEngine *engine) //m_threadBox->setModel(engine->threadsModel()); //m_threadBox->setModelColumn(ThreadData::ComboNameColumn); m_watchersWindow->setModel(engine->watchersModel()); + m_inspectorWindow->setModel(engine->inspectorModel()); m_qtMessageLogWindow->setModel(engine->qtMessageLogModel()); engine->watchHandler()->rebuildModel(); @@ -2162,6 +2172,7 @@ void DebuggerPluginPrivate::fontSettingsChanged changeFontSize(m_stackWindow, size); changeFontSize(m_threadsWindow, size); changeFontSize(m_watchersWindow, size); + changeFontSize(m_inspectorWindow, size); } void DebuggerPluginPrivate::cleanupViews() @@ -2261,7 +2272,7 @@ void DebuggerPluginPrivate::updateWatchersWindow() m_watchersWindow->setVisible( m_watchersWindow->model()->rowCount(QModelIndex()) > 0); m_returnWindow->setVisible( - m_returnWindow->model()->rowCount(QModelIndex()) > 0); + m_returnWindow->model()->rowCount(QModelIndex()) > 0); } void DebuggerPluginPrivate::updateState(DebuggerEngine *engine) @@ -2305,6 +2316,7 @@ void DebuggerPluginPrivate::updateState(DebuggerEngine *engine) m_debugWithoutDeployAction->setEnabled(false); m_visibleStartAction->setAction(m_continueAction); m_hiddenStopAction->setAction(m_exitAction); + m_localsAndWatchersWindow->setShowLocals(true); } else if (state == InferiorRunOk) { // Shift-F5 interrupts. It is also "interruptible". m_interruptAction->setEnabled(true); @@ -2314,6 +2326,7 @@ void DebuggerPluginPrivate::updateState(DebuggerEngine *engine) m_debugWithoutDeployAction->setEnabled(false); m_visibleStartAction->setAction(m_interruptAction); m_hiddenStopAction->setAction(m_interruptAction); + m_localsAndWatchersWindow->setShowLocals(false); } else if (state == DebuggerFinished) { // We don't want to do anything anymore. m_interruptAction->setEnabled(false); @@ -2403,7 +2416,6 @@ void DebuggerPluginPrivate::updateState(DebuggerEngine *engine) || state == DebuggerFinished || state == InferiorUnrunnable; setBusyCursor(!notbusy); - } void DebuggerPluginPrivate::updateDebugActions() @@ -2927,6 +2939,8 @@ void DebuggerPluginPrivate::extensionsInitialized() m_localsWindow->setObjectName(QLatin1String("CppDebugLocals")); m_watchersWindow = new WatchWindow(WatchTreeView::WatchersType); m_watchersWindow->setObjectName(QLatin1String("CppDebugWatchers")); + m_inspectorWindow = new WatchWindow(WatchTreeView::InspectType); + m_inspectorWindow->setObjectName(QLatin1String("Inspector")); // Snapshot m_snapshotHandler = new SnapshotHandler; @@ -3018,6 +3032,22 @@ void DebuggerPluginPrivate::extensionsInitialized() connect(action(OperateByInstruction), SIGNAL(triggered(bool)), SLOT(handleOperateByInstructionTriggered(bool))); + QAction *qmlSelectDummyAction = new QAction(tr("Select"), this); + qmlSelectDummyAction->setCheckable(true); + qmlSelectDummyAction->setIcon(QIcon(_(":/debugger/images/qml/select.png"))); + qmlSelectDummyAction->setEnabled(false); + Core::Command *qmlSelectCommand + = am->registerAction(qmlSelectDummyAction, QML_SELECTTOOL, + globalcontext); + + QAction *qmlZoomDummyAction = new QAction(tr("Zoom"), this); + qmlZoomDummyAction->setCheckable(true); + qmlZoomDummyAction->setIcon(QIcon(_(":/debugger/images/qml/zoom.png"))); + qmlZoomDummyAction->setEnabled(false); + Core::Command *qmlZoomCommand + = am->registerAction(qmlZoomDummyAction, QML_ZOOMTOOL, + globalcontext); + ActionContainer *debugMenu = am->actionContainer(ProjectExplorer::Constants::M_DEBUG); @@ -3044,17 +3074,13 @@ void DebuggerPluginPrivate::extensionsInitialized() m_mainWindow->createDockWidget(CppLanguage, m_stackWindow); m_mainWindow->createDockWidget(CppLanguage, m_threadsWindow); - QSplitter *localsAndWatchers = new MiniSplitter(Qt::Vertical); - localsAndWatchers->setObjectName(QLatin1String(DOCKWIDGET_WATCHERS)); - localsAndWatchers->setWindowTitle(m_localsWindow->windowTitle()); - localsAndWatchers->addWidget(m_localsWindow); - localsAndWatchers->addWidget(m_returnWindow); - localsAndWatchers->addWidget(m_watchersWindow); - localsAndWatchers->setStretchFactor(0, 3); - localsAndWatchers->setStretchFactor(1, 1); - localsAndWatchers->setStretchFactor(2, 1); - - dock = m_mainWindow->createDockWidget(CppLanguage, localsAndWatchers); + m_localsAndWatchersWindow = new LocalsAndWatchersWindow( + m_localsWindow, m_inspectorWindow, m_returnWindow, + m_watchersWindow); + m_localsAndWatchersWindow->setObjectName(QLatin1String(DOCKWIDGET_WATCHERS)); + m_localsAndWatchersWindow->setWindowTitle(m_localsWindow->windowTitle()); + + dock = m_mainWindow->createDockWidget(CppLanguage, m_localsAndWatchersWindow); dock->setProperty(DOCKWIDGET_DEFAULT_AREA, Qt::RightDockWidgetArea); m_mainWindow->addStagedMenuEntries(); @@ -3443,6 +3469,11 @@ void DebuggerPluginPrivate::extensionsInitialized() connect(action(SettingsDialog), SIGNAL(triggered()), SLOT(showSettingsDialog())); + // QML Actions + connect(action(ShowQmlObjectTree), SIGNAL(valueChanged(QVariant)), + SLOT(updateQmlActions())); + updateQmlActions(); + // Toolbar QWidget *toolbarContainer = new QWidget; @@ -3472,6 +3503,19 @@ void DebuggerPluginPrivate::extensionsInitialized() hbox->addSpacerItem(new QSpacerItem(4, 0)); m_mainWindow->setToolBar(CppLanguage, toolbarContainer); + + QWidget *qmlToolbar = new QWidget; + hbox = new QHBoxLayout(qmlToolbar); + hbox->setMargin(0); + hbox->setSpacing(0); + hbox->addWidget(toolButton(action(QmlUpdateOnSave))); + hbox->addWidget(toolButton(action(ShowAppOnTop))); + hbox->addWidget(new Utils::StyledSeparator); + hbox->addWidget(toolButton(qmlSelectCommand->action())); + hbox->addWidget(toolButton(qmlZoomCommand->action())); + hbox->addWidget(new Utils::StyledSeparator); + m_mainWindow->setToolBar(QmlLanguage, qmlToolbar); + m_mainWindow->setToolBar(AnyLanguage, m_statusLabel); connect(action(EnableReverseDebugging), diff --git a/src/plugins/qmljsinspector/images/app-on-top.png b/src/plugins/debugger/images/qml/app-on-top.png Binary files differindex ddec5400c6..ddec5400c6 100644 --- a/src/plugins/qmljsinspector/images/app-on-top.png +++ b/src/plugins/debugger/images/qml/app-on-top.png diff --git a/src/plugins/qmljsinspector/images/from-qml-small.png b/src/plugins/debugger/images/qml/apply-on-save.png Binary files differindex 666382c06d..666382c06d 100644 --- a/src/plugins/qmljsinspector/images/from-qml-small.png +++ b/src/plugins/debugger/images/qml/apply-on-save.png diff --git a/src/plugins/qmljsinspector/images/select-small.png b/src/plugins/debugger/images/qml/select.png Binary files differindex 672285582b..672285582b 100644 --- a/src/plugins/qmljsinspector/images/select-small.png +++ b/src/plugins/debugger/images/qml/select.png diff --git a/src/plugins/qmljsinspector/images/zoom-small.png b/src/plugins/debugger/images/qml/zoom.png Binary files differindex ebae877310..ebae877310 100644 --- a/src/plugins/qmljsinspector/images/zoom-small.png +++ b/src/plugins/debugger/images/qml/zoom.png diff --git a/src/plugins/debugger/localsandwatcherswindow.cpp b/src/plugins/debugger/localsandwatcherswindow.cpp new file mode 100644 index 0000000000..20e3f0379a --- /dev/null +++ b/src/plugins/debugger/localsandwatcherswindow.cpp @@ -0,0 +1,41 @@ +#include "localsandwatcherswindow.h" +#include <QVBoxLayout> +#include <QSplitter> +#include <QStackedWidget> + +namespace Debugger { +namespace Internal { + +LocalsAndWatchersWindow::LocalsAndWatchersWindow( + QWidget *locals, QWidget *inspector, QWidget *returnWidget, + QWidget *watchers, QWidget *parent) + : QWidget(parent) +{ + QVBoxLayout *layout = new QVBoxLayout(this); + layout->setMargin(0); + layout->setSpacing(0); + + m_splitter = new QSplitter(Qt::Vertical); + layout->addWidget(m_splitter); + + m_localsAndInspector = new QStackedWidget(); + m_localsAndInspector->addWidget(locals); + m_localsAndInspector->addWidget(inspector); + m_localsAndInspector->setCurrentWidget(inspector); + + m_splitter->addWidget(m_localsAndInspector); + m_splitter->addWidget(returnWidget); + m_splitter->addWidget(watchers); + + m_splitter->setStretchFactor(0, 3); + m_splitter->setStretchFactor(2, 1); + m_splitter->setStretchFactor(3, 1); +} + +void LocalsAndWatchersWindow::setShowLocals(bool showLocals) +{ + m_localsAndInspector->setCurrentIndex(showLocals ? 0 : 1); +} + +} // namespace Internal +} // namespace Debugger diff --git a/src/plugins/debugger/localsandwatcherswindow.h b/src/plugins/debugger/localsandwatcherswindow.h new file mode 100644 index 0000000000..b78c1373c6 --- /dev/null +++ b/src/plugins/debugger/localsandwatcherswindow.h @@ -0,0 +1,32 @@ +#ifndef LOCALSANDWATCHERSWIDGET_H +#define LOCALSANDWATCHERSWIDGET_H + +#include <QWidget> + +QT_BEGIN_NAMESPACE +class QSplitter; +class QStackedWidget; +QT_END_NAMESPACE + +namespace Debugger { +namespace Internal { + +class LocalsAndWatchersWindow : public QWidget +{ + Q_OBJECT +public: + explicit LocalsAndWatchersWindow( + QWidget *locals, QWidget *inspector, + QWidget *returnWidget, QWidget *watchers, QWidget *parent = 0); + + void setShowLocals(bool showLocals); + +private: + QSplitter *m_splitter; + QStackedWidget *m_localsAndInspector; +}; + +} // namespace Internal +} // namespace Debugger + +#endif // LOCALSANDWATCHERSWIDGET_H diff --git a/src/plugins/debugger/qml/qml.pri b/src/plugins/debugger/qml/qml.pri index 6ce2b3593b..c36fc83080 100644 --- a/src/plugins/debugger/qml/qml.pri +++ b/src/plugins/debugger/qml/qml.pri @@ -8,7 +8,10 @@ HEADERS += \ $$PWD/qscriptdebuggerclient.h \ $$PWD/qmlv8debuggerclient.h \ $$PWD/interactiveinterpreter.h \ - $$PWD/qmlv8debuggerclientconstants.h + $$PWD/qmlv8debuggerclientconstants.h \ + $$PWD/qmlinspectoragent.h \ + $$PWD/qmllivetextpreview.h \ + $$PWD/qmlinspectoradapter.h SOURCES += \ $$PWD/qmlengine.cpp \ @@ -17,4 +20,7 @@ SOURCES += \ $$PWD/qmlcppengine.cpp \ $$PWD/qscriptdebuggerclient.cpp \ $$PWD/qmlv8debuggerclient.cpp \ - $$PWD/interactiveinterpreter.cpp + $$PWD/interactiveinterpreter.cpp \ + $$PWD/qmlinspectoragent.cpp \ + $$PWD/qmllivetextpreview.cpp \ + $$PWD/qmlinspectoradapter.cpp diff --git a/src/plugins/debugger/qml/qmladapter.cpp b/src/plugins/debugger/qml/qmladapter.cpp index cf59e2502b..ab15ea3419 100644 --- a/src/plugins/debugger/qml/qmladapter.cpp +++ b/src/plugins/debugger/qml/qmladapter.cpp @@ -32,116 +32,80 @@ #include "qmladapter.h" -#include "qscriptdebuggerclient.h" -#include "qmlv8debuggerclient.h" - #include "qmlengine.h" +#include "qmlv8debuggerclient.h" +#include "qscriptdebuggerclient.h" -#include <extensionsystem/pluginmanager.h> -#include <utils/qtcassert.h> - -#include <qmldebug/baseenginedebugclient.h> #include <qmldebug/qdebugmessageclient.h> +#include <utils/qtcassert.h> -#include <QTimer> #include <QDebug> -#include <QWeakPointer> namespace Debugger { namespace Internal { -class QmlAdapterPrivate -{ -public: - explicit QmlAdapterPrivate(DebuggerEngine *engine) - : m_engine(engine) - , m_qmlClient(0) - , m_engineDebugClient(0) - , m_conn(0) - , m_currentSelectedDebugId(-1) - , m_msgClient(0) - { - m_connectionTimer.setInterval(4000); - m_connectionTimer.setSingleShot(true); - } - - QWeakPointer<DebuggerEngine> m_engine; - BaseQmlDebuggerClient *m_qmlClient; - BaseEngineDebugClient *m_engineDebugClient; - QTimer m_connectionTimer; - QmlDebugConnection *m_conn; - QHash<QString, BaseQmlDebuggerClient*> debugClients; - int m_currentSelectedDebugId; - QString m_currentSelectedDebugName; - QDebugMessageClient *m_msgClient; -}; - -} // namespace Internal - QmlAdapter::QmlAdapter(DebuggerEngine *engine, QObject *parent) - : QObject(parent), d(new Internal::QmlAdapterPrivate(engine)) + : QObject(parent) + , m_engine(engine) + , m_qmlClient(0) + , m_conn(0) + , m_msgClient(0) { - connect(&d->m_connectionTimer, SIGNAL(timeout()), SLOT(checkConnectionState())); - d->m_conn = new QmlDebugConnection(this); - connect(d->m_conn, SIGNAL(stateChanged(QAbstractSocket::SocketState)), + m_connectionTimer.setInterval(4000); + m_connectionTimer.setSingleShot(true); + connect(&m_connectionTimer, SIGNAL(timeout()), SLOT(checkConnectionState())); + + m_conn = new QmlDebugConnection(this); + connect(m_conn, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SLOT(connectionStateChanged())); - connect(d->m_conn, SIGNAL(error(QAbstractSocket::SocketError)), + connect(m_conn, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(connectionErrorOccurred(QAbstractSocket::SocketError))); - ExtensionSystem::PluginManager *pluginManager = - ExtensionSystem::PluginManager::instance(); - pluginManager->addObject(this); - createDebuggerClients(); - d->m_msgClient = new QDebugMessageClient(d->m_conn); - connect(d->m_msgClient, SIGNAL(newStatus(QmlDebugClient::Status)), + m_msgClient = new QDebugMessageClient(m_conn); + connect(m_msgClient, SIGNAL(newStatus(QmlDebugClient::Status)), this, SLOT(clientStatusChanged(QmlDebugClient::Status))); + } QmlAdapter::~QmlAdapter() { - ExtensionSystem::PluginManager *pluginManager = - ExtensionSystem::PluginManager::instance(); - - if (pluginManager->allObjects().contains(this)) - pluginManager->removeObject(this); - delete d; } void QmlAdapter::beginConnectionTcp(const QString &address, quint16 port) { - if (d->m_engine.isNull() - || (d->m_conn && d->m_conn->state() != QAbstractSocket::UnconnectedState)) + if (m_engine.isNull() + || (m_conn && m_conn->state() != QAbstractSocket::UnconnectedState)) return; showConnectionStatusMessage(tr("Connecting to debug server %1:%2").arg(address).arg( QString::number(port))); - d->m_conn->connectToHost(address, port); + m_conn->connectToHost(address, port); //A timeout to check the connection state - d->m_connectionTimer.start(); + m_connectionTimer.start(); } void QmlAdapter::beginConnectionOst(const QString &channel) { - if (d->m_engine.isNull() - || (d->m_conn && d->m_conn->state() != QAbstractSocket::UnconnectedState)) + if (m_engine.isNull() + || (m_conn && m_conn->state() != QAbstractSocket::UnconnectedState)) return; showConnectionStatusMessage(tr("Connecting to debug server on %1").arg(channel)); - d->m_conn->connectToOst(channel); + m_conn->connectToOst(channel); //A timeout to check the connection state - d->m_connectionTimer.start(); + m_connectionTimer.start(); } void QmlAdapter::closeConnection() { - if (d->m_connectionTimer.isActive()) { - d->m_connectionTimer.stop(); + if (m_connectionTimer.isActive()) { + m_connectionTimer.stop(); } else { - if (d->m_conn) { - d->m_conn->close(); + if (m_conn) { + m_conn->close(); } } } @@ -149,13 +113,13 @@ void QmlAdapter::closeConnection() void QmlAdapter::connectionErrorOccurred(QAbstractSocket::SocketError socketError) { showConnectionStatusMessage(tr("Error: (%1) %2", "%1=error code, %2=error message") - .arg(socketError).arg(d->m_conn->errorString())); + .arg(socketError).arg(m_conn->errorString())); // this is only an error if we are already connected and something goes wrong. if (isConnected()) { emit connectionError(socketError); } else { - d->m_connectionTimer.stop(); + m_connectionTimer.stop(); emit connectionStartupFailed(); } } @@ -179,13 +143,13 @@ void QmlAdapter::debugClientStatusChanged(QmlDebugClient::Status status) QmlDebugClient *client = qobject_cast<QmlDebugClient*>(sender()); QTC_ASSERT(client, return); - d->m_qmlClient = qobject_cast<Internal::BaseQmlDebuggerClient *>(client); - d->m_qmlClient->startSession(); + m_qmlClient = qobject_cast<Internal::BaseQmlDebuggerClient *>(client); + m_qmlClient->startSession(); } void QmlAdapter::connectionStateChanged() { - switch (d->m_conn->state()) { + switch (m_conn->state()) { case QAbstractSocket::UnconnectedState: { showConnectionStatusMessage(tr("disconnected.\n\n")); @@ -203,7 +167,7 @@ void QmlAdapter::connectionStateChanged() { showConnectionStatusMessage(tr("connected.\n")); - d->m_connectionTimer.stop(); + m_connectionTimer.stop(); //reloadEngines(); emit connected(); @@ -228,125 +192,83 @@ void QmlAdapter::checkConnectionState() void QmlAdapter::createDebuggerClients() { - - Internal::QScriptDebuggerClient *client1 = new Internal::QScriptDebuggerClient(d->m_conn); - connect(client1, SIGNAL(newStatus(QmlDebugClient::Status)), + Internal::QScriptDebuggerClient *debugClient1 = new Internal::QScriptDebuggerClient(m_conn); + connect(debugClient1, SIGNAL(newStatus(QmlDebugClient::Status)), this, SLOT(clientStatusChanged(QmlDebugClient::Status))); - connect(client1, SIGNAL(newStatus(QmlDebugClient::Status)), + connect(debugClient1, SIGNAL(newStatus(QmlDebugClient::Status)), this, SLOT(debugClientStatusChanged(QmlDebugClient::Status))); - Internal::QmlV8DebuggerClient *client2 = new Internal::QmlV8DebuggerClient(d->m_conn); - connect(client2, SIGNAL(newStatus(QmlDebugClient::Status)), + Internal::QmlV8DebuggerClient *debugClient2 = new Internal::QmlV8DebuggerClient(m_conn); + connect(debugClient2, SIGNAL(newStatus(QmlDebugClient::Status)), this, SLOT(clientStatusChanged(QmlDebugClient::Status))); - connect(client2, SIGNAL(newStatus(QmlDebugClient::Status)), + connect(debugClient2, SIGNAL(newStatus(QmlDebugClient::Status)), this, SLOT(debugClientStatusChanged(QmlDebugClient::Status))); - d->debugClients.insert(client1->name(),client1); - d->debugClients.insert(client2->name(),client2); + m_debugClients.insert(debugClient1->name(),debugClient1); + m_debugClients.insert(debugClient2->name(),debugClient2); - - client1->setEngine((Internal::QmlEngine*)(d->m_engine.data())); - client2->setEngine((Internal::QmlEngine*)(d->m_engine.data())); - - //engine->startSuccessful(); // FIXME: AAA: port to new debugger states + debugClient1->setEngine((Internal::QmlEngine*)(m_engine.data())); + debugClient2->setEngine((Internal::QmlEngine*)(m_engine.data())); } bool QmlAdapter::isConnected() const { - return d->m_conn && d->m_qmlClient && d->m_conn->state() == QAbstractSocket::ConnectedState; + return m_conn && m_qmlClient && m_conn->state() == QAbstractSocket::ConnectedState; } QmlDebugConnection *QmlAdapter::connection() const { - return d->m_conn; + return m_conn; } DebuggerEngine *QmlAdapter::debuggerEngine() const { - return d->m_engine.data(); + return m_engine.data(); } void QmlAdapter::showConnectionStatusMessage(const QString &message) { - if (!d->m_engine.isNull()) - d->m_engine.data()->showMessage(QLatin1String("QML Debugger: ") + message, LogStatus); + if (!m_engine.isNull()) + m_engine.data()->showMessage(QLatin1String("QML Debugger: ") + message, LogStatus); } void QmlAdapter::showConnectionErrorMessage(const QString &message) { - if (!d->m_engine.isNull()) - d->m_engine.data()->showMessage(QLatin1String("QML Debugger: ") + message, LogError); + if (!m_engine.isNull()) + m_engine.data()->showMessage(QLatin1String("QML Debugger: ") + message, LogError); } bool QmlAdapter::disableJsDebugging(bool block) { - if (d->m_engine.isNull()) + if (m_engine.isNull()) return block; - bool isBlocked = d->m_engine.data()->state() == InferiorRunOk; + bool isBlocked = m_engine.data()->state() == InferiorRunOk; if (isBlocked == block) return block; - if (block) { - d->m_engine.data()->continueInferior(); - } else { - d->m_engine.data()->requestInterruptInferior(); - } + if (block) + m_engine.data()->continueInferior(); + else + m_engine.data()->requestInterruptInferior(); return isBlocked; } Internal::BaseQmlDebuggerClient *QmlAdapter::activeDebuggerClient() { - return d->m_qmlClient; + return m_qmlClient; } QHash<QString, Internal::BaseQmlDebuggerClient*> QmlAdapter::debuggerClients() { - return d->debugClients; -} - -BaseEngineDebugClient *QmlAdapter::engineDebugClient() const -{ - return d->m_engineDebugClient; -} - -void QmlAdapter::setEngineDebugClient(BaseEngineDebugClient *client) -{ - Internal::QmlEngine *engine = - qobject_cast<Internal::QmlEngine *>(d->m_engine.data()); - if (engine && d->m_engineDebugClient) - disconnect(d->m_engineDebugClient, SIGNAL(result(quint32,QVariant,QByteArray)), - engine, - SLOT(expressionEvaluated(quint32,QVariant))); - d->m_engineDebugClient = client; - if (engine && d->m_engineDebugClient) - connect(d->m_engineDebugClient, SIGNAL(result(quint32,QVariant,QByteArray)), - engine, - SLOT(expressionEvaluated(quint32,QVariant))); + return m_debugClients; } QDebugMessageClient *QmlAdapter::messageClient() const { - return d->m_msgClient; -} - -int QmlAdapter::currentSelectedDebugId() const -{ - return d->m_currentSelectedDebugId; -} - -QString QmlAdapter::currentSelectedDisplayName() const -{ - return d->m_currentSelectedDebugName; -} - -void QmlAdapter::setCurrentSelectedDebugInfo(int currentDebugId, const QString &displayName) -{ - d->m_currentSelectedDebugId = currentDebugId; - d->m_currentSelectedDebugName = displayName; - emit selectionChanged(); + return m_msgClient; } void QmlAdapter::logServiceStatusChange(const QString &service, float version, @@ -374,8 +296,9 @@ void QmlAdapter::logServiceStatusChange(const QString &service, float version, void QmlAdapter::logServiceActivity(const QString &service, const QString &logMessage) { - if (!d->m_engine.isNull()) - d->m_engine.data()->showMessage(service + QLatin1Char(' ') + logMessage, LogDebug); + if (!m_engine.isNull()) + m_engine.data()->showMessage(service + QLatin1Char(' ') + logMessage, LogDebug); } +} // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/qml/qmladapter.h b/src/plugins/debugger/qml/qmladapter.h index 266f55ff94..d24d3d6b8e 100644 --- a/src/plugins/debugger/qml/qmladapter.h +++ b/src/plugins/debugger/qml/qmladapter.h @@ -35,18 +35,21 @@ #include "debugger_global.h" -#include <QObject> -#include <QAbstractSocket> #include <qmldebug/qmldebugclient.h> +#include <QAbstractSocket> +#include <QObject> +#include <QPointer> +#include <QTimer> + +using namespace QmlDebug; + namespace QmlDebug { class BaseEngineDebugClient; class QmlDebugConnection; class QDebugMessageClient; } -using namespace QmlDebug; - namespace Debugger { class DebuggerEngine; @@ -54,9 +57,8 @@ class DebuggerEngine; namespace Internal { class BaseQmlDebuggerClient; class QmlAdapterPrivate; -} // namespace Internal -class DEBUGGER_EXPORT QmlAdapter : public QObject +class QmlAdapter : public QObject { Q_OBJECT @@ -79,14 +81,8 @@ public: QHash<QString, Internal::BaseQmlDebuggerClient*> debuggerClients(); BaseEngineDebugClient *engineDebugClient() const; - void setEngineDebugClient(BaseEngineDebugClient *client); - QDebugMessageClient *messageClient() const; - int currentSelectedDebugId() const; - QString currentSelectedDisplayName() const; - void setCurrentSelectedDebugInfo(int debugId, const QString &displayName = QString()); - public slots: void logServiceStatusChange(const QString &service, float version, QmlDebugClient::Status newStatus); @@ -98,7 +94,6 @@ signals: void connectionStartupFailed(); void connectionError(QAbstractSocket::SocketError socketError); void serviceConnectionError(const QString serviceName); - void selectionChanged(); private slots: void connectionErrorOccurred(QAbstractSocket::SocketError socketError); @@ -113,9 +108,15 @@ private: void showConnectionErrorMessage(const QString &message); private: - Internal::QmlAdapterPrivate *d; + QPointer<DebuggerEngine> m_engine; + BaseQmlDebuggerClient *m_qmlClient; + QTimer m_connectionTimer; + QmlDebugConnection *m_conn; + QHash<QString, BaseQmlDebuggerClient*> m_debugClients; + QDebugMessageClient *m_msgClient; }; +} // namespace Internal } // namespace Debugger #endif // QMLADAPTER_H diff --git a/src/plugins/debugger/qml/qmlcppengine.cpp b/src/plugins/debugger/qml/qmlcppengine.cpp index 051243153a..b718afc59e 100644 --- a/src/plugins/debugger/qml/qmlcppengine.cpp +++ b/src/plugins/debugger/qml/qmlcppengine.cpp @@ -37,6 +37,7 @@ #include "stackhandler.h" #include "qmlengine.h" #include "qtmessageloghandler.h" +#include "watchdata.h" #include <coreplugin/icore.h> #include <utils/qtcassert.h> @@ -149,6 +150,8 @@ bool QmlCppEngine::setToolTipExpression(const QPoint & mousePos, void QmlCppEngine::updateWatchData(const WatchData &data, const WatchUpdateFlags &flags) { + if (data.iname.startsWith("inspect.")) + d->m_qmlEngine->updateWatchData(data, flags); d->m_activeEngine->updateWatchData(data, flags); } diff --git a/src/plugins/debugger/qml/qmlcppengine.h b/src/plugins/debugger/qml/qmlcppengine.h index 5966239632..e82b49e2da 100644 --- a/src/plugins/debugger/qml/qmlcppengine.h +++ b/src/plugins/debugger/qml/qmlcppengine.h @@ -40,7 +40,7 @@ namespace Internal { class QmlCppEnginePrivate; -class DEBUGGER_EXPORT QmlCppEngine : public DebuggerEngine +class QmlCppEngine : public DebuggerEngine { Q_OBJECT diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index 251fc4bb08..dbf568a23d 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -32,8 +32,10 @@ #include "qmlengine.h" #include "qmladapter.h" +#include "qmlinspectoradapter.h" #include "interactiveinterpreter.h" #include "baseqmldebuggerclient.h" +#include "qmlinspectoragent.h" #include "debuggerstartparameters.h" #include "debuggeractions.h" @@ -113,13 +115,13 @@ public: private: friend class QmlEngine; QmlAdapter m_adapter; + QmlInspectorAdapter m_inspectorAdapter; ApplicationLauncher m_applicationLauncher; QTimer m_noDebugOutputTimer; QmlOutputParser m_outputParser; QHash<QString, QTextDocument*> m_sourceDocuments; QHash<QString, QWeakPointer<TextEditor::ITextEditor> > m_sourceEditors; InteractiveInterpreter m_interpreter; - bool m_validContext; QHash<QString,BreakpointModelId> pendingBreakpoints; QList<quint32> queryIds; bool m_retryOnConnectFail; @@ -128,10 +130,11 @@ private: QmlEnginePrivate::QmlEnginePrivate(QmlEngine *q) : m_adapter(q), - m_validContext(false), + m_inspectorAdapter(&m_adapter, q), m_retryOnConnectFail(false), m_automaticConnect(false) -{} +{ +} class ASTWalker: public Visitor { @@ -326,14 +329,18 @@ QmlEngine::QmlEngine(const DebuggerStartParameters &startParameters, SLOT(updateCurrentContext())); connect(this->stackHandler(), SIGNAL(currentIndexChanged()), SLOT(updateCurrentContext())); - connect(&d->m_adapter, SIGNAL(selectionChanged()), + connect(&d->m_inspectorAdapter, SIGNAL(selectionChanged()), SLOT(updateCurrentContext())); + connect(d->m_inspectorAdapter.agent(), SIGNAL( + expressionResult(quint32,QVariant)), + SLOT(expressionEvaluated(quint32,QVariant))); connect(d->m_adapter.messageClient(), SIGNAL(message(QtMsgType,QString, QmlDebug::QDebugContextInfo)), SLOT(appendDebugOutput(QtMsgType,QString, QmlDebug::QDebugContextInfo))); + connect(&d->m_applicationLauncher, SIGNAL(processExited(int)), SLOT(disconnected())); @@ -1027,19 +1034,23 @@ void QmlEngine::updateWatchData(const WatchData &data, { // qDebug() << "UPDATE WATCH DATA" << data.toString(); //watchHandler()->rebuildModel(); - showStatusMessage(tr("Stopped."), 5000); + //showStatusMessage(tr("Stopped."), 5000); - if (!data.name.isEmpty() && d->m_adapter.activeDebuggerClient()) { - if (data.isValueNeeded()) { - d->m_adapter.activeDebuggerClient()->updateWatchData(data); - } - if (data.isChildrenNeeded() - && watchHandler()->isExpandedIName(data.iname)) { - d->m_adapter.activeDebuggerClient()->expandObject(data.iname, data.id); + if (data.iname.startsWith("inspect.")) { + d->m_inspectorAdapter.agent()->updateWatchData(data); + } else { + if (!data.name.isEmpty() && d->m_adapter.activeDebuggerClient()) { + if (data.isValueNeeded()) { + d->m_adapter.activeDebuggerClient()->updateWatchData(data); + } + if (data.isChildrenNeeded() + && watchHandler()->isExpandedIName(data.iname)) { + d->m_adapter.activeDebuggerClient()->expandObject(data.iname, data.id); + } } + synchronizeWatchers(); } - synchronizeWatchers(); if (!data.isSomethingNeeded()) watchHandler()->insertData(data); @@ -1111,8 +1122,7 @@ void QmlEngine::updateCurrentContext() { const QString context = state() == InferiorStopOk ? stackHandler()->currentFrame().function : - d->m_adapter.currentSelectedDisplayName(); - d->m_validContext = !context.isEmpty(); + d->m_inspectorAdapter.currentSelectedDisplayName(); showMessage(tr("Context: ").append(context), QtMessageLogStatus); } @@ -1149,55 +1159,39 @@ void QmlEngine::executeDebuggerCommand(const QString &command, DebuggerLanguages } } -bool QmlEngine::evaluateScriptExpression(const QString& expression) +bool QmlEngine::evaluateScriptExpression(const QString &expression) { bool didEvaluate = true; //Check if string is only white spaces if (!expression.trimmed().isEmpty()) { - //Check for a valid context - if (d->m_validContext) { - //check if it can be evaluated - if (canEvaluateScript(expression)) { - //Evaluate expression based on engine state - //When engine->state() == InferiorStopOk, the expression - //is sent to V8DebugService. In all other cases, the - //expression is evaluated by QDeclarativeEngine. - if (state() != InferiorStopOk) { - BaseEngineDebugClient *engineDebug = - d->m_adapter.engineDebugClient(); - - int id = d->m_adapter.currentSelectedDebugId(); - if (engineDebug && id != -1) { - quint32 queryId = - engineDebug->queryExpressionResult( - id, expression); - if (queryId) { - d->queryIds << queryId; - } else { - didEvaluate = false; - qtMessageLogHandler()-> - appendItem( - new QtMessageLogItem( - qtMessageLogHandler()->root(), - QtMessageLogHandler::ErrorType, - _("Error evaluating expression."))); - } - } + //check if it can be evaluated + if (canEvaluateScript(expression)) { + //Evaluate expression based on engine state + //When engine->state() == InferiorStopOk, the expression + //is sent to V8DebugService. In all other cases, the + //expression is evaluated by QDeclarativeEngine. + if (state() != InferiorStopOk) { + QmlInspectorAgent *agent = d->m_inspectorAdapter.agent(); + quint32 queryId + = agent->queryExpressionResult( + d->m_inspectorAdapter.currentSelectedDebugId(), + expression); + if (queryId) { + d->queryIds << queryId; } else { - executeDebuggerCommand(expression, QmlLanguage); + didEvaluate = false; + qtMessageLogHandler()-> + appendItem( + new QtMessageLogItem( + qtMessageLogHandler()->root(), + QtMessageLogHandler::ErrorType, + _("Error evaluating expression."))); } } else { - didEvaluate = false; + executeDebuggerCommand(expression, QmlLanguage); } } else { - //Incase of invalid context, show Error message - qtMessageLogHandler()-> - appendItem(new QtMessageLogItem( - qtMessageLogHandler()->root(), - QtMessageLogHandler::ErrorType, - _("Cannot evaluate without " - "a valid QML/JS Context.")), - qtMessageLogHandler()->rowCount()); + didEvaluate = false; } } return didEvaluate; diff --git a/src/plugins/debugger/qml/qmlengine.h b/src/plugins/debugger/qml/qmlengine.h index 7994379332..850baf8b8e 100644 --- a/src/plugins/debugger/qml/qmlengine.h +++ b/src/plugins/debugger/qml/qmlengine.h @@ -49,15 +49,13 @@ class IEditor; } namespace Debugger { - -class QmlAdapter; - namespace Internal { class QtMessageLogItem; +class QmlAdapter; class QmlEnginePrivate; -class DEBUGGER_EXPORT QmlEngine : public DebuggerEngine +class QmlEngine : public DebuggerEngine { Q_OBJECT diff --git a/src/plugins/debugger/qml/qmlinspectoradapter.cpp b/src/plugins/debugger/qml/qmlinspectoradapter.cpp new file mode 100644 index 0000000000..0d8724a095 --- /dev/null +++ b/src/plugins/debugger/qml/qmlinspectoradapter.cpp @@ -0,0 +1,611 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "qmlinspectoradapter.h" + +#include "debuggeractions.h" +#include "debuggercore.h" +#include "debuggerstringutils.h" +#include "qmladapter.h" +#include "qmlengine.h" +#include "qmlinspectoragent.h" +#include "qmllivetextpreview.h" + +#include <coreplugin/actionmanager/actionmanager.h> +#include <coreplugin/editormanager/ieditor.h> +#include <coreplugin/icore.h> +#include <qmldebug/declarativeenginedebugclient.h> +#include <qmldebug/declarativetoolsclient.h> +#include <qmldebug/qmlenginedebugclient.h> +#include <qmldebug/qmltoolsclient.h> +#include <qmljseditor/qmljseditorconstants.h> +#include <qmljs/qmljsmodelmanagerinterface.h> +#include <qmljstools/qmljssemanticinfo.h> +#include <utils/qtcassert.h> +#include <utils/savedaction.h> + +using namespace QmlDebug; + +namespace Debugger { +namespace Internal { + +// Get semantic info from QmlJSTextEditorWidget +// (we use the meta object system here to avoid having to link +// against qmljseditor) +static QmlJSTools::SemanticInfo getSemanticInfo(QPlainTextEdit *qmlJSTextEdit) +{ + QmlJSTools::SemanticInfo info; + QTC_ASSERT(QLatin1String(qmlJSTextEdit->metaObject()->className()) + == QLatin1String("QmlJSEditor::QmlJSTextEditorWidget"), + return info); + QTC_ASSERT(qmlJSTextEdit->metaObject()->indexOfProperty("semanticInfo") + != -1, return info); + + info = qmlJSTextEdit->property("semanticInfo") + .value<QmlJSTools::SemanticInfo>(); + return info; +} + +/*! + * QmlInspectorAdapter manages the clients for the inspector, and the + * integration with the text editor. + */ +QmlInspectorAdapter::QmlInspectorAdapter(QmlAdapter *debugAdapter, + QmlEngine *engine, + QObject *parent) + : QObject(parent) + , m_debugAdapter(debugAdapter) + , m_engine(engine) + , m_engineClient(0) + , m_toolsClient(0) + , m_agent(new QmlInspectorAgent(engine, this)) + , m_targetToSync(NoTarget) + , m_debugIdToSelect(-1) + , m_currentSelectedDebugId(-1) + , m_listeningToEditorManager(false) + , m_selectionCallbackExpected(false) + , m_cursorPositionChangedExternally(false) + , m_toolsClientConnected(false) + , m_inspectorToolsContext("Debugger.QmlInspector") + , m_selectAction(new QAction(this)) + , m_zoomAction(new QAction(this)) +{ + connect(m_agent, SIGNAL(objectFetched(QmlDebugObjectReference)), + SLOT(onObjectFetched(QmlDebugObjectReference))); + connect(m_agent, SIGNAL(objectTreeUpdated()), + SLOT(onObjectTreeUpdated())); + + QmlDebugConnection *connection = m_debugAdapter->connection(); + DeclarativeEngineDebugClient *engineClient1 + = new DeclarativeEngineDebugClient(connection); + connect(engineClient1, SIGNAL(newStatus(QmlDebugClient::Status)), + this, SLOT(clientStatusChanged(QmlDebugClient::Status))); + connect(engineClient1, SIGNAL(newStatus(QmlDebugClient::Status)), + this, SLOT(engineClientStatusChanged(QmlDebugClient::Status))); + + QmlEngineDebugClient *engineClient2 = new QmlEngineDebugClient(connection); + connect(engineClient2, SIGNAL(newStatus(QmlDebugClient::Status)), + this, SLOT(clientStatusChanged(QmlDebugClient::Status))); + connect(engineClient2, SIGNAL(newStatus(QmlDebugClient::Status)), + this, SLOT(engineClientStatusChanged(QmlDebugClient::Status))); + + m_engineClients.insert(engineClient1->name(), engineClient1); + m_engineClients.insert(engineClient2->name(), engineClient2); + + if (engineClient1->status() == QmlDebugClient::Enabled) + setActiveEngineClient(engineClient1); + if (engineClient2->status() == QmlDebugClient::Enabled) + setActiveEngineClient(engineClient2); + + DeclarativeToolsClient *toolsClient1 = new DeclarativeToolsClient(connection); + connect(toolsClient1, SIGNAL(connectedStatusChanged(QmlDebugClient::Status)), + this, SLOT(clientStatusChanged(QmlDebugClient::Status))); + connect(toolsClient1, SIGNAL(connectedStatusChanged(QmlDebugClient::Status)), + this, SLOT(toolsClientStatusChanged(QmlDebugClient::Status))); + + QmlToolsClient *toolsClient2 = new QmlToolsClient(connection); + connect(toolsClient2, SIGNAL(connectedStatusChanged(QmlDebugClient::Status)), + this, SLOT(clientStatusChanged(QmlDebugClient::Status))); + connect(toolsClient2, SIGNAL(connectedStatusChanged(QmlDebugClient::Status)), + this, SLOT(toolsClientStatusChanged(QmlDebugClient::Status))); + + // toolbar + m_selectAction->setObjectName("QML Select Action"); + m_zoomAction->setObjectName("QML Zoom Action"); + m_selectAction->setCheckable(true); + m_zoomAction->setCheckable(true); + + connect(m_selectAction, SIGNAL(triggered(bool)), + SLOT(onSelectActionTriggered(bool))); + connect(m_zoomAction, SIGNAL(triggered(bool)), + SLOT(onZoomActionTriggered(bool))); +} + +QmlInspectorAdapter::~QmlInspectorAdapter() +{ +} + +BaseEngineDebugClient *QmlInspectorAdapter::engineClient() const +{ + return m_engineClient; +} + +BaseToolsClient *QmlInspectorAdapter::toolsClient() const +{ + return m_toolsClient; +} + +QmlInspectorAgent *QmlInspectorAdapter::agent() const +{ + return m_agent; +} + +int QmlInspectorAdapter::currentSelectedDebugId() const +{ + return m_currentSelectedDebugId; +} + +QString QmlInspectorAdapter::currentSelectedDisplayName() const +{ + return m_currentSelectedDebugName; +} + +void QmlInspectorAdapter::clientStatusChanged(QmlDebugClient::Status status) +{ + QString serviceName; + float version = 0; + if (QmlDebugClient *client = qobject_cast<QmlDebugClient*>(sender())) { + serviceName = client->name(); + version = client->serviceVersion(); + } + + m_debugAdapter->logServiceStatusChange(serviceName, version, status); +} + +void QmlInspectorAdapter::toolsClientStatusChanged(QmlDebugClient::Status status) +{ + Core::ICore *core = Core::ICore::instance(); + Core::ActionManager *am = Core::ICore::actionManager(); + BaseToolsClient *client = qobject_cast<BaseToolsClient*>(sender()); + if (status == QmlDebugClient::Enabled) { + m_toolsClient = client; + + connect(client, SIGNAL(currentObjectsChanged(QList<int>)), + SLOT(selectObjectsFromToolsClient(QList<int>))); + connect(client, SIGNAL(logActivity(QString,QString)), + m_debugAdapter, SLOT(logServiceActivity(QString,QString))); + + // only enable zoom action for Qt 4.x/old client + // (zooming is integrated into selection tool in Qt 5). + m_zoomAction->setEnabled( + qobject_cast<DeclarativeToolsClient*>(client) != 0); + + // register actions here + // because there can be multiple QmlEngines + // at the same time (but hopefully one one is connected) + am->registerAction(m_selectAction, + Core::Id(Constants::QML_SELECTTOOL), + m_inspectorToolsContext); + am->registerAction(m_zoomAction, Core::Id(Constants::QML_ZOOMTOOL), + m_inspectorToolsContext); + + core->updateAdditionalContexts(Core::Context(), + m_inspectorToolsContext); + + Utils::SavedAction *action = debuggerCore()->action(QmlUpdateOnSave); + connect(action, SIGNAL(valueChanged(QVariant)), + SLOT(onUpdateOnSaveChanged(QVariant))); + + action = debuggerCore()->action(ShowAppOnTop); + connect(action, SIGNAL(valueChanged(QVariant)), + SLOT(onShowAppOnTopChanged(QVariant))); + if (action->isChecked()) + m_toolsClient->showAppOnTop(true); + + m_toolsClientConnected = true; + } else if (m_toolsClientConnected + && client == m_toolsClient) { + disconnect(client, SIGNAL(currentObjectsChanged(QList<int>)), + this, SLOT(selectObjectsFromToolsClient(QList<int>))); + disconnect(client, SIGNAL(logActivity(QString,QString)), + m_debugAdapter, SLOT(logServiceActivity(QString,QString))); + + am->unregisterAction(m_selectAction, + Core::Id(Constants::QML_SELECTTOOL)); + am->unregisterAction(m_zoomAction, + Core::Id(Constants::QML_ZOOMTOOL)); + + m_selectAction->setChecked(false); + m_zoomAction->setChecked(false); + core->updateAdditionalContexts(m_inspectorToolsContext, + Core::Context()); + + Utils::SavedAction *action = debuggerCore()->action(QmlUpdateOnSave); + disconnect(action, 0, this, 0); + action = debuggerCore()->action(ShowAppOnTop); + disconnect(action, 0, this, 0); + + m_toolsClientConnected = false; + } +} + +void QmlInspectorAdapter::engineClientStatusChanged(QmlDebugClient::Status status) +{ + if (status != QmlDebugClient::Enabled) + return; + + BaseEngineDebugClient *client + = qobject_cast<BaseEngineDebugClient*>(sender()); + QTC_ASSERT(client, return); + setActiveEngineClient(client); +} + +void QmlInspectorAdapter::selectObjectsFromEditor(const QList<int> &debugIds) +{ + int debugId = debugIds.first(); + + if (m_selectionCallbackExpected) { + m_selectionCallbackExpected = false; + return; + } + m_cursorPositionChangedExternally = true; + + QmlDebugObjectReference clientRef + = agent()->objectForId(debugId); + + // if children haven't been loaded yet do so first, the editor + // might actually be interested in the children! + if (clientRef.debugId() != debugId + || clientRef.needsMoreData()) { + m_targetToSync = ToolTarget; + m_debugIdToSelect = debugId; + agent()->fetchObject(debugId); + } else { + selectObject(clientRef, ToolTarget); + } +} + +void QmlInspectorAdapter::selectObjectsFromToolsClient(const QList<int> &debugIds) +{ + if (debugIds.isEmpty()) + return; + + int debugId = debugIds.first(); + + QmlDebugObjectReference clientRef + = agent()->objectForId(debugId); + + if (clientRef.debugId() != debugId) { + m_targetToSync = EditorTarget; + m_debugIdToSelect = debugId; + agent()->fetchObject(debugId); + } else { + selectObject(clientRef, EditorTarget); + } +} + +void QmlInspectorAdapter::onObjectFetched(const QmlDebugObjectReference &ref) +{ + if (ref.debugId() == m_debugIdToSelect) { + m_debugIdToSelect = -1; + selectObject(ref, m_targetToSync); + } +} + +void QmlInspectorAdapter::onObjectTreeUpdated() +{ + if (m_currentSelectedDebugId == -1) { + // select root element on startup + if (!m_agent->rootObjects().isEmpty()) + selectObject(m_agent->rootObjects().first(), NoTarget); + } +} + +void QmlInspectorAdapter::createPreviewForEditor(Core::IEditor *newEditor) +{ + if (newEditor && newEditor->id() + != QmlJSEditor::Constants::C_QMLJSEDITOR_ID) + return; + + QString filename = newEditor->document()->fileName(); + QmlJS::ModelManagerInterface *modelManager = + QmlJS::ModelManagerInterface::instance(); + QmlJS::Document::Ptr doc = modelManager->snapshot().document(filename); + if (!doc) { + if (filename.endsWith(".qml")) { + // add to list of docs that we have to update when + // snapshot figures out that there's a new document + m_pendingPreviewDocumentNames.append(filename); + } + return; + } + if (!doc->qmlProgram()) + return; + + QmlJS::Document::Ptr initdoc = m_loadedSnapshot.document(filename); + if (!initdoc) + initdoc = doc; + + if (m_textPreviews.contains(filename)) { + QmlLiveTextPreview *preview = m_textPreviews.value(filename); + preview->associateEditor(newEditor); + } else { + QmlLiveTextPreview *preview + = new QmlLiveTextPreview(doc, initdoc, this, this); + connect(preview, + SIGNAL(selectedItemsChanged(QList<int>)), + SLOT(selectObjectsFromEditor(QList<int>))); + preview->setApplyChangesToQmlInspector( + debuggerCore()->action(QmlUpdateOnSave)->isChecked()); + + m_textPreviews.insert(newEditor->document()->fileName(), preview); + preview->associateEditor(newEditor); + preview->updateDebugIds(); + } +} + +void QmlInspectorAdapter::removePreviewForEditor(Core::IEditor *editor) +{ + if (QmlLiveTextPreview *preview + = m_textPreviews.value(editor->document()->fileName())) { + preview->unassociateEditor(editor); + } +} + +void QmlInspectorAdapter::updatePendingPreviewDocuments(QmlJS::Document::Ptr doc) +{ + int idx = -1; + idx = m_pendingPreviewDocumentNames.indexOf(doc->fileName()); + + if (idx == -1) + return; + + Core::EditorManager *em = Core::EditorManager::instance(); + QList<Core::IEditor *> editors + = em->editorsForFileName(doc->fileName()); + + if (editors.isEmpty()) + return; + + m_pendingPreviewDocumentNames.removeAt(idx); + + Core::IEditor *editor = editors.takeFirst(); + createPreviewForEditor(editor); + QmlLiveTextPreview *preview + = m_textPreviews.value(editor->document()->fileName()); + foreach (Core::IEditor *editor, editors) + preview->associateEditor(editor); +} + +void QmlInspectorAdapter::onSelectActionTriggered(bool checked) +{ + if (checked) { + toolsClient()->setDesignModeBehavior(true); + toolsClient()->changeToSelectTool(); + m_zoomAction->setChecked(false); + } else { + toolsClient()->setDesignModeBehavior(false); + } +} + +void QmlInspectorAdapter::onZoomActionTriggered(bool checked) +{ + if (checked) { + toolsClient()->setDesignModeBehavior(true); + toolsClient()->changeToZoomTool(); + m_selectAction->setChecked(false); + } else { + toolsClient()->setDesignModeBehavior(false); + } +} + +void QmlInspectorAdapter::onShowAppOnTopChanged(const QVariant &value) +{ + bool showAppOnTop = value.toBool(); + if (m_toolsClient->status() == QmlDebugClient::Enabled) + m_toolsClient->showAppOnTop(showAppOnTop); +} + +void QmlInspectorAdapter::onUpdateOnSaveChanged(const QVariant &value) +{ + bool updateOnSave = value.toBool(); + for (QHash<QString, QmlLiveTextPreview *>::const_iterator it + = m_textPreviews.constBegin(); + it != m_textPreviews.constEnd(); ++it) { + it.value()->setApplyChangesToQmlInspector(updateOnSave); + } +} + +void QmlInspectorAdapter::setActiveEngineClient(BaseEngineDebugClient *client) +{ + if (m_engineClient == client) + return; + + m_engineClient = client; + m_agent->setEngineClient(m_engineClient); + + + if (m_engineClient && + m_engineClient->status() == QmlDebugClient::Enabled) { + QmlJS::ModelManagerInterface *modelManager + = QmlJS::ModelManagerInterface::instance(); + QmlJS::Snapshot snapshot = modelManager->snapshot(); + for (QHash<QString, QmlLiveTextPreview *>::const_iterator it + = m_textPreviews.constBegin(); + it != m_textPreviews.constEnd(); ++it) { + QmlJS::Document::Ptr doc = snapshot.document(it.key()); + it.value()->resetInitialDoc(doc); + } + + initializePreviews(); + } +} + +void QmlInspectorAdapter::initializePreviews() +{ + Core::EditorManager *em = Core::EditorManager::instance(); + QmlJS::ModelManagerInterface *modelManager + = QmlJS::ModelManagerInterface::instance(); + m_loadedSnapshot = modelManager->snapshot(); + + if (!m_listeningToEditorManager) { + m_listeningToEditorManager = true; + connect(em, SIGNAL(editorAboutToClose(Core::IEditor*)), + this, SLOT(removePreviewForEditor(Core::IEditor*))); + connect(em, SIGNAL(editorOpened(Core::IEditor*)), + this, SLOT(createPreviewForEditor(Core::IEditor*))); + connect(modelManager, + SIGNAL(documentChangedOnDisk(QmlJS::Document::Ptr)), + this, SLOT(updatePendingPreviewDocuments(QmlJS::Document::Ptr))); + } + + // initial update + foreach (Core::IEditor *editor, em->openedEditors()) + createPreviewForEditor(editor); +} + +void QmlInspectorAdapter::showConnectionStatusMessage(const QString &message) +{ + m_engine->showMessage(_("QML Inspector: ") + message, LogStatus); +} + +void QmlInspectorAdapter::gotoObjectReferenceDefinition( + const QmlDebugObjectReference &obj) +{ + if (m_cursorPositionChangedExternally) { + m_cursorPositionChangedExternally = false; + return; + } + + QmlDebugFileReference source = obj.source(); + + const QString fileName = m_engine->toFileInProject(source.url()); + + Core::EditorManager *editorManager = Core::EditorManager::instance(); + Core::IEditor *currentEditor = editorManager->currentEditor(); + Core::IEditor *editor = editorManager->openEditor(fileName); + TextEditor::ITextEditor *textEditor + = qobject_cast<TextEditor::ITextEditor*>(editor); + + if (currentEditor != editor) + m_selectionCallbackExpected = true; + + if (textEditor) { + QmlDebugObjectReference ref = objectReferenceForLocation(fileName); + if (ref.debugId() != obj.debugId()) { + m_selectionCallbackExpected = true; + editorManager->addCurrentPositionToNavigationHistory(); + textEditor->gotoLine(source.lineNumber()); + textEditor->widget()->setFocus(); + } + } +} + +QmlDebugObjectReference QmlInspectorAdapter::objectReferenceForLocation( + const QString &fileName, int cursorPosition) const +{ + Core::EditorManager *editorManager = Core::EditorManager::instance(); + Core::IEditor *editor = editorManager->openEditor(fileName); + TextEditor::ITextEditor *textEditor + = qobject_cast<TextEditor::ITextEditor*>(editor); + + if (textEditor + && textEditor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) { + if (cursorPosition == -1) + cursorPosition = textEditor->position(); + TextEditor::BaseTextEditor *baseTextEditor = + static_cast<TextEditor::BaseTextEditor*>(editor); + QPlainTextEdit *editWidget + = qobject_cast<QPlainTextEdit*>(baseTextEditor->widget()); + + QmlJSTools::SemanticInfo semanticInfo = getSemanticInfo(editWidget); + + if (QmlJS::AST::Node *node + = semanticInfo.declaringMemberNoProperties(cursorPosition)) { + if (QmlJS::AST::UiObjectMember *objMember + = node->uiObjectMemberCast()) { + return agent()->objectForLocation( + objMember->firstSourceLocation().startLine, + objMember->firstSourceLocation().startColumn); + } + } + } + return QmlDebugObjectReference(); +} + +inline QString displayName(const QmlDebugObjectReference &obj) +{ + // special! state names + if (obj.className() == "State") { + foreach (const QmlDebugPropertyReference &prop, obj.properties()) { + if (prop.name() == "name") + return prop.value().toString(); + } + } + + // has id? + if (!obj.idString().isEmpty()) + return obj.idString(); + + // return the simplified class name then + QString objTypeName = obj.className(); + QStringList declarativeStrings; + declarativeStrings << QLatin1String("QDeclarative") + << QLatin1String("QQml"); + foreach (const QString &str, declarativeStrings) { + if (objTypeName.startsWith(str)) { + objTypeName = objTypeName.mid(str.length()).section('_', 0, 0); + break; + } + } + return QString("<%1>").arg(objTypeName); +} + +void QmlInspectorAdapter::selectObject(const QmlDebugObjectReference &obj, + SelectionTarget target) +{ + if (target == ToolTarget) + m_toolsClient->setObjectIdList( + QList<QmlDebugObjectReference>() << obj); + + if (target == EditorTarget) + gotoObjectReferenceDefinition(obj); + + agent()->selectObjectInTree(obj.debugId()); + + m_currentSelectedDebugId = obj.debugId(); + m_currentSelectedDebugName = displayName(obj); + emit selectionChanged(); +} + +} // namespace Internal +} // namespace Debugger diff --git a/src/plugins/debugger/qml/qmlinspectoradapter.h b/src/plugins/debugger/qml/qmlinspectoradapter.h new file mode 100644 index 0000000000..cd25449925 --- /dev/null +++ b/src/plugins/debugger/qml/qmlinspectoradapter.h @@ -0,0 +1,150 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef QMLINSPECTORADAPTER_H +#define QMLINSPECTORADAPTER_H + +#include <QObject> +#include <QStringList> + +#include <coreplugin/icontext.h> +#include <qmldebug/qmldebugclient.h> +#include <qmljs/qmljsdocument.h> + +namespace Core { +class IEditor; +} + +namespace QmlDebug { +class BaseEngineDebugClient; +class BaseToolsClient; +class QmlDebugObjectReference; +} + +using namespace QmlDebug; + +namespace Debugger { +namespace Internal { + +class WatchTreeView; +class QmlAdapter; +class QmlEngine; +class QmlInspectorAgent; +class QmlLiveTextPreview; + +class QmlInspectorAdapter : public QObject +{ + Q_OBJECT + +public: + QmlInspectorAdapter(QmlAdapter *debugAdapter, QmlEngine *engine, + QObject *parent = 0); + ~QmlInspectorAdapter(); + + BaseEngineDebugClient *engineClient() const; + BaseToolsClient *toolsClient() const; + QmlInspectorAgent *agent() const; + + int currentSelectedDebugId() const; + QString currentSelectedDisplayName() const; + +signals: + void expressionResult(); + void selectionChanged(); + +private slots: + void clientStatusChanged(QmlDebugClient::Status status); + void toolsClientStatusChanged(QmlDebugClient::Status status); + void engineClientStatusChanged(QmlDebugClient::Status status); + + void selectObjectsFromEditor(const QList<int> &debugIds); + void selectObjectsFromToolsClient(const QList<int> &debugIds); + void onObjectFetched(const QmlDebugObjectReference &ref); + void onObjectTreeUpdated(); + + void createPreviewForEditor(Core::IEditor *newEditor); + void removePreviewForEditor(Core::IEditor *editor); + void updatePendingPreviewDocuments(QmlJS::Document::Ptr doc); + + void onSelectActionTriggered(bool checked); + void onZoomActionTriggered(bool checked); + void onShowAppOnTopChanged(const QVariant &value); + void onUpdateOnSaveChanged(const QVariant &value); + +private: + void setActiveEngineClient(BaseEngineDebugClient *client); + + void initializePreviews(); + void showConnectionStatusMessage(const QString &message); + + void gotoObjectReferenceDefinition(const QmlDebugObjectReference &obj); + QmlDebugObjectReference objectReferenceForLocation( + const QString &fileName, int cursorPosition = -1) const; + + enum SelectionTarget { NoTarget, ToolTarget, EditorTarget }; + void selectObject( + const QmlDebugObjectReference &objectReference, + SelectionTarget target); + + + QmlAdapter *m_debugAdapter; + QmlEngine *m_engine; + BaseEngineDebugClient *m_engineClient; + QHash<QString, BaseEngineDebugClient*> m_engineClients; + BaseToolsClient *m_toolsClient; + QmlInspectorAgent *m_agent; + + SelectionTarget m_targetToSync; + int m_debugIdToSelect; + + int m_currentSelectedDebugId; + QString m_currentSelectedDebugName; + + // Qml/JS editor integration + bool m_listeningToEditorManager; + QHash<QString, QmlLiveTextPreview *> m_textPreviews; + QmlJS::Snapshot m_loadedSnapshot; //the snapshot loaded by the viewer + QStringList m_pendingPreviewDocumentNames; + bool m_selectionCallbackExpected; + bool m_cursorPositionChangedExternally; + + // toolbar + bool m_toolsClientConnected; + Core::Context m_inspectorToolsContext; + QAction *m_selectAction; + QAction *m_zoomAction; +}; + +} // namespace Internal +} // namespace Debugger + +#endif // QMLINSPECTORADAPTER_H diff --git a/src/plugins/debugger/qml/qmlinspectoragent.cpp b/src/plugins/debugger/qml/qmlinspectoragent.cpp new file mode 100644 index 0000000000..99655f4f60 --- /dev/null +++ b/src/plugins/debugger/qml/qmlinspectoragent.cpp @@ -0,0 +1,786 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#include "qmlinspectoragent.h" + +#include "debuggeractions.h" +#include "debuggercore.h" +#include "debuggerengine.h" +#include "debuggerstringutils.h" +#include "watchhandler.h" + +#include <qmldebug/qmldebugconstants.h> +#include <utils/qtcassert.h> +#include <utils/savedaction.h> + +namespace Debugger { +namespace Internal { + +enum { + debug = false +}; + +/*! + * DebuggerAgent updates the watchhandler with the object tree data. + */ +QmlInspectorAgent::QmlInspectorAgent(DebuggerEngine *engine, QObject *parent) + : QObject(parent) + , m_engine(engine) + , m_engineClient(0) + , m_engineQueryId(0) + , m_rootContextQueryId(0) + , m_objectToSelect(-1) +{ + connect(debuggerCore()->action(ShowQmlObjectTree), + SIGNAL(valueChanged(QVariant)), SLOT(updateStatus())); +} + +void QmlInspectorAgent::refreshObjectTree() +{ + if (debug) + qDebug() << __FUNCTION__ << "()"; + + if (!m_rootContextQueryId) { + m_objectTreeQueryIds.clear(); + queryEngineContext(m_engines.value(0).debugId()); + } +} + +void QmlInspectorAgent::fetchObject(int debugId) +{ + if (debug) + qDebug() << __FUNCTION__ << "(" << debugId << ")"; + + m_fetchCurrentObjectsQueryIds + << fetchContextObject(QmlDebugObjectReference(debugId)); +} + +quint32 QmlInspectorAgent::queryExpressionResult(int debugId, + const QString &expression) +{ + if (debug) + qDebug() << __FUNCTION__ << "(" << debugId << expression + << m_engines.value(0).debugId() << ")"; + + return m_engineClient->queryExpressionResult(debugId, expression, + m_engines.value(0).debugId()); +} + +void QmlInspectorAgent::updateWatchData(const WatchData &data) +{ + if (debug) + qDebug() << __FUNCTION__ << "(" << data.id << ")"; + + if (data.id) { + // objects + QmlDebugObjectReference ref(data.id); + m_fetchCurrentObjectsQueryIds << fetchContextObject(ref); + WatchData d = data; + d.setAllUnneeded(); + m_engine->watchHandler()->beginCycle(InspectWatch, false); + m_engine->watchHandler()->insertData(d); + m_engine->watchHandler()->endCycle(InspectWatch); + } +} + +void QmlInspectorAgent::selectObjectInTree(int debugId) +{ + if (debug) { + qDebug() << __FUNCTION__ << "(" << debugId << ")"; + qDebug() << " " << debugId << "already fetched? " + << m_debugIdToIname.contains(debugId); + } + + if (m_debugIdToIname.contains(debugId)) { + QByteArray iname = m_debugIdToIname.value(debugId); + QTC_ASSERT(iname.startsWith("inspect."), qDebug() << iname); + QModelIndex itemIndex = m_engine->watchHandler()->itemIndex(iname); + QTC_ASSERT(itemIndex.isValid(), + qDebug() << "No for " << debugId << ", iname " << iname; return;); + if (debug) + qDebug() << " selecting" << iname << "in tree"; + m_engine->watchHandler()->setCurrentModelIndex(InspectWatch, itemIndex); + m_objectToSelect = 0; + } else { + // we've to fetch it + m_objectToSelect = debugId; + m_fetchCurrentObjectsQueryIds + << fetchContextObject(QmlDebugObjectReference(debugId)); + } +} + +quint32 QmlInspectorAgent::setBindingForObject(int objectDebugId, + const QString &propertyName, + const QVariant &value, + bool isLiteralValue, + QString source, + int line) +{ + if (debug) + qDebug() << __FUNCTION__ << "(" << objectDebugId << propertyName + << value.toString() << isLiteralValue << source << line << ")"; + + if (objectDebugId == -1) + return 0; + + if (propertyName == QLatin1String("id")) + return 0; // Crashes the QMLViewer. + + if (!isConnected() + || !debuggerCore()->boolSetting(ShowQmlObjectTree)) + return 0; + + log(LogSend, QString("SET_BINDING %1 %2 %3 %4").arg( + QString::number(objectDebugId), propertyName, value.toString(), + QString(isLiteralValue ? "true" : "false"))); + + quint32 queryId = m_engineClient->setBindingForObject( + objectDebugId, propertyName, value.toString(), isLiteralValue, + source, line); + + if (!queryId) + log(LogSend, QString("SET_BINDING failed!")); + + return queryId; +} + +quint32 QmlInspectorAgent::setMethodBodyForObject(int objectDebugId, + const QString &methodName, + const QString &methodBody) +{ + if (debug) + qDebug() << __FUNCTION__ << "(" << objectDebugId + << methodName << methodBody << ")"; + + if (objectDebugId == -1) + return 0; + + if (!isConnected() + || !debuggerCore()->boolSetting(ShowQmlObjectTree)) + return 0; + + log(LogSend, QString("SET_METHOD_BODY %1 %2 %3").arg( + QString::number(objectDebugId), methodName, methodBody)); + + quint32 queryId = m_engineClient->setMethodBody( + objectDebugId, methodName, methodBody); + + if (!queryId) + log(LogSend, QString("failed!")); + + return queryId; +} + +quint32 QmlInspectorAgent::resetBindingForObject(int objectDebugId, + const QString &propertyName) +{ + if (debug) + qDebug() << __FUNCTION__ << "(" << objectDebugId + << propertyName << ")"; + + if (objectDebugId == -1) + return 0; + + if (!isConnected() + || !debuggerCore()->boolSetting(ShowQmlObjectTree)) + return 0; + + log(LogSend, QString("RESET_BINDING %1 %2").arg( + QString::number(objectDebugId), propertyName)); + + quint32 queryId = m_engineClient->resetBindingForObject( + objectDebugId, propertyName); + + if (!queryId) + log(LogSend, QString("failed!")); + + return queryId; +} + + +QList<QmlDebugObjectReference> QmlInspectorAgent::objects() const +{ + QList<QmlDebugObjectReference> result; + foreach (const QmlDebugObjectReference &it, m_rootObjects) + result.append(objects(it)); + return result; +} + +QmlDebugObjectReference QmlInspectorAgent::objectForId(int debugId) const +{ + foreach (const QmlDebugObjectReference &it, m_rootObjects) { + QmlDebugObjectReference result = objectForId(debugId, it); + if (result.debugId() == debugId) + return result; + } + return QmlDebugObjectReference(); +} + +QmlDebugObjectReference QmlInspectorAgent::objectForId( + const QString &objectId) const +{ + if (!objectId.isEmpty() && objectId[0].isLower()) { + const QList<QmlDebugObjectReference> refs = objects(); + foreach (const QmlDebugObjectReference &ref, refs) { + if (ref.idString() == objectId) + return ref; + } + } + return QmlDebugObjectReference(); +} + +QmlDebugObjectReference QmlInspectorAgent::objectForLocation( + int line, int column) const +{ + const QList<QmlDebugObjectReference> refs = objects(); + foreach (const QmlDebugObjectReference &ref, refs) { + if (ref.source().lineNumber() == line + && ref.source().columnNumber() == column) + return ref; + } + + return QmlDebugObjectReference(); +} + +bool QmlInspectorAgent::addObjectWatch(int objectDebugId) +{ + if (debug) + qDebug() << __FUNCTION__ << "(" << objectDebugId << ")"; + + if (objectDebugId == -1) + return false; + + if (!isConnected() + || !debuggerCore()->boolSetting(ShowQmlObjectTree)) + return false; + + // already set + if (m_objectWatches.contains(objectDebugId)) + return true; + + QmlDebugObjectReference ref = objectForId(objectDebugId); + if (ref.debugId() != objectDebugId) + return false; + + // is flooding the debugging output log! + // log(LogSend, QString("WATCH_PROPERTY %1").arg(objectDebugId)); + + if (m_engineClient->addWatch(ref)) + m_objectWatches.append(objectDebugId); + + return false; +} + +bool QmlInspectorAgent::isObjectBeingWatched(int objectDebugId) +{ + return m_objectWatches.contains(objectDebugId); +} + +bool QmlInspectorAgent::removeObjectWatch(int objectDebugId) +{ + if (debug) + qDebug() << __FUNCTION__ << "(" << objectDebugId << ")"; + + if (objectDebugId == -1) + return false; + + if (!m_objectWatches.contains(objectDebugId)) + return false; + + if (!isConnected()) + return false; + + m_objectWatches.removeOne(objectDebugId); + return true; +} + +void QmlInspectorAgent::removeAllObjectWatches() +{ + if (debug) + qDebug() << __FUNCTION__ << "()"; + + foreach (int watchedObject, m_objectWatches) + removeObjectWatch(watchedObject); +} + +void QmlInspectorAgent::setEngineClient(BaseEngineDebugClient *client) +{ + if (m_engineClient == client) + return; + + if (m_engineClient) { + disconnect(m_engineClient, SIGNAL(newStatus(QmlDebugClient::Status)), + this, SLOT(updateStatus())); + disconnect(m_engineClient, SIGNAL(result(quint32,QVariant,QByteArray)), + this, SLOT(onResult(quint32,QVariant,QByteArray))); + disconnect(m_engineClient, SIGNAL(newObjects()), + this, SLOT(newObjects())); + } + + m_engineClient = client; + + if (m_engineClient) { + connect(m_engineClient, SIGNAL(newStatus(QmlDebugClient::Status)), + this, SLOT(updateStatus())); + connect(m_engineClient, SIGNAL(result(quint32,QVariant,QByteArray)), + this, SLOT(onResult(quint32,QVariant,QByteArray))); + connect(m_engineClient, SIGNAL(newObjects()), + this, SLOT(newObjects())); + } + + updateStatus(); +} + +void QmlInspectorAgent::updateStatus() +{ + if (m_engineClient + && (m_engineClient->status() == QmlDebugClient::Enabled) + && debuggerCore()->boolSetting(ShowQmlObjectTree)) { + reloadEngines(); + } else { + // clear view + m_engine->watchHandler()->beginCycle(InspectWatch, true); + m_engine->watchHandler()->endCycle(InspectWatch); + } +} + +void QmlInspectorAgent::onResult(quint32 queryId, const QVariant &value, + const QByteArray &type) +{ + if (debug) + qDebug() << __FUNCTION__ << "() ..."; + + if (type == _("FETCH_OBJECT_R")) { + log(LogReceive, _("FETCH_OBJECT_R %1").arg( + qvariant_cast<QmlDebugObjectReference>(value).idString())); + } else { + log(LogReceive, QLatin1String(type)); + } + + if (m_objectTreeQueryIds.contains(queryId)) { + m_objectTreeQueryIds.removeOne(queryId); + objectTreeFetched(qvariant_cast<QmlDebugObjectReference>(value)); + } else if (queryId == m_engineQueryId) { + m_engineQueryId = 0; + updateEngineList(qvariant_cast<QmlDebugEngineReferenceList>(value)); + } else if (queryId == m_rootContextQueryId) { + m_rootContextQueryId = 0; + rootContextChanged(qvariant_cast<QmlDebugContextReference>(value)); + } else if (m_fetchCurrentObjectsQueryIds.contains(queryId)) { + m_fetchCurrentObjectsQueryIds.removeOne(queryId); + QmlDebugObjectReference obj + = qvariant_cast<QmlDebugObjectReference>(value); + m_fetchCurrentObjects.push_front(obj); + onCurrentObjectsFetched(obj); + } else { + emit expressionResult(queryId, value); + } + + if (debug) + qDebug() << __FUNCTION__ << "done"; + +} + +void QmlInspectorAgent::newObjects() +{ + if (debug) + qDebug() << __FUNCTION__ << "()"; + + log(LogReceive, QString("OBJECT_CREATED")); + refreshObjectTree(); +} + +void QmlInspectorAgent::reloadEngines() +{ + if (debug) + qDebug() << __FUNCTION__ << "()"; + + if (!isConnected()) + return; + + log(LogSend, _("LIST_ENGINES")); + + m_engineQueryId = m_engineClient->queryAvailableEngines(); +} + +void QmlInspectorAgent::queryEngineContext(int id) +{ + if (debug) + qDebug() << __FUNCTION__ << "(" << id << ")"; + + if (id < 0) + return; + + if (!isConnected() + || !debuggerCore()->boolSetting(ShowQmlObjectTree)) + return; + + log(LogSend, QString("LIST_OBJECTS %1").arg(QString::number(id))); + + m_rootContextQueryId + = m_engineClient->queryRootContexts(QmlDebugEngineReference(id)); +} + +quint32 QmlInspectorAgent::fetchContextObject(const QmlDebugObjectReference &obj) +{ + if (debug) + qDebug() << __FUNCTION__ << "(" << obj << ")"; + + if (!isConnected() + || !debuggerCore()->boolSetting(ShowQmlObjectTree)) + return 0; + + log(LogSend, QString("FETCH_OBJECT %1").arg(obj.idString())); + quint32 queryId = m_engineClient->queryObject(obj); + if (debug) + qDebug() << __FUNCTION__ << "(" << obj.debugId() << ")" + << " - query id" << queryId; + return queryId; +} + +// fetch the root objects from the context + any child contexts +void QmlInspectorAgent::fetchRootObjects(const QmlDebugContextReference &context, + bool clear) +{ + if (debug) + qDebug() << __FUNCTION__ << "(" << context << clear << ")"; + + if (!isConnected() + || !debuggerCore()->boolSetting(ShowQmlObjectTree)) + return; + + if (clear) { + m_rootObjects.clear(); + m_objectTreeQueryIds.clear(); + } + foreach (const QmlDebugObjectReference & obj, context.objects()) { + quint32 queryId = 0; + using namespace QmlDebug::Constants; + if (m_engineClient->objectName() == QML_DEBUGGER && + m_engineClient->serviceVersion() >= CURRENT_SUPPORTED_VERSION) { + //Fetch only root objects + if (obj.parentId() == -1) + queryId = fetchContextObject(obj); + } else { + queryId = m_engineClient->queryObjectRecursive(obj); + } + + if (queryId) + m_objectTreeQueryIds << queryId; + } + foreach (const QmlDebugContextReference &child, context.contexts()) + fetchRootObjects(child, false); +} + +void QmlInspectorAgent::updateEngineList(const QmlDebugEngineReferenceList &engines) +{ + if (debug) + qDebug() << __FUNCTION__ << "(" << engines << ")"; + + m_engines = engines; + + // only care about first engine atm + queryEngineContext(engines.first().debugId()); +} + +void QmlInspectorAgent::rootContextChanged(const QmlDebugContextReference &context) +{ + if (debug) + qDebug() << __FUNCTION__ << "(" << context << ")"; + + fetchRootObjects(context, true); +} + +void QmlInspectorAgent::objectTreeFetched(const QmlDebugObjectReference &object) +{ + if (debug) + qDebug() << __FUNCTION__ << "(" << object << ")"; + + m_rootObjects.append(object); + + if (m_objectTreeQueryIds.isEmpty()) { + int old_count = m_debugIdHash.count(); + m_debugIdHash.clear(); + m_debugIdHash.reserve(old_count + 1); + m_debugIdToIname.clear(); + foreach (const QmlDebugObjectReference &it, m_rootObjects) + buildDebugIdHashRecursive(it); + + emit objectTreeUpdated(); + + // sync tree with watchhandler + QList<WatchData> watchData; + foreach (const QmlDebugObjectReference &obj, m_rootObjects) + watchData.append(buildWatchData(obj, WatchData())); + + WatchHandler *watchHandler = m_engine->watchHandler(); + watchHandler->beginCycle(InspectWatch, true); + watchHandler->insertBulkData(watchData); + watchHandler->endCycle(InspectWatch); + } +} + +void QmlInspectorAgent::onCurrentObjectsFetched(const QmlDebugObjectReference &obj) +{ + if (debug) + qDebug() << __FUNCTION__ << "( " << obj << ")"; + + // get parents if not known yet + if (!getObjectHierarchy(obj)) + return; + + if (debug) + qDebug() << " adding" << m_fetchCurrentObjects << "to tree"; + + foreach (const QmlDebugObjectReference &o, m_fetchCurrentObjects) + addObjectToTree(o, false); + + QmlDebugObjectReference last = m_fetchCurrentObjects.last(); + m_fetchCurrentObjects.clear(); + + if (m_objectToSelect == last.debugId()) { + // select item in view + QByteArray iname = m_debugIdToIname.value(last.debugId()); + QModelIndex itemIndex = m_engine->watchHandler()->itemIndex(iname); + QTC_ASSERT(itemIndex.isValid(), return); + if (debug) + qDebug() << " selecting" << iname << "in tree"; + m_engine->watchHandler()->setCurrentModelIndex(InspectWatch, itemIndex); + m_objectToSelect = -1; + } + + emit objectFetched(last); + emit objectTreeUpdated(); +} + +// Fetches all anchestors of object. Returns if all has been fetched already. +bool QmlInspectorAgent::getObjectHierarchy(const QmlDebugObjectReference &obj) +{ + if (debug) + qDebug() << __FUNCTION__ << "(" << obj << ")"; + + QmlDebugObjectReference parent = objectForId(obj.parentId()); + //for root object + if (obj.parentId() == -1) + return true; + + //for other objects + if (parent.debugId() == -1 || parent.needsMoreData()) { + m_fetchCurrentObjectsQueryIds + << fetchContextObject(QmlDebugObjectReference(obj.parentId())); + } else { + return getObjectHierarchy(parent); + } + return false; +} + +void QmlInspectorAgent::buildDebugIdHashRecursive(const QmlDebugObjectReference &ref) +{ + if (debug) + qDebug() << __FUNCTION__ << "(" << ref << ")"; + + QUrl fileUrl = ref.source().url(); + int lineNum = ref.source().lineNumber(); + int colNum = ref.source().columnNumber(); + int rev = 0; + + // handle the case where the url contains the revision number encoded. + //(for object created by the debugger) + static QRegExp rx("(.*)_(\\d+):(\\d+)$"); + if (rx.exactMatch(fileUrl.path())) { + fileUrl.setPath(rx.cap(1)); + rev = rx.cap(2).toInt(); + lineNum += rx.cap(3).toInt() - 1; + } + + const QString filePath + = m_engine->toFileInProject(fileUrl); + + // append the debug ids in the hash + QPair<QString, int> file = qMakePair<QString, int>(filePath, rev); + QPair<int, int> location = qMakePair<int, int>(lineNum, colNum); + if (!m_debugIdHash[file][location].contains(ref.debugId())) + m_debugIdHash[file][location].append(ref.debugId()); + + foreach (const QmlDebugObjectReference &it, ref.children()) + buildDebugIdHashRecursive(it); +} + +static QByteArray buildIName(const WatchData &parent, int debugId) +{ + if (!parent.isValid()) + return "inspect." + QByteArray::number(debugId); + return parent.iname + "." + QByteArray::number(debugId); +} + +static QByteArray buildIName(const WatchData &parent, const QString &name) +{ + return parent.iname + "." + name.toLatin1(); +} + +QList<WatchData> QmlInspectorAgent::buildWatchData(const QmlDebugObjectReference &obj, + const WatchData &parent) +{ + if (debug) + qDebug() << __FUNCTION__ << "(" << obj << parent.iname << ")"; + + QList<WatchData> list; + + WatchData objWatch; + QString name = obj.idString(); + if (name.isEmpty()) + name = obj.className(); + + // object + objWatch.id = obj.debugId(); + objWatch.exp = name.toLatin1(); + objWatch.name = name; + objWatch.iname = buildIName(parent, obj.debugId()); + objWatch.type = obj.className().toLatin1(); + objWatch.value = _("object"); + objWatch.setHasChildren(true); + objWatch.setAllUnneeded(); + + list.append(objWatch); + m_debugIdToIname.insert(objWatch.id, objWatch.iname); + + // properties + WatchData propertiesWatch; + propertiesWatch.id = objWatch.id; + propertiesWatch.exp = ""; + propertiesWatch.name = tr("properties"); + propertiesWatch.iname = objWatch.iname + ".[properties]"; + propertiesWatch.type = ""; + propertiesWatch.value = _("list"); + propertiesWatch.setHasChildren(true); + propertiesWatch.setAllUnneeded(); + + list.append(propertiesWatch); + + foreach (const QmlDebugPropertyReference &property, obj.properties()) { + WatchData propertyWatch; + propertyWatch.exp = property.name().toLatin1(); + propertyWatch.name = property.name(); + propertyWatch.iname = buildIName(propertiesWatch, property.name()); + propertyWatch.type = property.valueTypeName().toLatin1(); + propertyWatch.value = property.value().toString(); + propertyWatch.setAllUnneeded(); + propertyWatch.setHasChildren(false); + list.append(propertyWatch); + } + + // recurse + foreach (const QmlDebugObjectReference &child, obj.children()) + list.append(buildWatchData(child, objWatch)); + return list; +} + +void QmlInspectorAgent::addObjectToTree(const QmlDebugObjectReference &obj, + bool notify) +{ + int count = m_rootObjects.count(); + for (int i = 0; i < count; i++) { + int parentId = obj.parentId(); + if (m_engineClient->serviceVersion() < 2) { + // we don't get parentId in qt 4.x + parentId = m_rootObjects[i].insertObjectInTree(obj); + } + + if (parentId >= 0) { + buildDebugIdHashRecursive(obj); + if (notify) + emit objectTreeUpdated(); + + // find parent + QTC_ASSERT(m_debugIdToIname.contains(parentId), break); + QByteArray iname = m_debugIdToIname.value(parentId); + const WatchData *parent = m_engine->watchHandler()->findItem(iname); + if (parent) { + QList<WatchData> watches = buildWatchData(obj, *parent); + m_engine->watchHandler()->beginCycle(false); + m_engine->watchHandler()->insertBulkData(watches); + m_engine->watchHandler()->endCycle(); + break; + } + } + } +} + +QmlDebugObjectReference QmlInspectorAgent::objectForId(int debugId, + const QmlDebugObjectReference &objectRef) const +{ + if (objectRef.debugId() == debugId) + return objectRef; + + foreach (const QmlDebugObjectReference &child, objectRef.children()) { + QmlDebugObjectReference result = objectForId(debugId, child); + if (result.debugId() == debugId) + return result; + } + + return QmlDebugObjectReference(); +} + +QList<QmlDebugObjectReference> QmlInspectorAgent::objects( + const QmlDebugObjectReference &objectRef) const +{ + QList<QmlDebugObjectReference> result; + result.append(objectRef); + + foreach (const QmlDebugObjectReference &child, objectRef.children()) + result.append(objects(child)); + + return result; +} + +void QmlInspectorAgent::log(QmlInspectorAgent::LogDirection direction, + const QString &message) +{ + QString msg = _("Inspector"); + if (direction == LogSend) + msg += _(" sending "); + else + msg += _(" receiving "); + msg += message; + + if (m_engine) + m_engine->showMessage(msg, LogDebug); +} + +bool QmlInspectorAgent::isConnected() +{ + return m_engineClient + && (m_engineClient->status() == QmlDebugClient::Enabled); +} + +} // Internal +} // Debugger diff --git a/src/plugins/debugger/qml/qmlinspectoragent.h b/src/plugins/debugger/qml/qmlinspectoragent.h new file mode 100644 index 0000000000..59a493f3e0 --- /dev/null +++ b/src/plugins/debugger/qml/qmlinspectoragent.h @@ -0,0 +1,160 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** 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. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +**************************************************************************/ + +#ifndef QMLINSPECTORAGENT_H +#define QMLINSPECTORAGENT_H + +#include <QObject> + +#include <qmldebug/baseenginedebugclient.h> +#include <watchdata.h> + +using namespace QmlDebug; + +namespace Debugger { + +class DebuggerEngine; + +namespace Internal { + +class WatchData; + +//map <filename, editorRevision> -> <lineNumber, columnNumber> -> debugId +typedef +QHash<QPair<QString, int>, QHash<QPair<int, int>, QList<int> > > DebugIdHash; + +class QmlInspectorAgent : public QObject +{ + Q_OBJECT +public: + explicit QmlInspectorAgent(DebuggerEngine *engine, QObject *parent = 0); + + + void refreshObjectTree(); + void fetchObject(int debugId); + quint32 queryExpressionResult(int debugId, const QString &expression); + + void updateWatchData(const WatchData &data); + void selectObjectInTree(int debugId); + + quint32 setBindingForObject(int objectDebugId, + const QString &propertyName, + const QVariant &value, + bool isLiteralValue, + QString source, + int line); + quint32 setMethodBodyForObject(int objectDebugId, const QString &methodName, + const QString &methodBody); + quint32 resetBindingForObject(int objectDebugId, + const QString &propertyName); + + QList<QmlDebugObjectReference> objects() const; + QmlDebugObjectReference objectForId(int debugId) const; + QmlDebugObjectReference objectForId(const QString &objectId) const; + QmlDebugObjectReference objectForLocation(int line, int column) const; + QList<QmlDebugObjectReference> rootObjects() const { return m_rootObjects; } + DebugIdHash debugIdHash() const { return m_debugIdHash; } + + bool addObjectWatch(int objectDebugId); + bool isObjectBeingWatched(int objectDebugId); + bool removeObjectWatch(int objectDebugId); + void removeAllObjectWatches(); + + void setEngineClient(BaseEngineDebugClient *client); + +signals: + void objectTreeUpdated(); + void objectFetched(const QmlDebugObjectReference &ref); + void expressionResult(quint32 queryId, const QVariant &value); + void propertyChanged(int debugId, const QByteArray &propertyName, + const QVariant &propertyValue); + +private slots: + void updateStatus(); + void onResult(quint32 queryId, const QVariant &value, const QByteArray &type); + void newObjects(); + +private: + void reloadEngines(); + void queryEngineContext(int id); + quint32 fetchContextObject(const QmlDebugObjectReference &obj); + void fetchRootObjects(const QmlDebugContextReference &context, bool clear); + + void updateEngineList(const QmlDebugEngineReferenceList &engines); + void rootContextChanged(const QmlDebugContextReference &context); + void objectTreeFetched(const QmlDebugObjectReference &result); + void onCurrentObjectsFetched(const QmlDebugObjectReference &result); + bool getObjectHierarchy(const QmlDebugObjectReference &object); + + + void buildDebugIdHashRecursive(const QmlDebugObjectReference &ref); + QList<WatchData> buildWatchData(const QmlDebugObjectReference &obj, + const WatchData &parent); + void addObjectToTree(const QmlDebugObjectReference &obj, bool notify); + + QmlDebugObjectReference objectForId( + int debugId, + const QmlDebugObjectReference &ref) const; + QList<QmlDebugObjectReference> objects( + const QmlDebugObjectReference &objectRef) const; + + + enum LogDirection { + LogSend, + LogReceive + }; + void log(LogDirection direction, const QString &message); + + bool isConnected(); + +private: + DebuggerEngine *m_engine; + QmlDebug::BaseEngineDebugClient *m_engineClient; + + quint32 m_engineQueryId; + quint32 m_rootContextQueryId; + int m_objectToSelect; + QList<quint32> m_objectTreeQueryIds; + QList<QmlDebugObjectReference> m_rootObjects; + QList<quint32> m_fetchCurrentObjectsQueryIds; + QList<QmlDebugObjectReference> m_fetchCurrentObjects; + QmlDebugEngineReferenceList m_engines; + QHash<int, QByteArray> m_debugIdToIname; + DebugIdHash m_debugIdHash; + + QList<int> m_objectWatches; +}; + +} // Internal +} // Debugger + +#endif // QMLINSPECTORAGENT_H diff --git a/src/plugins/qmljsinspector/qmljslivetextpreview.cpp b/src/plugins/debugger/qml/qmllivetextpreview.cpp index e3bb0ce62d..1f352db46b 100644 --- a/src/plugins/qmljsinspector/qmljslivetextpreview.cpp +++ b/src/plugins/debugger/qml/qmllivetextpreview.cpp @@ -30,36 +30,23 @@ ** **************************************************************************/ -#include <typeinfo> +#include "qmllivetextpreview.h" -#include "qmljsinspector.h" -#include "qmljsclientproxy.h" -#include "qmljslivetextpreview.h" +#include "qmlinspectoradapter.h" +#include "qmlinspectoragent.h" -#include "qmljsinspectorconstants.h" +#include <coreplugin/infobar.h> +#include <qmldebug/basetoolsclient.h> #include <qmljseditor/qmljseditorconstants.h> -#include <qmljs/qmljsdelta.h> #include <qmljs/parser/qmljsast_p.h> -#include <extensionsystem/pluginmanager.h> -#include <projectexplorer/projectexplorer.h> -#include <projectexplorer/project.h> - -#include <coreplugin/icore.h> -#include <coreplugin/infobar.h> -#include <coreplugin/editormanager/ieditor.h> -#include <coreplugin/id.h> -#include <coreplugin/editormanager/editormanager.h> - -#include <debugger/debuggerconstants.h> - +#include <qmljs/qmljsdelta.h> +#include <qmljs/qmljsmodelmanagerinterface.h> #include <utils/qtcassert.h> -#include <QDebug> - using namespace QmlJS; using namespace QmlJS::AST; -namespace QmlJSInspector { +namespace Debugger { namespace Internal { /*! @@ -70,10 +57,10 @@ class MapObjectWithDebugReference : public Visitor public: typedef QList<int> DebugIdList; MapObjectWithDebugReference() : activated(0) {} - virtual void endVisit(UiObjectDefinition *ast) ; - virtual void endVisit(UiObjectBinding *ast) ; - virtual bool visit(UiObjectDefinition *ast) ; - virtual bool visit(UiObjectBinding *ast) ; + virtual void endVisit(UiObjectDefinition *ast); + virtual void endVisit(UiObjectBinding *ast); + virtual bool visit(UiObjectDefinition *ast); + virtual bool visit(UiObjectBinding *ast); QHash<QPair<int, int>, DebugIdList> ids; QString filename; @@ -87,298 +74,6 @@ private: int activated; }; -bool MapObjectWithDebugReference::visit(UiObjectDefinition *ast) -{ - if (lookupObjects.contains(ast)) - activated++; - return true; -} - -bool MapObjectWithDebugReference::visit(UiObjectBinding *ast) -{ - if (lookupObjects.contains(ast)) - activated++; - return true; -} - -void MapObjectWithDebugReference::endVisit(UiObjectDefinition *ast) -{ - process(ast); - if (lookupObjects.contains(ast)) - activated--; -} - -void MapObjectWithDebugReference::endVisit(UiObjectBinding *ast) -{ - process(ast); - if (lookupObjects.contains(ast)) - activated--; -} - -void MapObjectWithDebugReference::process(UiObjectMember *ast) -{ - if (lookupObjects.isEmpty() || activated) { - SourceLocation loc = ast->firstSourceLocation(); - QHash<QPair<int, int>, DebugIdList>::const_iterator it - = ids.constFind(qMakePair<int, int>(loc.startLine, loc.startColumn)); - if (it != ids.constEnd()) - result[ast].append(*it); - } -} - -void MapObjectWithDebugReference::process(UiObjectBinding *ast) -{ - if (lookupObjects.isEmpty() || activated) { - SourceLocation loc = ast->qualifiedTypeNameId->identifierToken; - QHash<QPair<int, int>, DebugIdList>::const_iterator it - = ids.constFind(qMakePair<int, int>(loc.startLine, loc.startColumn)); - if (it != ids.constEnd()) - result[ast].append(*it); - } -} - -void QmlJSLiveTextPreview::associateEditor(Core::IEditor *editor) -{ - using namespace TextEditor; - if (editor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) { - QTC_ASSERT(QLatin1String(editor->widget()->metaObject()->className()) == - QLatin1String("QmlJSEditor::QmlJSTextEditorWidget"), - return); - - BaseTextEditorWidget *editWidget - = qobject_cast<BaseTextEditorWidget*>(editor->widget()); - QTC_ASSERT(editWidget, return); - - if (!m_editors.contains(editWidget)) { - m_editors << editWidget; - if (m_clientProxy.data()) - connect(editWidget, - SIGNAL(selectedElementsChanged(QList<int>,QString)), - SLOT(changeSelectedElements(QList<int>,QString))); - } - } -} - -void QmlJSLiveTextPreview::unassociateEditor(Core::IEditor *oldEditor) -{ - using namespace TextEditor; - if (oldEditor && oldEditor->id() - == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) { - BaseTextEditorWidget *editWidget - = qobject_cast<BaseTextEditorWidget*>(oldEditor->widget()); - QTC_ASSERT(editWidget, return); - - if (m_editors.contains(editWidget)) { - m_editors.removeOne(editWidget); - disconnect(editWidget, 0, this, 0); - } - } -} - -QmlJSLiveTextPreview::QmlJSLiveTextPreview(const QmlJS::Document::Ptr &doc, - const QmlJS::Document::Ptr &initDoc, - ClientProxy *clientProxy, - QObject *parent) - : QObject(parent) - , m_previousDoc(doc) - , m_initialDoc(initDoc) - , m_applyChangesToQmlInspector(true) - , m_clientProxy(clientProxy) - , m_nodeForOffset(0) - , m_updateNodeForOffset(false) -{ - Q_ASSERT(doc->fileName() == initDoc->fileName()); - m_filename = doc->fileName(); - - connect(QmlJS::ModelManagerInterface::instance(), SIGNAL(documentChangedOnDisk(QmlJS::Document::Ptr)), - SLOT(documentChanged(QmlJS::Document::Ptr))); - - if (m_clientProxy.data()) { - connect(m_clientProxy.data(), SIGNAL(objectTreeUpdated()), - SLOT(updateDebugIds())); - } -} - -void QmlJSLiveTextPreview::resetInitialDoc(const QmlJS::Document::Ptr &doc) -{ - m_initialDoc = doc; - m_previousDoc = doc; - m_createdObjects.clear(); - m_debugIds.clear(); - m_docWithUnappliedChanges.clear(); -} - - -QList<int> QmlJSLiveTextPreview::objectReferencesForOffset(quint32 offset) -{ - QList<int> result; - QHashIterator<QmlJS::AST::UiObjectMember*, QList<int> > iter(m_debugIds); - QmlJS::AST::UiObjectMember *possibleNode = 0; - while(iter.hasNext()) { - iter.next(); - QmlJS::AST::UiObjectMember *member = iter.key(); - quint32 startOffset = member->firstSourceLocation().offset; - quint32 endOffset = member->lastSourceLocation().offset; - if (startOffset <= offset && offset <= endOffset) { - if (!possibleNode) - possibleNode = member; - if (possibleNode->firstSourceLocation().offset <= startOffset && - endOffset <= possibleNode->lastSourceLocation().offset) - possibleNode = member; - } - } - if (possibleNode) { - if (possibleNode != m_nodeForOffset) { - //We have found a better match, set flag so that we can - //query again to check if this is the best match for the offset - m_updateNodeForOffset = true; - m_nodeForOffset = possibleNode; - } - result = m_debugIds.value(possibleNode); - } - return result; -} - -void QmlJSLiveTextPreview::changeSelectedElements(QList<int> offsets, - const QString &wordAtCursor) -{ - if (m_editors.isEmpty() || !m_previousDoc || !m_clientProxy) - return; - - m_updateNodeForOffset = false; - m_lastOffsets = offsets; - QmlDebugObjectReference objectRefUnderCursor; - objectRefUnderCursor - = m_clientProxy.data()->objectReferenceForId(wordAtCursor); - - QList<int> selectedReferences; - bool containsReferenceUnderCursor = false; - - foreach(int offset, offsets) { - if (offset >= 0) { - QList<int> list = objectReferencesForOffset(offset); - - if (!containsReferenceUnderCursor - && objectRefUnderCursor.debugId() != -1) { - foreach(int id, list) { - if (id == objectRefUnderCursor.debugId()) { - containsReferenceUnderCursor = true; - break; - } - } - } - - selectedReferences << list; - } - } - - // fallback: use ref under cursor if nothing else is found - if (selectedReferences.isEmpty() - && !containsReferenceUnderCursor - && objectRefUnderCursor.debugId() != -1) - { - selectedReferences << objectRefUnderCursor.debugId(); - } - - if (!selectedReferences.isEmpty()) { - QList<QmlDebugObjectReference> refs; - foreach(int i, selectedReferences) - refs << QmlDebugObjectReference(i); - emit selectedItemsChanged(refs); - } -} - -static QList<int> findRootObjectRecursive(const QmlDebugObjectReference &object, - const Document::Ptr &doc) -{ - QList<int> result; - if (object.className() == doc->componentName()) - result += object.debugId(); - - foreach (const QmlDebugObjectReference &it, object.children()) { - result += findRootObjectRecursive(it, doc); - } - return result; -} - -void QmlJSLiveTextPreview::updateDebugIds() -{ - if (!m_initialDoc->qmlProgram()) - return; - - ClientProxy *clientProxy = m_clientProxy.data(); - if (!clientProxy) - return; - - DebugIdHash::const_iterator it - = clientProxy->debugIdHash().constFind( - qMakePair<QString, int>(m_initialDoc->fileName(), 0)); - if (it != clientProxy->debugIdHash().constEnd()) { - // Map all the object that comes from the document as it has been loaded - // by the server. - const QmlJS::Document::Ptr &doc = m_initialDoc; - - MapObjectWithDebugReference visitor; - visitor.ids = (*it); - visitor.filename = doc->fileName(); - doc->qmlProgram()->accept(&visitor); - - m_debugIds = visitor.result; - if (doc != m_previousDoc) { - Delta delta; - m_debugIds = delta(doc, m_previousDoc, m_debugIds); - } - } - - const QmlJS::Document::Ptr &doc = m_previousDoc; - if (!doc->qmlProgram()) - return; - - // Map the root nodes of the document. - if(doc->qmlProgram()->members && doc->qmlProgram()->members->member) { - UiObjectMember *root = doc->qmlProgram()->members->member; - QList<int> r; - foreach (const QmlDebugObjectReference& it, - clientProxy->rootObjectReference()) { - r += findRootObjectRecursive(it, doc); - } - if (!r.isEmpty()) - m_debugIds[root] += r; - } - - // Map the node of the later created objects. - for (QHash<Document::Ptr,QSet<UiObjectMember*> >::const_iterator it - = m_createdObjects.constBegin(); - it != m_createdObjects.constEnd(); ++it) { - - const QmlJS::Document::Ptr &doc = it.key(); - - DebugIdHash::const_iterator id_it = clientProxy->debugIdHash().constFind( - qMakePair<QString, int>(doc->fileName(), doc->editorRevision())); - if (id_it == clientProxy->debugIdHash().constEnd()) - continue; - - MapObjectWithDebugReference visitor; - visitor.ids = *id_it; - visitor.filename = doc->fileName(); - visitor.lookupObjects = it.value(); - doc->qmlProgram()->accept(&visitor); - - Delta::DebugIdMap debugIds = visitor.result; - if (doc != m_previousDoc) { - Delta delta; - debugIds = delta(doc, m_previousDoc, debugIds); - } - for(Delta::DebugIdMap::const_iterator it2 = debugIds.constBegin(); - it2 != debugIds.constEnd(); ++it2) { - m_debugIds[it2.key()] += it2.value(); - } - } - if (m_updateNodeForOffset) - changeSelectedElements(m_lastOffsets, QString()); -} - - class UpdateInspector : public Delta { private: static inline QString stripQuotes(const QString &str) @@ -460,7 +155,7 @@ private: ExpressionStatement *expStatement = cast<ExpressionStatement*>(scriptBinding->statement); - switch(expStatement->expression->kind) { + switch (expStatement->expression->kind) { case Node::Kind_NumericLiteral: case Node::Kind_UnaryPlusExpression: case Node::Kind_UnaryMinusExpression: @@ -491,7 +186,8 @@ protected: Q_UNUSED(scriptBinding); Q_UNUSED(parentDefinition); appliedChangesToViewer = true; - m_clientProxy->setMethodBodyForObject(debugId, methodName, methodBody); + m_inspectorAdapter->engineClient()->setMethodBody(debugId, + methodName, methodBody); } virtual void updateScriptBinding(DebugId debugId, @@ -501,11 +197,11 @@ protected: const QString &scriptCode) { if (unsyncronizableChanges - == QmlJSLiveTextPreview::NoUnsyncronizableChanges) { + == QmlLiveTextPreview::NoUnsyncronizableChanges) { if (propertyName == QLatin1String("id")) { unsyncronizableElementName = propertyName; unsyncronizableChanges - = QmlJSLiveTextPreview::AttributeChangeWarning; + = QmlLiveTextPreview::AttributeChangeWarning; unsyncronizableChangeLine = parentDefinition->firstSourceLocation().startLine; unsyncronizableChangeColumn @@ -518,7 +214,7 @@ protected: if (isLiteral) expr = castToLiteral(scriptCode, scriptBinding); appliedChangesToViewer = true; - m_clientProxy->setBindingForObject( + m_inspectorAdapter->engineClient()->setBindingForObject( debugId, propertyName, expr, isLiteral, document()->fileName(), scriptBinding->firstSourceLocation().startLine); @@ -527,13 +223,13 @@ protected: virtual void resetBindingForObject(int debugId, const QString &propertyName) { appliedChangesToViewer = true; - m_clientProxy->resetBindingForObject(debugId, propertyName); + m_inspectorAdapter->engineClient()->resetBindingForObject(debugId, propertyName); } virtual void removeObject(int debugId) { appliedChangesToViewer = true; - m_clientProxy->destroyQmlObject(debugId); + m_inspectorAdapter->toolsClient()->destroyQmlObject(debugId); } virtual void createObject(const QString &qmlText, DebugId ref, @@ -543,18 +239,18 @@ protected: { appliedChangesToViewer = true; referenceRefreshRequired = true; - m_clientProxy->createQmlObject(qmlText, ref, importList, filename, order); + m_inspectorAdapter->toolsClient()->createQmlObject(qmlText, ref, importList, filename, order); } virtual void reparentObject(int debugId, int newParent) { appliedChangesToViewer = true; - m_clientProxy->reparentQmlObject(debugId, newParent); + m_inspectorAdapter->toolsClient()->reparentQmlObject(debugId, newParent); } void notifyUnsyncronizableElementChange(UiObjectMember *parent) { - if (unsyncronizableChanges == QmlJSLiveTextPreview::NoUnsyncronizableChanges) { + if (unsyncronizableChanges == QmlLiveTextPreview::NoUnsyncronizableChanges) { UiObjectDefinition *parentDefinition = cast<UiObjectDefinition *>(parent); if (parentDefinition && parentDefinition->qualifiedTypeNameId && !parentDefinition->qualifiedTypeNameId->name.isEmpty()) @@ -562,7 +258,7 @@ protected: unsyncronizableElementName = parentDefinition->qualifiedTypeNameId->name.toString(); unsyncronizableChanges - = QmlJSLiveTextPreview::ElementChangeWarning; + = QmlLiveTextPreview::ElementChangeWarning; unsyncronizableChangeLine = parentDefinition->firstSourceLocation().startLine; unsyncronizableChangeColumn @@ -572,30 +268,294 @@ protected: } public: - UpdateInspector(ClientProxy *clientProxy) + UpdateInspector(QmlInspectorAdapter *inspectorAdapter) : appliedChangesToViewer(false) , referenceRefreshRequired(false) - , unsyncronizableChanges(QmlJSLiveTextPreview::NoUnsyncronizableChanges) - , m_clientProxy(clientProxy) + , unsyncronizableChanges(QmlLiveTextPreview::NoUnsyncronizableChanges) + , m_inspectorAdapter(inspectorAdapter) { - } + bool appliedChangesToViewer; bool referenceRefreshRequired; QString unsyncronizableElementName; - QmlJSLiveTextPreview::UnsyncronizableChangeType unsyncronizableChanges; + QmlLiveTextPreview::UnsyncronizableChangeType unsyncronizableChanges; unsigned unsyncronizableChangeLine; unsigned unsyncronizableChangeColumn; - ClientProxy *m_clientProxy; + QmlInspectorAdapter *m_inspectorAdapter; }; -void QmlJSLiveTextPreview::documentChanged(QmlJS::Document::Ptr doc) +bool MapObjectWithDebugReference::visit(UiObjectDefinition *ast) +{ + if (lookupObjects.contains(ast)) + activated++; + return true; +} + +bool MapObjectWithDebugReference::visit(UiObjectBinding *ast) +{ + if (lookupObjects.contains(ast)) + activated++; + return true; +} + +void MapObjectWithDebugReference::endVisit(UiObjectDefinition *ast) +{ + process(ast); + if (lookupObjects.contains(ast)) + activated--; +} + +void MapObjectWithDebugReference::endVisit(UiObjectBinding *ast) +{ + process(ast); + if (lookupObjects.contains(ast)) + activated--; +} + +void MapObjectWithDebugReference::process(UiObjectMember *ast) +{ + if (lookupObjects.isEmpty() || activated) { + SourceLocation loc = ast->firstSourceLocation(); + QHash<QPair<int, int>, DebugIdList>::const_iterator it + = ids.constFind(qMakePair<int, int>(loc.startLine, loc.startColumn)); + if (it != ids.constEnd()) + result[ast].append(*it); + } +} + +void MapObjectWithDebugReference::process(UiObjectBinding *ast) +{ + if (lookupObjects.isEmpty() || activated) { + SourceLocation loc = ast->qualifiedTypeNameId->identifierToken; + QHash<QPair<int, int>, DebugIdList>::const_iterator it + = ids.constFind(qMakePair<int, int>(loc.startLine, loc.startColumn)); + if (it != ids.constEnd()) + result[ast].append(*it); + } +} + +/*! + * Manages a Qml/JS document for the inspector + */ +QmlLiveTextPreview::QmlLiveTextPreview(const QmlJS::Document::Ptr &doc, + const QmlJS::Document::Ptr &initDoc, + QmlInspectorAdapter *inspectorAdapter, + QObject *parent) + : QObject(parent) + , m_previousDoc(doc) + , m_initialDoc(initDoc) + , m_applyChangesToQmlInspector(true) + , m_inspectorAdapter(inspectorAdapter) + , m_nodeForOffset(0) + , m_updateNodeForOffset(false) +{ + QTC_CHECK(doc->fileName() == initDoc->fileName()); + + QmlJS::ModelManagerInterface *modelManager + = QmlJS::ModelManagerInterface::instance(); + + connect(modelManager, SIGNAL(documentChangedOnDisk(QmlJS::Document::Ptr)), + SLOT(documentChanged(QmlJS::Document::Ptr))); + + connect(m_inspectorAdapter->agent(), SIGNAL(objectTreeUpdated()), + SLOT(updateDebugIds())); +} + +void QmlLiveTextPreview::associateEditor(Core::IEditor *editor) +{ + using namespace TextEditor; + if (editor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) { + QTC_ASSERT(QLatin1String(editor->widget()->metaObject()->className()) == + QLatin1String("QmlJSEditor::QmlJSTextEditorWidget"), + return); + + BaseTextEditorWidget *editWidget + = qobject_cast<BaseTextEditorWidget*>(editor->widget()); + QTC_ASSERT(editWidget, return); + + if (!m_editors.contains(editWidget)) { + m_editors << editWidget; + if (m_inspectorAdapter) + connect(editWidget, + SIGNAL(selectedElementsChanged(QList<int>,QString)), + SLOT(changeSelectedElements(QList<int>,QString))); + } + } +} + +void QmlLiveTextPreview::unassociateEditor(Core::IEditor *oldEditor) +{ + using namespace TextEditor; + if (oldEditor && oldEditor->id() + == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) { + BaseTextEditorWidget *editWidget + = qobject_cast<BaseTextEditorWidget*>(oldEditor->widget()); + QTC_ASSERT(editWidget, return); + + if (m_editors.contains(editWidget)) { + m_editors.removeOne(editWidget); + disconnect(editWidget, 0, this, 0); + } + } +} + +void QmlLiveTextPreview::resetInitialDoc(const QmlJS::Document::Ptr &doc) +{ + m_initialDoc = doc; + m_previousDoc = doc; + m_createdObjects.clear(); + m_debugIds.clear(); + m_docWithUnappliedChanges.clear(); +} + +void QmlLiveTextPreview::setApplyChangesToQmlInspector(bool applyChanges) +{ + if (applyChanges && !m_applyChangesToQmlInspector) { + if (m_docWithUnappliedChanges) { + m_applyChangesToQmlInspector = true; + documentChanged(m_docWithUnappliedChanges); + } + } + + m_applyChangesToQmlInspector = applyChanges; +} + +static QList<int> findRootObjectRecursive(const QmlDebugObjectReference &object, + const Document::Ptr &doc) +{ + QList<int> result; + if (object.className() == doc->componentName()) + result += object.debugId(); + + foreach (const QmlDebugObjectReference &it, object.children()) { + result += findRootObjectRecursive(it, doc); + } + return result; +} + +void QmlLiveTextPreview::updateDebugIds() +{ + if (!m_initialDoc->qmlProgram()) + return; + + DebugIdHash::const_iterator it + = m_inspectorAdapter->agent()->debugIdHash().constFind( + qMakePair<QString, int>(m_initialDoc->fileName(), 0)); + if (it != m_inspectorAdapter->agent()->debugIdHash().constEnd()) { + // Map all the object that comes from the document as it has been loaded + // by the server. + const QmlJS::Document::Ptr &doc = m_initialDoc; + + MapObjectWithDebugReference visitor; + visitor.ids = (*it); + visitor.filename = doc->fileName(); + doc->qmlProgram()->accept(&visitor); + + m_debugIds = visitor.result; + if (doc != m_previousDoc) { + Delta delta; + m_debugIds = delta(doc, m_previousDoc, m_debugIds); + } + } + + const QmlJS::Document::Ptr &doc = m_previousDoc; + if (!doc->qmlProgram()) + return; + + // Map the root nodes of the document. + if (doc->qmlProgram()->members && doc->qmlProgram()->members->member) { + UiObjectMember *root = doc->qmlProgram()->members->member; + QList<int> r; + foreach (const QmlDebugObjectReference& it, + m_inspectorAdapter->agent()->rootObjects()) { + r += findRootObjectRecursive(it, doc); + } + if (!r.isEmpty()) + m_debugIds[root] += r; + } + + // Map the node of the later created objects. + for (QHash<Document::Ptr,QSet<UiObjectMember*> >::const_iterator it + = m_createdObjects.constBegin(); + it != m_createdObjects.constEnd(); ++it) { + + const QmlJS::Document::Ptr &doc = it.key(); + + DebugIdHash::const_iterator id_it = m_inspectorAdapter->agent()->debugIdHash().constFind( + qMakePair<QString, int>(doc->fileName(), doc->editorRevision())); + if (id_it == m_inspectorAdapter->agent()->debugIdHash().constEnd()) + continue; + + MapObjectWithDebugReference visitor; + visitor.ids = *id_it; + visitor.filename = doc->fileName(); + visitor.lookupObjects = it.value(); + doc->qmlProgram()->accept(&visitor); + + Delta::DebugIdMap debugIds = visitor.result; + if (doc != m_previousDoc) { + Delta delta; + debugIds = delta(doc, m_previousDoc, debugIds); + } + for (Delta::DebugIdMap::const_iterator it2 = debugIds.constBegin(); + it2 != debugIds.constEnd(); ++it2) { + m_debugIds[it2.key()] += it2.value(); + } + } + if (m_updateNodeForOffset) + changeSelectedElements(m_lastOffsets, QString()); +} + +void QmlLiveTextPreview::changeSelectedElements(QList<int> offsets, + const QString &wordAtCursor) { - if (doc->fileName() != m_previousDoc->fileName() || m_clientProxy.isNull()) + if (m_editors.isEmpty() || !m_previousDoc) return; - bool experimentalWarningShown = false; + m_updateNodeForOffset = false; + m_lastOffsets = offsets; + QmlDebugObjectReference objectRefUnderCursor; + objectRefUnderCursor + = m_inspectorAdapter->agent()->objectForId(wordAtCursor); + + QList<int> selectedReferences; + bool containsReferenceUnderCursor = false; + + foreach (int offset, offsets) { + if (offset >= 0) { + QList<int> list = objectReferencesForOffset(offset); + + if (!containsReferenceUnderCursor + && objectRefUnderCursor.debugId() != -1) { + foreach (int id, list) { + if (id == objectRefUnderCursor.debugId()) { + containsReferenceUnderCursor = true; + break; + } + } + } + + selectedReferences << list; + } + } + + // fallback: use ref under cursor if nothing else is found + if (selectedReferences.isEmpty() + && !containsReferenceUnderCursor + && objectRefUnderCursor.debugId() != -1) { + selectedReferences << objectRefUnderCursor.debugId(); + } + + if (!selectedReferences.isEmpty()) + emit selectedItemsChanged(selectedReferences); +} + +void QmlLiveTextPreview::documentChanged(QmlJS::Document::Ptr doc) +{ + if (doc->fileName() != m_previousDoc->fileName()) + return; if (m_applyChangesToQmlInspector) { m_docWithUnappliedChanges.clear(); @@ -603,21 +563,14 @@ void QmlJSLiveTextPreview::documentChanged(QmlJS::Document::Ptr doc) if (doc && m_previousDoc && doc->fileName() == m_previousDoc->fileName() && doc->qmlProgram() && m_previousDoc->qmlProgram()) { - UpdateInspector delta(m_clientProxy.data()); + UpdateInspector delta(m_inspectorAdapter); m_debugIds = delta(m_previousDoc, doc, m_debugIds); if (delta.referenceRefreshRequired) - m_clientProxy.data()->refreshObjectTree(); + m_inspectorAdapter->agent()->refreshObjectTree(); - if (InspectorUi::instance()->showExperimentalWarning() - && delta.appliedChangesToViewer) { - showExperimentalWarning(); - experimentalWarningShown = true; - InspectorUi::instance()->setShowExperimentalWarning(false); - } - if (delta.unsyncronizableChanges != NoUnsyncronizableChanges - && !experimentalWarningShown) + if (delta.unsyncronizableChanges != NoUnsyncronizableChanges) showSyncWarning(delta.unsyncronizableChanges, delta.unsyncronizableElementName, delta.unsyncronizableChangeLine, @@ -627,30 +580,44 @@ void QmlJSLiveTextPreview::documentChanged(QmlJS::Document::Ptr doc) if (!delta.newObjects.isEmpty()) m_createdObjects[doc] += delta.newObjects; - m_clientProxy.data()->clearComponentCache(); + m_inspectorAdapter->toolsClient()->clearComponentCache(); } } else { m_docWithUnappliedChanges = doc; } } -void QmlJSLiveTextPreview::showExperimentalWarning() +QList<int> QmlLiveTextPreview::objectReferencesForOffset(quint32 offset) { - foreach (QWeakPointer<TextEditor::BaseTextEditorWidget> editor, m_editors) - if (editor) { - Core::InfoBarEntry info( - Constants::INFO_EXPERIMENTAL, - tr("You changed a QML file in Live Preview mode, which " - "modifies the running QML application. In case of " - "unexpected behavior, please reload the QML " - "application.")); - info.setCustomButtonInfo(tr("Disable Live Preview"), this, - SLOT(disableLivePreview())); - editor.data()->editorDocument()->infoBar()->addInfo(info); + QList<int> result; + QHashIterator<QmlJS::AST::UiObjectMember*, QList<int> > iter(m_debugIds); + QmlJS::AST::UiObjectMember *possibleNode = 0; + while (iter.hasNext()) { + iter.next(); + QmlJS::AST::UiObjectMember *member = iter.key(); + quint32 startOffset = member->firstSourceLocation().offset; + quint32 endOffset = member->lastSourceLocation().offset; + if (startOffset <= offset && offset <= endOffset) { + if (!possibleNode) + possibleNode = member; + if (possibleNode->firstSourceLocation().offset <= startOffset && + endOffset <= possibleNode->lastSourceLocation().offset) + possibleNode = member; } + } + if (possibleNode) { + if (possibleNode != m_nodeForOffset) { + //We have found a better match, set flag so that we can + //query again to check if this is the best match for the offset + m_updateNodeForOffset = true; + m_nodeForOffset = possibleNode; + } + result = m_debugIds.value(possibleNode); + } + return result; } -void QmlJSLiveTextPreview::showSyncWarning( +void QmlLiveTextPreview::showSyncWarning( UnsyncronizableChangeType unsyncronizableChangeType, const QString &elementName, unsigned line, unsigned column) { @@ -666,87 +633,22 @@ void QmlJSLiveTextPreview::showSyncWarning( "changed without reloading the QML application. ") .arg(elementName, QString::number(line), QString::number(column)); break; - case QmlJSLiveTextPreview::NoUnsyncronizableChanges: + case QmlLiveTextPreview::NoUnsyncronizableChanges: default: return; } errorMessage.append(tr("You can continue debugging, but behavior can be unexpected.")); - foreach (QWeakPointer<TextEditor::BaseTextEditorWidget> editor, m_editors) { + foreach (TextEditor::BaseTextEditorWidget *editor, m_editors) { if (editor) { - Core::InfoBar *infoBar = editor.data()->editorDocument()->infoBar(); + Core::InfoBar *infoBar = editor->editorDocument()->infoBar(); infoBar->addInfo(Core::InfoBarEntry( - QLatin1String(Constants::INFO_OUT_OF_SYNC), + QLatin1String("Debugger.Inspector.OutOfSyncWarning"), errorMessage)); } } } -void QmlJSLiveTextPreview::reloadQmlViewer() -{ - foreach (QWeakPointer<TextEditor::BaseTextEditorWidget> editor, m_editors) { - if (editor) { - Core::InfoBar *infoBar = editor.data()->editorDocument()->infoBar(); - infoBar->removeInfo(Constants::INFO_OUT_OF_SYNC); - } - } - emit reloadQmlViewerRequested(); -} - -void QmlJSLiveTextPreview::disableLivePreview() -{ - foreach (QWeakPointer<TextEditor::BaseTextEditorWidget> editor, m_editors) { - if (editor) { - Core::InfoBar *infoBar = editor.data()->editorDocument()->infoBar(); - infoBar->removeInfo(Constants::INFO_OUT_OF_SYNC); - } - } - emit disableLivePreviewRequested(); -} - -void QmlJSLiveTextPreview::setApplyChangesToQmlInspector(bool applyChanges) -{ - if (applyChanges && !m_applyChangesToQmlInspector) { - if (m_docWithUnappliedChanges) { - m_applyChangesToQmlInspector = true; - documentChanged(m_docWithUnappliedChanges); - } - } - - m_applyChangesToQmlInspector = applyChanges; -} - -void QmlJSLiveTextPreview::setClientProxy(ClientProxy *clientProxy) -{ - if (m_clientProxy.data()) { - disconnect(m_clientProxy.data(), SIGNAL(objectTreeUpdated()), - this, SLOT(updateDebugIds())); - } - - m_clientProxy = clientProxy; - - if (m_clientProxy.data()) { - connect(m_clientProxy.data(), SIGNAL(objectTreeUpdated()), - SLOT(updateDebugIds())); - - foreach (QWeakPointer<TextEditor::BaseTextEditorWidget> editWidget, - m_editors) - if (editWidget) - connect(editWidget.data(), - SIGNAL(selectedElementsChanged(QList<int>,QString)), - this, - SLOT(changeSelectedElements(QList<int>,QString))); - } else { - foreach (QWeakPointer<TextEditor::BaseTextEditorWidget> editWidget, - m_editors) - if (editWidget) - disconnect(editWidget.data(), - SIGNAL(selectedElementsChanged(QList<int>,QString)), - this, - SLOT(changeSelectedElements(QList<int>,QString))); - } -} - } // namespace Internal -} // namespace QmlJSInspector +} // namespace Debugger diff --git a/src/plugins/qmljsinspector/qmljslivetextpreview.h b/src/plugins/debugger/qml/qmllivetextpreview.h index 59f922d33b..0ba3a30b6f 100644 --- a/src/plugins/qmljsinspector/qmljslivetextpreview.h +++ b/src/plugins/debugger/qml/qmllivetextpreview.h @@ -30,21 +30,14 @@ ** **************************************************************************/ -#ifndef SCRIPTBINDINGREWRITER_H -#define SCRIPTBINDINGREWRITER_H +#ifndef QMLLIVETEXTPREVIEW_H +#define QMLLIVETEXTPREVIEW_H #include <QObject> -#include <QWeakPointer> -#include <texteditor/basetexteditor.h> -#include <qmldebug/baseenginedebugclient.h> -#include <qmljs/parser/qmljsastfwd_p.h> +#include <texteditor/basetexteditor.h> #include <qmljs/qmljsdocument.h> -QT_FORWARD_DECLARE_CLASS(QTextDocument) - -using namespace QmlDebug; - namespace Core { class IEditor; } @@ -53,41 +46,28 @@ namespace QmlJS { class ModelManagerInterface; } -namespace QmlJSInspector { +namespace Debugger { namespace Internal { -class ClientProxy; - +class UpdateInspector; +class QmlInspectorAdapter; -class QmlJSLiveTextPreview : public QObject +class QmlLiveTextPreview : public QObject { Q_OBJECT public: - explicit QmlJSLiveTextPreview(const QmlJS::Document::Ptr &doc, - const QmlJS::Document::Ptr &initDoc, - ClientProxy *clientProxy, - QObject *parent = 0); - //void updateDocuments(); + QmlLiveTextPreview(const QmlJS::Document::Ptr &doc, + const QmlJS::Document::Ptr &initDoc, + QmlInspectorAdapter *inspectorAdapter, + QObject *parent = 0); void associateEditor(Core::IEditor *editor); void unassociateEditor(Core::IEditor *editor); - void setActiveObject(const QmlDebugObjectReference &object); - void mapObjectToQml(const QmlDebugObjectReference &object); void resetInitialDoc(const QmlJS::Document::Ptr &doc); - void setClientProxy(ClientProxy *clientProxy); - - enum UnsyncronizableChangeType { - NoUnsyncronizableChanges, - AttributeChangeWarning, - ElementChangeWarning - }; - signals: - void selectedItemsChanged(const QList<QmlDebugObjectReference> &objects); - void reloadQmlViewerRequested(); - void disableLivePreviewRequested(); + void selectedItemsChanged(const QList<int> &debugIds); public slots: void setApplyChangesToQmlInspector(bool applyChanges); @@ -96,17 +76,18 @@ public slots: private slots: void changeSelectedElements(QList<int> offsets, const QString &wordAtCursor); void documentChanged(QmlJS::Document::Ptr doc); - void disableLivePreview(); - void reloadQmlViewer(); private: + enum UnsyncronizableChangeType { + NoUnsyncronizableChanges, + AttributeChangeWarning, + ElementChangeWarning + }; + QList<int> objectReferencesForOffset(quint32 offset); - QVariant castToLiteral(const QString &expression, - QmlJS::AST::UiScriptBinding *scriptBinding); void showSyncWarning(UnsyncronizableChangeType unsyncronizableChangeType, const QString &elementName, unsigned line, unsigned column); - void showExperimentalWarning(); private: QHash<QmlJS::AST::UiObjectMember*, QList<int> > m_debugIds; @@ -114,20 +95,20 @@ private: QmlJS::Document::Ptr m_previousDoc; QmlJS::Document::Ptr m_initialDoc; //the document that was loaded by the server - QString m_filename; - QList<QWeakPointer<TextEditor::BaseTextEditorWidget> > m_editors; + QList<QPointer<TextEditor::BaseTextEditorWidget> > m_editors; bool m_applyChangesToQmlInspector; QmlJS::Document::Ptr m_docWithUnappliedChanges; - QWeakPointer<ClientProxy> m_clientProxy; + QmlInspectorAdapter *m_inspectorAdapter; QList<int> m_lastOffsets; QmlJS::AST::UiObjectMember *m_nodeForOffset; bool m_updateNodeForOffset; + friend class UpdateInspector; }; } // namespace Internal -} // namespace QmlJSInspector +} // namespace Debugger -#endif // SCRIPTBINDINGREWRITER_H +#endif // QMLLIVETEXTPREVIEW_H diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index f90f9b7672..12f9a58744 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -172,6 +172,10 @@ WatchModel::WatchModel(WatchHandler *handler, WatchType type) m_root->iname = "tooltip"; m_root->name = WatchHandler::tr("Tooltip"); break; + case InspectWatch: + m_root->iname = "inspect"; + m_root->name = WatchHandler::tr("Inspector"); + break; } } @@ -576,7 +580,7 @@ bool WatchModel::canFetchMore(const QModelIndex &index) const { WatchItem *item = watchItem(index); QTC_ASSERT(item, return false); - return index.isValid() && m_handler->m_contentsValid && !m_fetchTriggered.contains(item->iname); + return index.isValid() && contentIsValid() && !m_fetchTriggered.contains(item->iname); } void WatchModel::fetchMore(const QModelIndex &index) @@ -713,6 +717,14 @@ int WatchModel::itemFormat(const WatchData &data) const return theTypeFormats.value(stripForFormat(data.type), -1); } +bool WatchModel::contentIsValid() const +{ + // inspector doesn't follow normal beginCycle()/endCycle() + if (m_type == InspectWatch) + return true; + return m_handler->m_contentsValid; +} + static inline QString expression(const WatchItem *item) { if (!item->exp.isEmpty()) @@ -812,7 +824,7 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const static const QVariant red(QColor(200, 0, 0)); static const QVariant gray(QColor(140, 140, 140)); switch (idx.column()) { - case 1: return (!data.valueEnabled || !m_handler->m_contentsValid) ? gray + case 1: return (!data.valueEnabled || !contentIsValid()) ? gray : data.changed ? red : QVariant(); } break; @@ -927,7 +939,7 @@ bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int ro Qt::ItemFlags WatchModel::flags(const QModelIndex &idx) const { - if (!m_handler->m_contentsValid) + if (!contentIsValid()) return Qt::ItemFlags(); if (!idx.isValid()) @@ -1276,6 +1288,7 @@ WatchHandler::WatchHandler(DebuggerEngine *engine) m_locals = new WatchModel(this, LocalsWatch); m_watchers = new WatchModel(this, WatchersWatch); m_tooltips = new WatchModel(this, TooltipsWatch); + m_inspect = new WatchModel(this, InspectWatch); m_contentsValid = false; m_resetLocationScheduled = false; @@ -1294,6 +1307,7 @@ void WatchHandler::beginCycle(bool fullCycle) m_locals->beginCycle(fullCycle); m_watchers->beginCycle(fullCycle); m_tooltips->beginCycle(fullCycle); + // don't sync m_inspect here: It's updated on it's own } void WatchHandler::endCycle() @@ -1309,6 +1323,16 @@ void WatchHandler::endCycle() updateWatchersWindow(); } +void WatchHandler::beginCycle(WatchType type, bool fullCycle) +{ + model(type)->beginCycle(fullCycle); +} + +void WatchHandler::endCycle(WatchType type) +{ + model(type)->endCycle(); +} + void WatchHandler::cleanup() { m_expandedINames.clear(); @@ -1316,10 +1340,12 @@ void WatchHandler::cleanup() m_return->reinitialize(); m_locals->reinitialize(); m_tooltips->reinitialize(); + m_inspect->reinitialize(); m_return->m_fetchTriggered.clear(); m_locals->m_fetchTriggered.clear(); m_watchers->m_fetchTriggered.clear(); m_tooltips->m_fetchTriggered.clear(); + m_inspect->m_fetchTriggered.clear(); #if 1 for (EditHandlers::ConstIterator it = m_editHandlers.begin(); it != m_editHandlers.end(); ++it) { @@ -1336,6 +1362,7 @@ void WatchHandler::emitAllChanged() m_locals->emitAllChanged(); m_watchers->emitAllChanged(); m_tooltips->emitAllChanged(); + m_inspect->emitAllChanged(); } void WatchHandler::insertData(const WatchData &data) @@ -1347,9 +1374,10 @@ void WatchHandler::insertData(const WatchData &data) return; } - if (data.isSomethingNeeded() && data.iname.contains('.')) { + if (data.isSomethingNeeded() && data.iname.contains(".")) { MODEL_DEBUG("SOMETHING NEEDED: " << data.toString()); - if (!m_engine->isSynchronous()) { + if (!m_engine->isSynchronous() + || data.iname.startsWith("inspect.")) { WatchModel *model = modelForIName(data.iname); QTC_ASSERT(model, return); model->insertData(data); @@ -1381,6 +1409,7 @@ void WatchHandler::reinsertAllData() m_watchers->reinsertAllData(); m_tooltips->reinsertAllData(); m_return->reinsertAllData(); + m_inspect->reinsertAllData(); } // Bulk-insertion @@ -1685,6 +1714,7 @@ WatchModel *WatchHandler::model(WatchType type) const case LocalsWatch: return m_locals; case WatchersWatch: return m_watchers; case TooltipsWatch: return m_tooltips; + case InspectWatch: return m_inspect; } QTC_CHECK(false); return 0; @@ -1700,6 +1730,8 @@ WatchModel *WatchHandler::modelForIName(const QByteArray &iname) const return m_tooltips; if (iname.startsWith("watch")) return m_watchers; + if (iname.startsWith("inspect")) + return m_inspect; QTC_ASSERT(false, qDebug() << "INAME: " << iname); return 0; } @@ -1746,6 +1778,7 @@ void WatchHandler::setFormat(const QByteArray &type0, int format) m_locals->emitDataChanged(1); m_watchers->emitDataChanged(1); m_tooltips->emitDataChanged(1); + m_inspect->emitDataChanged(1); } int WatchHandler::format(const QByteArray &iname) const @@ -1905,6 +1938,7 @@ void WatchHandler::resetLocation() m_locals->invalidateAll(); m_watchers->invalidateAll(); m_tooltips->invalidateAll(); + m_inspect->invalidateAll(); } } @@ -1914,6 +1948,14 @@ bool WatchHandler::isValidToolTip(const QByteArray &iname) const return item && !item->type.trimmed().isEmpty(); } +void WatchHandler::setCurrentModelIndex(WatchType modelType, + const QModelIndex &index) +{ + if (WatchModel *m = model(modelType)) { + emit m->setCurrentIndex(index); + } +} + QHash<QByteArray, int> WatchHandler::watcherNames() { return theWatcherNames; diff --git a/src/plugins/debugger/watchhandler.h b/src/plugins/debugger/watchhandler.h index e7ac34b362..c99fe88685 100644 --- a/src/plugins/debugger/watchhandler.h +++ b/src/plugins/debugger/watchhandler.h @@ -55,7 +55,8 @@ enum WatchType ReturnWatch, LocalsWatch, WatchersWatch, - TooltipsWatch + TooltipsWatch, + InspectWatch }; enum IntegerFormat @@ -78,6 +79,9 @@ public: virtual int rowCount(const QModelIndex &idx = QModelIndex()) const; virtual int columnCount(const QModelIndex &idx) const; +signals: + void setCurrentIndex(const QModelIndex &index); + private: QVariant data(const QModelIndex &index, int role) const; bool setData(const QModelIndex &index, const QVariant &value, int role); @@ -131,6 +135,7 @@ private: DebuggerEngine *engine() const; QString display(const WatchItem *item, int col) const; int itemFormat(const WatchData &data) const; + bool contentIsValid() const; int m_generationCounter; WatchHandler *m_handler; @@ -157,6 +162,10 @@ public: void beginCycle(bool fullCycle = true); // Called at begin of updateLocals() cycle void updateWatchers(); // Called after locals are fetched void endCycle(); // Called after all results have been received + + void beginCycle(WatchType type, bool fullCycle = true); + void endCycle(WatchType type); + void showEditValue(const WatchData &data); void insertData(const WatchData &data); @@ -204,6 +213,8 @@ public: void resetLocation(); bool isValidToolTip(const QByteArray &iname) const; + void setCurrentModelIndex(WatchType modelType, const QModelIndex &index); + private: friend class WatchModel; @@ -230,6 +241,7 @@ private: WatchModel *m_locals; WatchModel *m_watchers; WatchModel *m_tooltips; + WatchModel *m_inspect; DebuggerEngine *m_engine; int m_watcherCounter; diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp index 1c98f5f309..2153eb9bf9 100644 --- a/src/plugins/debugger/watchwindow.cpp +++ b/src/plugins/debugger/watchwindow.cpp @@ -994,11 +994,15 @@ void WatchTreeView::setModel(QAbstractItemModel *model) setRootIsDecorated(true); if (header()) { header()->setDefaultAlignment(Qt::AlignLeft); - if (m_type != LocalsType) + if (m_type != LocalsType && m_type != InspectType) header()->hide(); } connect(model, SIGNAL(layoutChanged()), SLOT(resetHelper())); + + QTC_ASSERT(qobject_cast<WatchModel*>(model), return); + connect(model, SIGNAL(setCurrentIndex(QModelIndex)), + SLOT(setCurrentIndex(QModelIndex))); } void WatchTreeView::resetHelper() diff --git a/src/plugins/debugger/watchwindow.h b/src/plugins/debugger/watchwindow.h index 8e07825dc6..9a28f6380e 100644 --- a/src/plugins/debugger/watchwindow.h +++ b/src/plugins/debugger/watchwindow.h @@ -49,7 +49,7 @@ class WatchTreeView : public BaseTreeView Q_OBJECT public: - enum Type { ReturnType, LocalsType, TooltipType, WatchersType }; + enum Type { ReturnType, LocalsType, TooltipType, WatchersType, InspectType }; explicit WatchTreeView(Type type, QWidget *parent = 0); Type type() const { return m_type; } diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index 14906a5648..87cc7ef1d8 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -61,8 +61,7 @@ include(../../qtcreator.pri) contains(QT_CONFIG, declarative)|contains(QT_CONFIG, quick1) { SUBDIRS += \ - plugin_qmlprojectmanager \ - plugin_qmljsinspector + plugin_qmlprojectmanager include(../private_headers.pri) exists($${QT_PRIVATE_HEADERS}/QtDeclarative/private/qdeclarativecontext_p.h) { @@ -193,6 +192,7 @@ plugin_debugger.subdir = debugger plugin_debugger.depends = plugin_projectexplorer plugin_debugger.depends += plugin_coreplugin plugin_debugger.depends += plugin_cpptools +plugin_debugger.depends += plugin_qmljstools plugin_fakevim.subdir = fakevim plugin_fakevim.depends = plugin_coreplugin @@ -264,10 +264,6 @@ plugin_qmldesigner.depends += plugin_qt4projectmanager plugin_qmldesigner.depends += plugin_qmlprojectmanager plugin_qmldesigner.depends += plugin_cpptools -plugin_qmljsinspector.subdir = qmljsinspector -plugin_qmljsinspector.depends += plugin_debugger -plugin_qmljsinspector.depends += plugin_qmljstools - plugin_mercurial.subdir = mercurial plugin_mercurial.depends = plugin_vcsbase plugin_mercurial.depends += plugin_projectexplorer diff --git a/src/plugins/qmljsinspector/QmlJSInspector.pluginspec.in b/src/plugins/qmljsinspector/QmlJSInspector.pluginspec.in deleted file mode 100644 index 98d166e4ee..0000000000 --- a/src/plugins/qmljsinspector/QmlJSInspector.pluginspec.in +++ /dev/null @@ -1,26 +0,0 @@ -<plugin name=\"QmlJSInspector\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\"> - <vendor>Nokia Corporation</vendor> - <copyright>(C) 2011 Nokia Corporation</copyright> - <license> -Commercial Usage - -Licensees holding valid Qt Commercial licenses may use this plugin 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 plugin may be used under the terms of the GNU Lesser -General Public License version 2.1 as published by the Free Software -Foundation. 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.</license> - <category>Qt Quick</category> - <description>Debugger for QML files</description> - <url>http://qt.nokia.com</url> - <dependencyList> - <dependency name=\"Debugger\" version=\"$$QTCREATOR_VERSION\"/> - <dependency name=\"QmlJSTools\" version=\"$$QTCREATOR_VERSION\"/> - </dependencyList> -</plugin> diff --git a/src/plugins/qmljsinspector/basetoolsclient.cpp b/src/plugins/qmljsinspector/basetoolsclient.cpp deleted file mode 100644 index 8ac8a935df..0000000000 --- a/src/plugins/qmljsinspector/basetoolsclient.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** GNU Lesser General Public License Usage -** -** 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. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ - -#include "basetoolsclient.h" - -namespace QmlJSInspector { -namespace Internal { - -BaseToolsClient::BaseToolsClient(QmlDebug::QmlDebugConnection* client, QLatin1String clientName) - : QmlDebugClient(clientName, client) -{ - setObjectName(clientName); -} - -void BaseToolsClient::statusChanged(Status status) -{ - emit connectedStatusChanged(status); -} - -void BaseToolsClient::recurseObjectIdList(const QmlDebug::QmlDebugObjectReference &ref, - QList<int> &debugIds, QList<QString> &objectIds) -{ - debugIds << ref.debugId(); - objectIds << ref.idString(); - foreach (const QmlDebug::QmlDebugObjectReference &child, ref.children()) - recurseObjectIdList(child, debugIds, objectIds); -} - -} // namespace Internal -} // namespace QmlJSInspector diff --git a/src/plugins/qmljsinspector/basetoolsclient.h b/src/plugins/qmljsinspector/basetoolsclient.h deleted file mode 100644 index 7653d39b85..0000000000 --- a/src/plugins/qmljsinspector/basetoolsclient.h +++ /dev/null @@ -1,104 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** GNU Lesser General Public License Usage -** -** 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. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ - -#ifndef BASETOOLSCLIENT_H -#define BASETOOLSCLIENT_H - -#include <qmldebug/qmldebugclient.h> -#include <qmldebug/baseenginedebugclient.h> - -namespace QmlJSInspector { -namespace Internal { - -class BaseToolsClient : public QmlDebug::QmlDebugClient -{ - Q_OBJECT -public: - BaseToolsClient(QmlDebug::QmlDebugConnection* client, QLatin1String clientName); - - virtual void setCurrentObjects(const QList<int> &debugIds) = 0; - virtual void reloadViewer() = 0; - virtual void setDesignModeBehavior(bool inDesignMode) = 0; - virtual void setAnimationSpeed(qreal slowDownFactor) = 0; - virtual void setAnimationPaused(bool paused) = 0; - virtual void changeToSelectTool() = 0; - virtual void changeToSelectMarqueeTool() = 0; - virtual void changeToZoomTool() = 0; - virtual void showAppOnTop(bool showOnTop) = 0; - - virtual void createQmlObject(const QString &qmlText, int parentDebugId, - const QStringList &imports, const QString &filename, - int order) = 0; - virtual void destroyQmlObject(int debugId) = 0; - virtual void reparentQmlObject(int debugId, int newParent) = 0; - - virtual void applyChangesToQmlFile() = 0; - virtual void applyChangesFromQmlFile() = 0; - - virtual QList<int> currentObjects() const = 0; - - // ### Qt 4.8: remove if we can have access to qdeclarativecontextdata or id's - virtual void setObjectIdList( - const QList<QmlDebug::QmlDebugObjectReference> &objectRoots) = 0; - - virtual void clearComponentCache() = 0; - -signals: - void connectedStatusChanged(QmlDebugClient::Status status); - - void currentObjectsChanged(const QList<int> &debugIds); - void selectToolActivated(); - void selectMarqueeToolActivated(); - void zoomToolActivated(); - void animationSpeedChanged(qreal slowdownFactor); - void animationPausedChanged(bool paused); - void designModeBehaviorChanged(bool inDesignMode); - void showAppOnTopChanged(bool showAppOnTop); - void reloaded(); // the server has reloadetd he document - - void logActivity(QString client, QString message); - -protected: - void statusChanged(Status); - - void recurseObjectIdList(const QmlDebug::QmlDebugObjectReference &ref, - QList<int> &debugIds, QList<QString> &objectIds); -protected: - enum LogDirection { - LogSend, - LogReceive - }; -}; - -} // namespace Internal -} // namespace QmlJSInspector - -#endif // BASETOOLSCLIENT_H diff --git a/src/plugins/qmljsinspector/declarativetoolsclient.cpp b/src/plugins/qmljsinspector/declarativetoolsclient.cpp deleted file mode 100644 index f2d95072a9..0000000000 --- a/src/plugins/qmljsinspector/declarativetoolsclient.cpp +++ /dev/null @@ -1,442 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** GNU Lesser General Public License Usage -** -** 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. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ - -#include "declarativetoolsclient.h" -#include "qmljsclientproxy.h" -#include "qmljsinspectorconstants.h" - -using namespace QmlJSDebugger; - -namespace QmlJSInspector { -namespace Internal { - -DeclarativeToolsClient::DeclarativeToolsClient(QmlDebugConnection *client) - : BaseToolsClient(client,QLatin1String(Constants::QDECLARATIVE_OBSERVER_MODE)), - m_connection(client) -{ - setObjectName(name()); -} - -void DeclarativeToolsClient::messageReceived(const QByteArray &message) -{ - QDataStream ds(message); - - InspectorProtocol::Message type; - ds >> type; - - switch (type) { - case InspectorProtocol::CurrentObjectsChanged: { - int objectCount; - ds >> objectCount; - - log(LogReceive, type, QString("%1 [list of debug ids]").arg(objectCount)); - - m_currentDebugIds.clear(); - - for (int i = 0; i < objectCount; ++i) { - int debugId; - ds >> debugId; - if (debugId != -1) - m_currentDebugIds << debugId; - } - - emit currentObjectsChanged(m_currentDebugIds); - break; - } - case InspectorProtocol::ToolChanged: { - int toolId; - ds >> toolId; - - log(LogReceive, type, QString::number(toolId)); - - if (toolId == Constants::ZoomMode) { - emit zoomToolActivated(); - } else if (toolId == Constants::SelectionToolMode) { - emit selectToolActivated(); - } else if (toolId == Constants::MarqueeSelectionToolMode) { - emit selectMarqueeToolActivated(); - } - break; - } - case InspectorProtocol::AnimationSpeedChanged: { - qreal slowDownFactor; - ds >> slowDownFactor; - - log(LogReceive, type, QString::number(slowDownFactor)); - - emit animationSpeedChanged(slowDownFactor); - break; - } - case InspectorProtocol::AnimationPausedChanged: { - bool paused; - ds >> paused; - - log(LogReceive, type, paused ? QLatin1String("true") - : QLatin1String("false")); - - emit animationPausedChanged(paused); - break; - } - case InspectorProtocol::SetDesignMode: { - bool inDesignMode; - ds >> inDesignMode; - - log(LogReceive, type, QLatin1String(inDesignMode ? "true" : "false")); - - emit designModeBehaviorChanged(inDesignMode); - break; - } - case InspectorProtocol::ShowAppOnTop: { - bool showAppOnTop; - ds >> showAppOnTop; - - log(LogReceive, type, QLatin1String(showAppOnTop ? "true" : "false")); - - emit showAppOnTopChanged(showAppOnTop); - break; - } - case InspectorProtocol::Reloaded: { - log(LogReceive, type); - emit reloaded(); - break; - } - default: - log(LogReceive, type, QLatin1String("Warning: Not handling message")); - } -} - -QList<int> DeclarativeToolsClient::currentObjects() const -{ - return m_currentDebugIds; -} - -void DeclarativeToolsClient::setCurrentObjects(const QList<int> &debugIds) -{ - if (!m_connection || !m_connection->isConnected()) - return; - - if (debugIds == m_currentDebugIds) - return; - - m_currentDebugIds = debugIds; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::SetCurrentObjects; - ds << cmd - << debugIds.length(); - - foreach (int id, debugIds) { - ds << id; - } - - log(LogSend, cmd, QString("%1 [list of ids]").arg(debugIds.length())); - - sendMessage(message); -} - -void DeclarativeToolsClient::setObjectIdList( - const QList<QmlDebug::QmlDebugObjectReference> &objectRoots) -{ - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - QList<int> debugIds; - QList<QString> objectIds; - - foreach (const QmlDebug::QmlDebugObjectReference &ref, objectRoots) - recurseObjectIdList(ref, debugIds, objectIds); - - InspectorProtocol::Message cmd = InspectorProtocol::ObjectIdList; - ds << cmd - << debugIds.length(); - - Q_ASSERT(debugIds.length() == objectIds.length()); - - for(int i = 0; i < debugIds.length(); ++i) { - ds << debugIds[i] << objectIds[i]; - } - - log(LogSend, cmd, - QString("%1 %2 [list of debug / object ids]").arg(debugIds.length())); - - sendMessage(message); -} - -void DeclarativeToolsClient::clearComponentCache() -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::ClearComponentCache; - ds << cmd; - - log(LogSend, cmd); - - sendMessage(message); -} - -void DeclarativeToolsClient::reloadViewer() -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::Reload; - ds << cmd; - - log(LogSend, cmd); - - sendMessage(message); -} - -void DeclarativeToolsClient::setDesignModeBehavior(bool inDesignMode) -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::SetDesignMode; - ds << cmd - << inDesignMode; - - log(LogSend, cmd, QLatin1String(inDesignMode ? "true" : "false")); - - sendMessage(message); -} - -void DeclarativeToolsClient::setAnimationSpeed(qreal slowDownFactor) -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::SetAnimationSpeed; - ds << cmd - << slowDownFactor; - - - log(LogSend, cmd, QString::number(slowDownFactor)); - - sendMessage(message); -} - -void DeclarativeToolsClient::setAnimationPaused(bool paused) -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::SetAnimationPaused; - ds << cmd - << paused; - - log(LogSend, cmd, paused ? QLatin1String("true") : QLatin1String("false")); - - sendMessage(message); -} - -void DeclarativeToolsClient::changeToSelectTool() -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::ChangeTool; - InspectorProtocol::Tool tool = InspectorProtocol::SelectTool; - ds << cmd - << tool; - - log(LogSend, cmd, InspectorProtocol::toString(tool)); - - sendMessage(message); -} - -void DeclarativeToolsClient::changeToSelectMarqueeTool() -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::ChangeTool; - InspectorProtocol::Tool tool = InspectorProtocol::SelectMarqueeTool; - ds << cmd - << tool; - - log(LogSend, cmd, InspectorProtocol::toString(tool)); - - sendMessage(message); -} - -void DeclarativeToolsClient::changeToZoomTool() -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::ChangeTool; - InspectorProtocol::Tool tool = InspectorProtocol::ZoomTool; - ds << cmd - << tool; - - log(LogSend, cmd, InspectorProtocol::toString(tool)); - - sendMessage(message); -} - -void DeclarativeToolsClient::showAppOnTop(bool showOnTop) -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::ShowAppOnTop; - ds << cmd << showOnTop; - - log(LogSend, cmd, QLatin1String(showOnTop ? "true" : "false")); - - sendMessage(message); -} - -void DeclarativeToolsClient::createQmlObject(const QString &qmlText, - int parentDebugId, - const QStringList &imports, - const QString &filename, int order) -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::CreateObject; - ds << cmd - << qmlText - << parentDebugId - << imports - << filename - << order; - - log(LogSend, cmd, QString("%1 %2 [%3] %4").arg(qmlText, - QString::number(parentDebugId), - imports.join(","), filename)); - - sendMessage(message); -} - -void DeclarativeToolsClient::destroyQmlObject(int debugId) -{ - if (!m_connection || !m_connection->isConnected()) - return; - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::DestroyObject; - ds << cmd << debugId; - - log(LogSend, cmd, QString::number(debugId)); - - sendMessage(message); -} - -void DeclarativeToolsClient::reparentQmlObject(int debugId, int newParent) -{ - if (!m_connection || !m_connection->isConnected()) - return; - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - - InspectorProtocol::Message cmd = InspectorProtocol::MoveObject; - ds << cmd - << debugId - << newParent; - - log(LogSend, cmd, QString("%1 %2").arg(QString::number(debugId), - QString::number(newParent))); - - sendMessage(message); -} - - -void DeclarativeToolsClient::applyChangesToQmlFile() -{ - if (!m_connection || !m_connection->isConnected()) - return; - - // TODO -} - -void DeclarativeToolsClient::applyChangesFromQmlFile() -{ - if (!m_connection || !m_connection->isConnected()) - return; - - // TODO -} - -void DeclarativeToolsClient::log(LogDirection direction, - InspectorProtocol::Message message, - const QString &extra) -{ - QString msg; - if (direction == LogSend) - msg += QLatin1String(" sending "); - else - msg += QLatin1String(" receiving "); - - msg += InspectorProtocol::toString(message); - msg += QLatin1Char(' '); - msg += extra; - emit logActivity(name(), msg); -} - -} // namespace Internal -} // namespace QmlJSInspector diff --git a/src/plugins/qmljsinspector/declarativetoolsclient.h b/src/plugins/qmljsinspector/declarativetoolsclient.h deleted file mode 100644 index f38e565046..0000000000 --- a/src/plugins/qmljsinspector/declarativetoolsclient.h +++ /dev/null @@ -1,90 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** GNU Lesser General Public License Usage -** -** 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. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ - -#ifndef DECLARATIVETOOLSCLIENT_H -#define DECLARATIVETOOLSCLIENT_H - -#include "basetoolsclient.h" - -#include <inspectorprotocol.h> - -namespace QmlJSInspector { -namespace Internal { - -class DeclarativeToolsClient : public BaseToolsClient -{ - Q_OBJECT -public: - DeclarativeToolsClient(QmlDebug::QmlDebugConnection *client); - - void setCurrentObjects(const QList<int> &debugIds); - void reloadViewer(); - void setDesignModeBehavior(bool inDesignMode); - void setAnimationSpeed(qreal slowDownFactor); - void setAnimationPaused(bool paused); - void changeToSelectTool(); - void changeToSelectMarqueeTool(); - void changeToZoomTool(); - void showAppOnTop(bool showOnTop); - - void createQmlObject(const QString &qmlText, int parentDebugId, - const QStringList &imports, const QString &filename, - int order); - void destroyQmlObject(int debugId); - void reparentQmlObject(int debugId, int newParent); - - void applyChangesToQmlFile(); - void applyChangesFromQmlFile(); - - QList<int> currentObjects() const; - - // ### Qt 4.8: remove if we can have access to qdeclarativecontextdata or id's - void setObjectIdList(const QList<QmlDebug::QmlDebugObjectReference> &objectRoots); - - void clearComponentCache(); - -protected: - void messageReceived(const QByteArray &); - -private: - void log(LogDirection direction, - QmlJSDebugger::InspectorProtocol::Message message, - const QString &extra = QString()); - -private: - QList<int> m_currentDebugIds; - QmlDebug::QmlDebugConnection *m_connection; -}; - -} // namespace Internal -} // namespace QmlJSInspector - -#endif // DECLARATIVETOOLSCLIENT_H diff --git a/src/plugins/qmljsinspector/images/from-qml.png b/src/plugins/qmljsinspector/images/from-qml.png Binary files differdeleted file mode 100644 index e3a6e24c19..0000000000 --- a/src/plugins/qmljsinspector/images/from-qml.png +++ /dev/null diff --git a/src/plugins/qmljsinspector/images/pause-small.png b/src/plugins/qmljsinspector/images/pause-small.png Binary files differdeleted file mode 100644 index 114d89b12b..0000000000 --- a/src/plugins/qmljsinspector/images/pause-small.png +++ /dev/null diff --git a/src/plugins/qmljsinspector/images/pause.png b/src/plugins/qmljsinspector/images/pause.png Binary files differdeleted file mode 100644 index c5d33a2d04..0000000000 --- a/src/plugins/qmljsinspector/images/pause.png +++ /dev/null diff --git a/src/plugins/qmljsinspector/images/play-small.png b/src/plugins/qmljsinspector/images/play-small.png Binary files differdeleted file mode 100644 index 011598a746..0000000000 --- a/src/plugins/qmljsinspector/images/play-small.png +++ /dev/null diff --git a/src/plugins/qmljsinspector/images/play.png b/src/plugins/qmljsinspector/images/play.png Binary files differdeleted file mode 100644 index af75fcdb62..0000000000 --- a/src/plugins/qmljsinspector/images/play.png +++ /dev/null diff --git a/src/plugins/qmljsinspector/images/reload.png b/src/plugins/qmljsinspector/images/reload.png Binary files differdeleted file mode 100644 index b5afefb32b..0000000000 --- a/src/plugins/qmljsinspector/images/reload.png +++ /dev/null diff --git a/src/plugins/qmljsinspector/images/select-marquee-small.png b/src/plugins/qmljsinspector/images/select-marquee-small.png Binary files differdeleted file mode 100644 index 92fe40d1ad..0000000000 --- a/src/plugins/qmljsinspector/images/select-marquee-small.png +++ /dev/null diff --git a/src/plugins/qmljsinspector/images/select-marquee.png b/src/plugins/qmljsinspector/images/select-marquee.png Binary files differdeleted file mode 100644 index a28381f117..0000000000 --- a/src/plugins/qmljsinspector/images/select-marquee.png +++ /dev/null diff --git a/src/plugins/qmljsinspector/images/select.png b/src/plugins/qmljsinspector/images/select.png Binary files differdeleted file mode 100644 index 5b0376f6f7..0000000000 --- a/src/plugins/qmljsinspector/images/select.png +++ /dev/null diff --git a/src/plugins/qmljsinspector/images/to-qml-small.png b/src/plugins/qmljsinspector/images/to-qml-small.png Binary files differdeleted file mode 100644 index 2ab951fd08..0000000000 --- a/src/plugins/qmljsinspector/images/to-qml-small.png +++ /dev/null diff --git a/src/plugins/qmljsinspector/images/to-qml.png b/src/plugins/qmljsinspector/images/to-qml.png Binary files differdeleted file mode 100644 index 84ff48fa95..0000000000 --- a/src/plugins/qmljsinspector/images/to-qml.png +++ /dev/null diff --git a/src/plugins/qmljsinspector/images/zoom.png b/src/plugins/qmljsinspector/images/zoom.png Binary files differdeleted file mode 100644 index 4abf314440..0000000000 --- a/src/plugins/qmljsinspector/images/zoom.png +++ /dev/null diff --git a/src/plugins/qmljsinspector/qmljsclientproxy.cpp b/src/plugins/qmljsinspector/qmljsclientproxy.cpp deleted file mode 100644 index 3d5c2fe68b..0000000000 --- a/src/plugins/qmljsinspector/qmljsclientproxy.cpp +++ /dev/null @@ -1,810 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** -** GNU Lesser General Public License Usage -** -** 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. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ - -#include "qmljsclientproxy.h" -#include "qmltoolsclient.h" -#include "declarativetoolsclient.h" -#include "qmljsinspector.h" - -#include <qmldebug/qmldebugconstants.h> -#include <debugger/debuggerplugin.h> -#include <debugger/debuggerrunner.h> -#include <debugger/qml/qmlengine.h> -#include <debugger/qml/qmladapter.h> -#include <extensionsystem/pluginmanager.h> -#include <utils/qtcassert.h> -#include <projectexplorer/project.h> -#include <qmldebug/declarativeenginedebugclient.h> -#include <qmldebug/qmlenginedebugclient.h> - -#include <QUrl> -#include <QAbstractSocket> - -using namespace QmlJSInspector::Internal; - -ClientProxy::ClientProxy(Debugger::QmlAdapter *adapter, QObject *parent) - : QObject(parent) - , m_adapter(adapter) - , m_engineClient(0) - , m_inspectorHelperClient(0) - , m_engineQueryId(0) - , m_contextQueryId(0) - , m_isConnected(false) -{ - connectToServer(); -} - -ClientProxy::~ClientProxy() -{ - m_adapter.data()->setEngineDebugClient(0); - m_adapter.data()->setCurrentSelectedDebugInfo(-1); -} - -void ClientProxy::connectToServer() -{ - DeclarativeEngineDebugClient *client1 = new DeclarativeEngineDebugClient( - m_adapter.data()->connection()); - QmlEngineDebugClient *client2 = new QmlEngineDebugClient( - m_adapter.data()->connection()); - - connect(client1, SIGNAL(newStatus(QmlDebugClient::Status)), - SLOT(clientStatusChanged(QmlDebugClient::Status))); - connect(client1, SIGNAL(newStatus(QmlDebugClient::Status)), - SLOT(engineClientStatusChanged(QmlDebugClient::Status))); - - connect(client2, SIGNAL(newStatus(QmlDebugClient::Status)), - SLOT(clientStatusChanged(QmlDebugClient::Status))); - connect(client2, SIGNAL(newStatus(QmlDebugClient::Status)), - SLOT(engineClientStatusChanged(QmlDebugClient::Status))); - - DeclarativeToolsClient *toolsClient1 = new DeclarativeToolsClient( - m_adapter.data()->connection()); - QmlToolsClient *toolsClient2 = new QmlToolsClient( - m_adapter.data()->connection()); - - connect(toolsClient1, SIGNAL(connectedStatusChanged(QmlDebugClient::Status)), - SLOT(clientStatusChanged(QmlDebugClient::Status))); - connect(toolsClient1, SIGNAL(connectedStatusChanged(QmlDebugClient::Status)), - SLOT(toolsClientStatusChanged(QmlDebugClient::Status))); - - connect(toolsClient2, SIGNAL(connectedStatusChanged(QmlDebugClient::Status)), - SLOT(clientStatusChanged(QmlDebugClient::Status))); - connect(toolsClient2, SIGNAL(connectedStatusChanged(QmlDebugClient::Status)), - SLOT(toolsClientStatusChanged(QmlDebugClient::Status))); - - updateConnected(); -} - -void ClientProxy::clientStatusChanged(QmlDebugClient::Status status) -{ - QString serviceName; - float version = 0; - if (QmlDebugClient *client - = qobject_cast<QmlDebugClient*>(sender())) { - serviceName = client->name(); - version = client->serviceVersion(); - } - - if (m_adapter) - m_adapter.data()->logServiceStatusChange(serviceName, version, status); - - updateConnected(); -} - -QmlDebugClient *ClientProxy::engineDebugClient() const -{ - return m_engineClient; -} - -QmlDebugClient *ClientProxy::toolsClient() const -{ - return m_inspectorHelperClient; -} - -void ClientProxy::engineClientStatusChanged( - QmlDebugClient::Status status) -{ - if (status == QmlDebugClient::Enabled) { - m_engineClient = qobject_cast<BaseEngineDebugClient*>(sender()); - connect(m_engineClient, SIGNAL(newObjects()), this, SLOT(newObjects())); - connect(m_engineClient, SIGNAL(result(quint32,QVariant,QByteArray)), - SLOT(onResult(quint32,QVariant,QByteArray))); - connect(m_engineClient, SIGNAL(valueChanged(int,QByteArray,QVariant)), - SLOT(objectWatchTriggered(int,QByteArray,QVariant))); - m_adapter.data()->setEngineDebugClient(m_engineClient); - updateConnected(); - } -} - -void ClientProxy::toolsClientStatusChanged( - QmlDebugClient::Status status) -{ - if (status == QmlDebugClient::Enabled) { - m_inspectorHelperClient = qobject_cast<BaseToolsClient*>(sender()); - connect(m_inspectorHelperClient, SIGNAL(currentObjectsChanged(QList<int>)), - SLOT(onCurrentObjectsChanged(QList<int>))); - connect(m_inspectorHelperClient, SIGNAL(zoomToolActivated()), - SIGNAL(zoomToolActivated())); - connect(m_inspectorHelperClient, SIGNAL(selectToolActivated()), - SIGNAL(selectToolActivated())); - connect(m_inspectorHelperClient, SIGNAL(selectMarqueeToolActivated()), - SIGNAL(selectMarqueeToolActivated())); - connect(m_inspectorHelperClient, SIGNAL(animationSpeedChanged(qreal)), - SIGNAL(animationSpeedChanged(qreal))); - connect(m_inspectorHelperClient, SIGNAL(animationPausedChanged(bool)), - SIGNAL(animationPausedChanged(bool))); - connect(m_inspectorHelperClient, SIGNAL(designModeBehaviorChanged(bool)), - SIGNAL(designModeBehaviorChanged(bool))); - connect(m_inspectorHelperClient, SIGNAL(showAppOnTopChanged(bool)), - SIGNAL(showAppOnTopChanged(bool))); - connect(m_inspectorHelperClient, SIGNAL(reloaded()), this, - SIGNAL(serverReloaded())); - connect(m_inspectorHelperClient, SIGNAL(logActivity(QString,QString)), - m_adapter.data(), SLOT(logServiceActivity(QString,QString))); - updateConnected(); - } -} - -void ClientProxy::refreshObjectTree() -{ - if (!m_contextQueryId) { - m_objectTreeQueryIds.clear(); - queryEngineContext(m_engines.value(0).debugId()); - } -} - -void ClientProxy::onCurrentObjectsChanged(const QList<int> &debugIds, - bool requestIfNeeded) -{ - QList<QmlDebugObjectReference> selectedItems; - m_fetchCurrentObjects.clear(); - m_fetchCurrentObjectsQueryIds.clear(); - foreach (int debugId, debugIds) { - QmlDebugObjectReference ref = objectReferenceForId(debugId); - if (ref.debugId() != -1 && !ref.needsMoreData()) { - selectedItems << ref; - } else if (requestIfNeeded) { - m_fetchCurrentObjectsQueryIds - << fetchContextObject(QmlDebugObjectReference(debugId)); - - } - } - - emit selectedItemsChanged(selectedItems); -} - -void ClientProxy::onCurrentObjectsFetched(quint32 queryId, - const QVariant &result) -{ - m_fetchCurrentObjectsQueryIds.removeOne(queryId); - QmlDebugObjectReference obj - = qvariant_cast<QmlDebugObjectReference>(result); - m_fetchCurrentObjects.push_front(obj); - - if (!getObjectHierarchy(obj)) - return; - - foreach (const QmlDebugObjectReference &o, m_fetchCurrentObjects) - addObjectToTree(o, false); - emit selectedItemsChanged(QList<QmlDebugObjectReference>() << - m_fetchCurrentObjects.last()); -} - -bool ClientProxy::getObjectHierarchy(const QmlDebugObjectReference &obj) -{ - QmlDebugObjectReference parent = objectReferenceForId(obj.parentId()); - //for root object - if (obj.parentId() == -1) - return true; - - //for other objects - if (parent.debugId() == -1 || parent.needsMoreData()) { - m_fetchCurrentObjectsQueryIds - << fetchContextObject(QmlDebugObjectReference(obj.parentId())); - } else { - return getObjectHierarchy(parent); - } - return false; -} - -void ClientProxy::setSelectedItemsByDebugId(const QList<int> &debugIds) -{ - if (!isConnected()) - return; - - m_inspectorHelperClient->setCurrentObjects(debugIds); -} - -void ClientProxy::setSelectedItemsByObjectId( - const QList<QmlDebugObjectReference> &objectRefs) -{ - if (isConnected()) { - QList<int> debugIds; - - foreach (const QmlDebugObjectReference &ref, objectRefs) { - debugIds << ref.debugId(); - } - - m_inspectorHelperClient->setCurrentObjects(debugIds); - } -} - -void ClientProxy::addObjectToTree(const QmlDebugObjectReference &obj, - bool notify) -{ - int count = m_rootObjects.count(); - for (int i = 0; i < count; i++) { - if (m_rootObjects[i].insertObjectInTree(obj)) { - buildDebugIdHashRecursive(obj); - if (notify) - emit objectTreeUpdated(); - break; - } - } -} - -QmlDebugObjectReference ClientProxy::objectReferenceForId(int debugId) const -{ - foreach (const QmlDebugObjectReference &it, m_rootObjects) { - QmlDebugObjectReference result = objectReferenceForId(debugId, it); - if (result.debugId() == debugId) - return result; - } - return QmlDebugObjectReference(); -} - -void ClientProxy::log(LogDirection direction, const QString &message) -{ - QString msg; - if (direction == LogSend) { - msg += " sending "; - } else { - msg += " receiving "; - } - msg += message; - - if (m_adapter) - m_adapter.data()->logServiceActivity("QmlDebug", msg); -} - -QList<QmlDebugObjectReference> -QmlJSInspector::Internal::ClientProxy::rootObjectReference() const -{ - return m_rootObjects; -} - -QmlDebugObjectReference -ClientProxy::objectReferenceForId( - int debugId, - const QmlDebugObjectReference &objectRef) const -{ - if (objectRef.debugId() == debugId) - return objectRef; - - foreach (const QmlDebugObjectReference &child, objectRef.children()) { - QmlDebugObjectReference result = objectReferenceForId(debugId, child); - if (result.debugId() == debugId) - return result; - } - - return QmlDebugObjectReference(); -} - -QmlDebugObjectReference ClientProxy::objectReferenceForId( - const QString &objectId) const -{ - if (!objectId.isEmpty() && objectId[0].isLower()) { - const QList<QmlDebugObjectReference> refs = objectReferences(); - foreach (const QmlDebugObjectReference &ref, refs) { - if (ref.idString() == objectId) - return ref; - } - } - return QmlDebugObjectReference(); -} - -QmlDebugObjectReference ClientProxy::objectReferenceForLocation( - int line, int column) const -{ - const QList<QmlDebugObjectReference> refs = objectReferences(); - foreach (const QmlDebugObjectReference &ref, refs) { - if (ref.source().lineNumber() == line - && ref.source().columnNumber() == column) - return ref; - } - - return QmlDebugObjectReference(); -} - -QList<QmlDebugObjectReference> ClientProxy::objectReferences() const -{ - QList<QmlDebugObjectReference> result; - foreach (const QmlDebugObjectReference &it, m_rootObjects) { - result.append(objectReferences(it)); - } - return result; -} - -QList<QmlDebugObjectReference> -ClientProxy::objectReferences(const QmlDebugObjectReference &objectRef) const -{ - QList<QmlDebugObjectReference> result; - result.append(objectRef); - - foreach (const QmlDebugObjectReference &child, objectRef.children()) { - result.append(objectReferences(child)); - } - - return result; -} - -quint32 ClientProxy::setBindingForObject(int objectDebugId, - const QString &propertyName, - const QVariant &value, - bool isLiteralValue, - QString source, - int line) -{ - if (objectDebugId == -1) - return false; - - if (propertyName == QLatin1String("id")) - return false; // Crashes the QMLViewer. - - if (!isConnected()) - return false; - - log(LogSend, QString("SET_BINDING %1 %2 %3 %4").arg( - QString::number(objectDebugId), propertyName, value.toString(), - QString(isLiteralValue ? "true" : "false"))); - - quint32 queryId = m_engineClient->setBindingForObject( - objectDebugId, propertyName, value.toString(), isLiteralValue, - source, line); - - if (!queryId) - log(LogSend, QString("failed!")); - - return queryId; -} - -quint32 ClientProxy::setMethodBodyForObject(int objectDebugId, - const QString &methodName, - const QString &methodBody) -{ - if (objectDebugId == -1) - return false; - - if (!isConnected()) - return false; - - log(LogSend, QString("SET_METHOD_BODY %1 %2 %3").arg( - QString::number(objectDebugId), methodName, methodBody)); - - quint32 queryId = m_engineClient->setMethodBody( - objectDebugId, methodName, methodBody); - - if (!queryId) - log(LogSend, QString("failed!")); - - return queryId; -} - -quint32 ClientProxy::resetBindingForObject(int objectDebugId, - const QString &propertyName) -{ - if (objectDebugId == -1) - return false; - - if (!isConnected()) - return false; - - log(LogSend, QString("RESET_BINDING %1 %2").arg( - QString::number(objectDebugId), propertyName)); - - quint32 queryId = m_engineClient->resetBindingForObject( - objectDebugId, propertyName); - - if (!queryId) - log(LogSend, QString("failed!")); - - return queryId; -} - -quint32 ClientProxy::queryExpressionResult(int objectDebugId, - const QString &expr) -{ - if (objectDebugId == -1) - return 0; - - if (!isConnected()) - return 0; - - bool block = false; - if (m_adapter) - block = m_adapter.data()->disableJsDebugging(true); - - log(LogSend, QString("EVAL_EXPRESSION %1 %2").arg( - QString::number(objectDebugId), expr)); - quint32 queryId - = m_engineClient->queryExpressionResult(objectDebugId, expr); - - if (m_adapter) - m_adapter.data()->disableJsDebugging(block); - return queryId; -} - -void ClientProxy::clearComponentCache() -{ - if (isConnected()) - m_inspectorHelperClient->clearComponentCache(); -} - -bool ClientProxy::addObjectWatch(int objectDebugId) -{ - if (objectDebugId == -1) - return false; - - if (!isConnected()) - return false; - - // already set - if (m_objectWatches.contains(objectDebugId)) - return true; - - QmlDebugObjectReference ref = objectReferenceForId(objectDebugId); - if (ref.debugId() != objectDebugId) - return false; - - // is flooding the debugging output log! - // log(LogSend, QString("WATCH_PROPERTY %1").arg(objectDebugId)); - - if (m_engineClient->addWatch(ref)) - m_objectWatches.append(objectDebugId); - - return false; -} - -bool ClientProxy::isObjectBeingWatched(int objectDebugId) -{ - return m_objectWatches.contains(objectDebugId); -} - - -void ClientProxy::objectWatchTriggered(int objectDebugId, - const QByteArray &propertyName, - const QVariant &propertyValue) -{ - if (m_objectWatches.contains(objectDebugId)) - emit propertyChanged(objectDebugId, propertyName, propertyValue); -} - -bool ClientProxy::removeObjectWatch(int objectDebugId) -{ - if (objectDebugId == -1) - return false; - - if (!m_objectWatches.contains(objectDebugId)) - return false; - - if (!isConnected()) - return false; - - m_objectWatches.removeOne(objectDebugId); - return true; -} - -void ClientProxy::removeAllObjectWatches() -{ - foreach (int watchedObject, m_objectWatches) - removeObjectWatch(watchedObject); -} - -void ClientProxy::queryEngineContext(int id) -{ - if (id < 0) - return; - - if (!isConnected()) - return; - - if (m_contextQueryId) - m_contextQueryId = 0; - - log(LogSend, QString("LIST_OBJECTS %1").arg(QString::number(id))); - - m_contextQueryId - = m_engineClient->queryRootContexts(QmlDebugEngineReference(id)); -} - -void ClientProxy::contextChanged(const QVariant &value) -{ - - if (m_contextQueryId) { - m_contextQueryId = 0; - emit rootContext(value); - } -} - -quint32 ClientProxy::fetchContextObject(const QmlDebugObjectReference &obj) -{ - if (!isConnected()) - return 0; - - log(LogSend, QString("FETCH_OBJECT %1").arg(obj.idString())); - return m_engineClient->queryObject(obj); -} - -void ClientProxy::fetchRootObjects( - const QmlDebugContextReference &context, bool clear) -{ - if (!isConnected()) - return; - if (clear) { - m_rootObjects.clear(); - m_objectTreeQueryIds.clear(); - } - foreach (const QmlDebugObjectReference & obj, context.objects()) { - quint32 queryId = 0; - using namespace QmlDebug::Constants; - if (m_engineClient->objectName() == QML_DEBUGGER && - m_engineClient->serviceVersion() >= CURRENT_SUPPORTED_VERSION) { - //Fetch only root objects - if (obj.parentId() == -1) - queryId = fetchContextObject(obj); - } else { - queryId = m_engineClient->queryObjectRecursive(obj); - } - - if (queryId) - m_objectTreeQueryIds << queryId; - } - foreach (const QmlDebugContextReference &child, context.contexts()) { - fetchRootObjects(child, false); - } -} - -void ClientProxy::insertObjectInTreeIfNeeded( - const QmlDebugObjectReference &object) -{ - if (!m_rootObjects.contains(object)) - return; - int count = m_rootObjects.count(); - for (int i = 0; i < count; i++) { - if (m_rootObjects[i].parentId() < 0 - && m_rootObjects[i].insertObjectInTree(object)) { - m_rootObjects.removeOne(object); - break; - } - } -} - -void ClientProxy::onResult(quint32 queryId, const QVariant &value, - const QByteArray &type) -{ - if (type == "FETCH_OBJECT_R") { - log(LogReceive, QString("FETCH_OBJECT_R %1").arg( - qvariant_cast<QmlDebugObjectReference>(value).idString())); - } else { - log(LogReceive, QLatin1String(type)); - } - - if (m_objectTreeQueryIds.contains(queryId)) - objectTreeFetched(queryId, value); - else if (queryId == m_engineQueryId) - updateEngineList(value); - else if (queryId == m_contextQueryId) - contextChanged(value); - else if (m_fetchCurrentObjectsQueryIds.contains(queryId)) - onCurrentObjectsFetched(queryId, value); - else - emit result(queryId, value); -} - -void ClientProxy::objectTreeFetched(quint32 queryId, const QVariant &result) -{ - QmlDebugObjectReference obj - = qvariant_cast<QmlDebugObjectReference>(result); - m_rootObjects.append(obj); - - m_objectTreeQueryIds.removeOne(queryId); - if (m_objectTreeQueryIds.isEmpty()) { - int old_count = m_debugIdHash.count(); - m_debugIdHash.clear(); - m_debugIdHash.reserve(old_count + 1); - foreach (const QmlDebugObjectReference &it, m_rootObjects) - buildDebugIdHashRecursive(it); - emit objectTreeUpdated(); - - if (isConnected()) { - if (!m_inspectorHelperClient->currentObjects().isEmpty()) - onCurrentObjectsChanged(m_inspectorHelperClient->currentObjects(), - false); - - m_inspectorHelperClient->setObjectIdList(m_rootObjects); - } - } -} - -void ClientProxy::buildDebugIdHashRecursive(const QmlDebugObjectReference &ref) -{ - QUrl fileUrl = ref.source().url(); - int lineNum = ref.source().lineNumber(); - int colNum = ref.source().columnNumber(); - int rev = 0; - - // handle the case where the url contains the revision number encoded. - //(for object created by the debugger) - static QRegExp rx("(.*)_(\\d+):(\\d+)$"); - if (rx.exactMatch(fileUrl.path())) { - fileUrl.setPath(rx.cap(1)); - rev = rx.cap(2).toInt(); - lineNum += rx.cap(3).toInt() - 1; - } - - const QString filePath - = InspectorUi::instance()->findFileInProject(fileUrl); - - // append the debug ids in the hash - m_debugIdHash[qMakePair<QString, int>(filePath, rev)][qMakePair<int, int>( - lineNum, colNum)].append(ref.debugId()); - - foreach (const QmlDebugObjectReference &it, ref.children()) - buildDebugIdHashRecursive(it); -} - - -void ClientProxy::reloadQmlViewer() -{ - if (isConnected()) - m_inspectorHelperClient->reloadViewer(); -} - -void ClientProxy::setDesignModeBehavior(bool inDesignMode) -{ - if (isConnected()) - m_inspectorHelperClient->setDesignModeBehavior(inDesignMode); -} - -void ClientProxy::setAnimationSpeed(qreal slowDownFactor) -{ - if (isConnected()) - m_inspectorHelperClient->setAnimationSpeed(slowDownFactor); -} - -void ClientProxy::setAnimationPaused(bool paused) -{ - if (isConnected()) - m_inspectorHelperClient->setAnimationPaused(paused); -} - -void ClientProxy::changeToZoomTool() -{ - if (isConnected()) - m_inspectorHelperClient->changeToZoomTool(); -} -void ClientProxy::changeToSelectTool() -{ - if (isConnected()) - m_inspectorHelperClient->changeToSelectTool(); -} - -void ClientProxy::changeToSelectMarqueeTool() -{ - if (isConnected()) - m_inspectorHelperClient->changeToSelectMarqueeTool(); -} - -void ClientProxy::showAppOnTop(bool showOnTop) -{ - if (isConnected()) - m_inspectorHelperClient->showAppOnTop(showOnTop); -} - -void ClientProxy::createQmlObject(const QString &qmlText, int parentDebugId, - const QStringList &imports, - const QString &filename, int order) -{ - if (isConnected()) - m_inspectorHelperClient->createQmlObject(qmlText, parentDebugId, imports, - filename, order); -} - -void ClientProxy::destroyQmlObject(int debugId) -{ - if (isConnected()) - m_inspectorHelperClient->destroyQmlObject(debugId); -} - -void ClientProxy::reparentQmlObject(int debugId, int newParent) -{ - if (isConnected()) - m_inspectorHelperClient->reparentQmlObject(debugId, newParent); -} - -void ClientProxy::updateConnected() -{ - bool isConnected = m_inspectorHelperClient && - m_inspectorHelperClient->status() == QmlDebugClient::Enabled && - m_engineClient && - m_engineClient->status() == QmlDebugClient::Enabled; - - if (isConnected != m_isConnected) { - m_isConnected = isConnected; - if (isConnected) { - emit connected(); - reloadEngines(); - } else { - emit disconnected(); - } - } -} - -void ClientProxy::reloadEngines() -{ - if (!isConnected()) - return; - - emit aboutToReloadEngines(); - - log(LogSend, QString("LIST_ENGINES")); - - m_engineQueryId = m_engineClient->queryAvailableEngines(); -} - -QList<QmlDebugEngineReference> ClientProxy::engines() const -{ - return m_engines; -} - -void ClientProxy::updateEngineList(const QVariant &value) -{ - m_engines = qvariant_cast<QmlDebugEngineReferenceList>(value); - m_engineQueryId = 0; - emit enginesChanged(); -} - -Debugger::QmlAdapter *ClientProxy::qmlAdapter() const -{ - return m_adapter.data(); -} - -bool ClientProxy::isConnected() const -{ - return m_isConnected; -} - -void ClientProxy::newObjects() -{ - log(LogReceive, QString("OBJECT_CREATED")); - refreshObjectTree(); -} diff --git a/src/plugins/qmljsinspector/qmljsclientproxy.h b/src/plugins/qmljsinspector/qmljsclientproxy.h deleted file mode 100644 index 727961ea05..0000000000 --- a/src/plugins/qmljsinspector/qmljsclientproxy.h +++ /dev/null @@ -1,219 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** -** GNU Lesser General Public License Usage -** -** 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. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ -#ifndef QMLJSCLIENTPROXY_H -#define QMLJSCLIENTPROXY_H - -#include "qmljsinspectorplugin.h" -#include <qmldebug/baseenginedebugclient.h> -#include <QObject> - -QT_FORWARD_DECLARE_CLASS(QUrl) - -using namespace QmlDebug; - -namespace Debugger { -class QmlAdapter; -} - -namespace QmlJSInspector { - -//map <filename, editorRevision> -> <lineNumber, columnNumber> -> debugIds -typedef -QHash<QPair<QString, int>, QHash<QPair<int, int>, QList<int> > > DebugIdHash; - -namespace Internal { - -class InspectorPlugin; -class BaseToolsClient; - - -class ClientProxy : public QObject -{ - Q_OBJECT - -public: - explicit ClientProxy(Debugger::QmlAdapter *adapter, QObject *parent = 0); - ~ClientProxy(); - - quint32 setBindingForObject(int objectDebugId, - const QString &propertyName, - const QVariant &value, - bool isLiteralValue, - QString source, - int line); - - quint32 setMethodBodyForObject(int objectDebugId, const QString &methodName, - const QString &methodBody); - quint32 resetBindingForObject(int objectDebugId, - const QString &propertyName); - quint32 queryExpressionResult(int objectDebugId, const QString &expr); - void clearComponentCache(); - - bool addObjectWatch(int objectDebugId); - bool isObjectBeingWatched(int objectDebugId); - bool removeObjectWatch(int objectDebugId); - void removeAllObjectWatches(); - - // returns the object references - QList<QmlDebugObjectReference> objectReferences() const; - QmlDebugObjectReference objectReferenceForId(int debugId) const; - QmlDebugObjectReference objectReferenceForId(const QString &objectId) const; - QmlDebugObjectReference objectReferenceForLocation(int line, - int column) const; - QList<QmlDebugObjectReference> rootObjectReference() const; - DebugIdHash debugIdHash() const { return m_debugIdHash; } - - bool isConnected() const; - - void setSelectedItemsByDebugId(const QList<int> &debugIds); - void setSelectedItemsByObjectId( - const QList<QmlDebugObjectReference> &objectRefs); - - QList<QmlDebugEngineReference> engines() const; - - Debugger::QmlAdapter *qmlAdapter() const; - - quint32 fetchContextObject(const QmlDebugObjectReference& obj); - void addObjectToTree(const QmlDebugObjectReference &obj, bool notify = true); - void fetchRootObjects(const QmlDebugContextReference &context, bool clear); - void insertObjectInTreeIfNeeded(const QmlDebugObjectReference &object); - - QmlDebugClient *engineDebugClient() const; - QmlDebugClient *toolsClient() const; - -signals: - void objectTreeUpdated(); - void connectionStatusMessage(const QString &text); - - void aboutToReloadEngines(); - void enginesChanged(); - - void selectedItemsChanged( - const QList<QmlDebugObjectReference> &selectedItems); - - void connected(); - void disconnected(); - - void selectToolActivated(); - void selectMarqueeToolActivated(); - void zoomToolActivated(); - void animationSpeedChanged(qreal slowDownFactor); - void animationPausedChanged(bool paused); - void designModeBehaviorChanged(bool inDesignMode); - void showAppOnTopChanged(bool showAppOnTop); - void serverReloaded(); - void propertyChanged(int debugId, const QByteArray &propertyName, - const QVariant &propertyValue); - - void result(quint32 queryId, const QVariant &result); - void rootContext(const QVariant &context); - -public slots: - void refreshObjectTree(); - void queryEngineContext(int id); - void reloadQmlViewer(); - - void setDesignModeBehavior(bool inDesignMode); - void setAnimationSpeed(qreal slowDownFactor); - void setAnimationPaused(bool paused); - void changeToZoomTool(); - void changeToSelectTool(); - void changeToSelectMarqueeTool(); - void showAppOnTop(bool showOnTop); - void createQmlObject(const QString &qmlText, int parentDebugId, - const QStringList &imports, - const QString &filename = QString(), int order = 0); - void destroyQmlObject(int debugId); - void reparentQmlObject(int debugId, int newParent); - -private slots: - void connectToServer(); - void clientStatusChanged(QmlDebugClient::Status status); - void engineClientStatusChanged(QmlDebugClient::Status status); - void toolsClientStatusChanged(QmlDebugClient::Status status); - - void onCurrentObjectsChanged(const QList<int> &debugIds, - bool requestIfNeeded = true); - void newObjects(); - void objectWatchTriggered(int debugId, const QByteArray &propertyName, - const QVariant &propertyValue); - void onResult(quint32 queryId, const QVariant &value, - const QByteArray &type); - void onCurrentObjectsFetched(quint32 queryId, const QVariant &result); - -private: - void contextChanged(const QVariant &value); - void updateEngineList(const QVariant &value); - void objectTreeFetched(quint32 queryId, const QVariant &result); - void updateConnected(); - void reloadEngines(); - bool getObjectHierarchy(const QmlDebugObjectReference &obj); - - QList<QmlDebugObjectReference> objectReferences( - const QmlDebugObjectReference &objectRef) const; - QmlDebugObjectReference objectReferenceForId( - int debugId, - const QmlDebugObjectReference &ref) const; - - enum LogDirection { - LogSend, - LogReceive - }; - void log(LogDirection direction, const QString &message); - - -private: - void buildDebugIdHashRecursive(const QmlDebugObjectReference &ref); - - QWeakPointer<Debugger::QmlAdapter> m_adapter; - BaseEngineDebugClient *m_engineClient; - BaseToolsClient *m_inspectorHelperClient; - - quint32 m_engineQueryId; - quint32 m_contextQueryId; - QList<quint32> m_objectTreeQueryIds; - QList<quint32> m_fetchCurrentObjectsQueryIds; - - QList<QmlDebugObjectReference> m_rootObjects; - QList<QmlDebugObjectReference> m_fetchCurrentObjects; - QmlDebugEngineReferenceList m_engines; - DebugIdHash m_debugIdHash; - - QList<int> m_objectWatches; - - bool m_isConnected; -}; - -} // namespace Internal -} // namespace QmlJSInspector - -#endif // QMLJSCLIENTPROXY_H diff --git a/src/plugins/qmljsinspector/qmljscontextcrumblepath.cpp b/src/plugins/qmljsinspector/qmljscontextcrumblepath.cpp deleted file mode 100644 index ceef69125d..0000000000 --- a/src/plugins/qmljsinspector/qmljscontextcrumblepath.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** -** GNU Lesser General Public License Usage -** -** 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. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ -#include "qmljscontextcrumblepath.h" - -#include <QMouseEvent> -#include <QDebug> - -namespace QmlJSInspector { -namespace Internal { - -ContextCrumblePath::ContextCrumblePath(QWidget *parent) - : CrumblePath(parent) - , m_isEmpty(true) -{ - updateContextPath(QStringList(), QList<int>()); -} - -void ContextCrumblePath::updateContextPath(const QStringList &path, - const QList<int> &debugIds) -{ - Q_ASSERT(path.count() == debugIds.count()); - - CrumblePath::clear(); - - m_isEmpty = path.isEmpty(); - if (m_isEmpty) { - pushElement(tr("[no context]"), -2); - } else { - for (int i = 0; i < path.count(); i++) - pushElement(path[i], debugIds[i]); - } -} - -void ContextCrumblePath::addChildren(const QStringList &childrenNames, - const QList<int> &childrenDebugIds) -{ - Q_ASSERT(childrenNames.count() == childrenDebugIds.count()); - for (int i = 0; i < childrenNames.count(); i++) - addChild(childrenNames[i], childrenDebugIds[i]); - - //Sort them alphabetically - if (childrenDebugIds.count()) - sortChildren(); -} - -void ContextCrumblePath::clear() -{ - updateContextPath(QStringList(), QList<int>()); -} - -bool ContextCrumblePath::isEmpty() const -{ - return m_isEmpty; -} - -int ContextCrumblePath::debugIdForIndex(int index) const -{ - return CrumblePath::dataForIndex(index).toInt(); -} - -} // namespace Internal -} // namespace QmlJSInspector diff --git a/src/plugins/qmljsinspector/qmljscontextcrumblepath.h b/src/plugins/qmljsinspector/qmljscontextcrumblepath.h deleted file mode 100644 index 6ee083fc1e..0000000000 --- a/src/plugins/qmljsinspector/qmljscontextcrumblepath.h +++ /dev/null @@ -1,64 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** -** GNU Lesser General Public License Usage -** -** 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. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ -#ifndef QMLJSCONTEXTCRUMBLEPATH_H -#define QMLJSCONTEXTCRUMBLEPATH_H - -#include <utils/crumblepath.h> -#include <QStringList> - -namespace QmlJSInspector { -namespace Internal { - -class ContextCrumblePath : public Utils::CrumblePath -{ - Q_OBJECT - -public: - ContextCrumblePath(QWidget *parent = 0); - - bool isEmpty() const; - int debugIdForIndex(int index) const; - -public slots: - void updateContextPath(const QStringList &path, const QList<int> &debugIds); - void addChildren(const QStringList &childrenNames, - const QList<int> &childrenDebugIds); - void clear(); - -private: - bool m_isEmpty; -}; - -} // namespace Internal -} // namespace QmlJSInspector - -#endif // QMLJSCONTEXTCRUMBLEPATH_H diff --git a/src/plugins/qmljsinspector/qmljsinspector.cpp b/src/plugins/qmljsinspector/qmljsinspector.cpp deleted file mode 100644 index 2b0a19b8cf..0000000000 --- a/src/plugins/qmljsinspector/qmljsinspector.cpp +++ /dev/null @@ -1,1048 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** -** GNU Lesser General Public License Usage -** -** 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. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ - -#include "qmljsinspectorconstants.h" -#include "qmljsinspector.h" -#include "qmljsinspectortoolbar.h" -#include "qmljsclientproxy.h" -#include "qmljslivetextpreview.h" -#include "qmljscontextcrumblepath.h" -#include "qmljsinspectorsettings.h" -#include "qmljspropertyinspector.h" - -#include <qmljs/qmljsmodelmanagerinterface.h> -#include <qmljs/qmljsdocument.h> -#include <qmljs/parser/qmljsast_p.h> -#include <qmljseditor/qmljseditorconstants.h> -#include <qmljseditor/qmljseditor.h> -#include <debugger/debuggermainwindow.h> -#include <debugger/debuggerplugin.h> -#include <debugger/qml/qmlengine.h> -#include <debugger/debuggerstartparameters.h> -#include <debugger/qml/qmladapter.h> -#include <qmldebug/qmldebugconstants.h> - -#include <utils/filterlineedit.h> -#include <utils/qtcassert.h> -#include <utils/styledbar.h> -#include <utils/stylehelper.h> - -#include <coreplugin/icontext.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/id.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 <texteditor/basetexteditor.h> - -#include <projectexplorer/runconfiguration.h> -#include <projectexplorer/buildconfiguration.h> -#include <projectexplorer/projectexplorer.h> -#include <projectexplorer/projectexplorerconstants.h> -#include <projectexplorer/project.h> -#include <projectexplorer/target.h> -#include <projectexplorer/applicationrunconfiguration.h> - -#include <extensionsystem/pluginmanager.h> - -#include <aggregation/aggregate.h> -#include <find/treeviewfind.h> - -#include <QDebug> -#include <QStringList> -#include <QTimer> -#include <QtPlugin> -#include <QDateTime> - -#include <QLabel> -#include <QDockWidget> -#include <QVBoxLayout> -#include <QAction> -#include <QLineEdit> -#include <QLabel> -#include <QPainter> -#include <QSpinBox> -#include <QMessageBox> -#include <QTextBlock> - -#include <QToolTip> -#include <QCursor> -#include <QHostAddress> - -using namespace QmlJS; -using namespace QmlJS::AST; -using namespace QmlJSInspector::Internal; - -enum { - MaxConnectionAttempts = 50, - ConnectionAttemptDefaultInterval = 75, - - // used when debugging with c++ - connection can take a lot of time - ConnectionAttemptSimultaneousInterval = 500 -}; - -InspectorUi *InspectorUi::m_instance = 0; - -InspectorUi::InspectorUi(QObject *parent) - : QObject(parent) - , m_listeningToEditorManager(false) - , m_toolBar(0) - , m_crumblePath(0) - , m_propertyInspector(0) - , m_settings(new InspectorSettings(this)) - , m_clientProxy(0) - , m_debugQuery(0) - , m_selectionCallbackExpected(false) - , m_cursorPositionChangedExternally(false) - , m_onCrumblePathClicked(false) -{ - m_instance = this; - m_toolBar = new QmlJsInspectorToolBar(this); -} - -InspectorUi::~InspectorUi() -{ -} - -void InspectorUi::setupUi() -{ - setupDockWidgets(); - restoreSettings(); - - disable(); -} - -void InspectorUi::saveSettings() const -{ - m_settings->saveSettings(Core::ICore::settings()); -} - -void InspectorUi::restoreSettings() -{ - m_settings->restoreSettings(Core::ICore::settings()); -} - -void InspectorUi::setDebuggerEngine(QObject *engine) -{ - Debugger::Internal::QmlEngine *qmlEngine = - qobject_cast<Debugger::Internal::QmlEngine *>(engine); - QTC_ASSERT(qmlEngine, return); - Debugger::DebuggerEngine *masterEngine = qmlEngine; - if (qmlEngine->isSlaveEngine()) - masterEngine = qmlEngine->masterEngine(); - - connect(qmlEngine, - SIGNAL(tooltipRequested(QPoint,TextEditor::ITextEditor*,int)), - this, - SLOT(showDebuggerTooltip(QPoint,TextEditor::ITextEditor*,int))); - connect(masterEngine, SIGNAL(stateChanged(Debugger::DebuggerState)), - this, SLOT(onEngineStateChanged(Debugger::DebuggerState))); -} - -void InspectorUi::onEngineStateChanged(Debugger::DebuggerState state) -{ - bool enable = state == Debugger::InferiorRunOk; - if (enable) - m_toolBar->enable(); - else - m_toolBar->disable(); - m_crumblePath->setEnabled(enable); - m_propertyInspector->setContentsValid(enable); - m_propertyInspector->reset(); -} - -// Get semantic info from QmlJSTextEditorWidget -// (we use the meta object system here to avoid having to link -// against qmljseditor) -QmlJSTools::SemanticInfo getSemanticInfo(QPlainTextEdit *qmlJSTextEdit) -{ - QmlJSTools::SemanticInfo info; - QTC_ASSERT(QLatin1String(qmlJSTextEdit->metaObject()->className()) - == QLatin1String("QmlJSEditor::QmlJSTextEditorWidget"), - return info); - QTC_ASSERT(qmlJSTextEdit->metaObject()->indexOfProperty("semanticInfo") - != -1, return info); - - info = qmlJSTextEdit->property("semanticInfo") - .value<QmlJSTools::SemanticInfo>(); - return info; -} - -void InspectorUi::showDebuggerTooltip(const QPoint &mousePos, - TextEditor::ITextEditor *editor, - int cursorPos) -{ - Q_UNUSED(mousePos); - if (m_clientProxy && editor->id() - == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) { - TextEditor::BaseTextEditor *baseTextEditor = - static_cast<TextEditor::BaseTextEditor*>(editor); - QPlainTextEdit *editWidget - = qobject_cast<QPlainTextEdit*>(baseTextEditor->widget()); - - QmlJSTools::SemanticInfo semanticInfo = getSemanticInfo(editWidget); - - QTextCursor tc(editWidget->document()); - tc.setPosition(cursorPos); - tc.movePosition(QTextCursor::StartOfWord); - tc.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); - - QString wordAtCursor = tc.selectedText(); - QString query; - QLatin1Char doubleQuote('"'); - - QmlJS::AST::Node *qmlNode = semanticInfo.astNodeAt(cursorPos); - if (!qmlNode) - return; - - QmlDebugObjectReference ref; - if (QmlJS::AST::Node *node - = semanticInfo.declaringMemberNoProperties(cursorPos)) { - if (QmlJS::AST::UiObjectMember *objMember - = node->uiObjectMemberCast()) { - ref = m_clientProxy->objectReferenceForLocation( - objMember->firstSourceLocation().startLine, - objMember->firstSourceLocation().startColumn); - } - } - - if (ref.debugId() == -1) - return; - - if (wordAtCursor == QString("id")) { - query = QString("\"id:") + ref.idString() + doubleQuote; - } else { - using namespace QmlJS::AST; - if ((qmlNode->kind == Node::Kind_IdentifierExpression) || - (qmlNode->kind == Node::Kind_FieldMemberExpression)) { - ExpressionNode *expressionNode = qmlNode->expressionCast(); - tc.setPosition(expressionNode->firstSourceLocation().begin()); - tc.setPosition(expressionNode->lastSourceLocation().end(), - QTextCursor::KeepAnchor); - QString refToLook = tc.selectedText(); - if ((qmlNode->kind == ::Node::Kind_IdentifierExpression) && - (m_clientProxy->objectReferenceForId(refToLook).debugId() - == -1)) { - query = doubleQuote + QString("local: ") + refToLook - + doubleQuote; - foreach (const QmlDebugPropertyReference &property, - ref.properties()) { - if (property.name() == wordAtCursor - && !property.valueTypeName().isEmpty()) { - query = doubleQuote + property.name() - + QLatin1Char(':') + doubleQuote - + QLatin1Char('+') + property.name(); - break; - } - } - } - else - query = doubleQuote + refToLook + QLatin1Char(':') - + doubleQuote + QLatin1Char('+') + refToLook; - } else { - // show properties - foreach (const QmlDebugPropertyReference &property, ref.properties()) { - if (property.name() == wordAtCursor - && !property.valueTypeName().isEmpty()) { - query = doubleQuote + property.name() + QLatin1Char(':') - + doubleQuote + QLatin1Char('+') - + property.name(); - break; - } - } - } - } - - if (!query.isEmpty()) { - m_debugQuery - = m_clientProxy->queryExpressionResult(ref.debugId(), query); - } - } -} - -void InspectorUi::onResult(quint32 queryId, const QVariant &result) -{ - if (m_showObjectQueryId == queryId) { - m_showObjectQueryId = 0; - QmlDebugObjectReference obj - = qvariant_cast<QmlDebugObjectReference>(result); - m_clientProxy->addObjectToTree(obj); - if (m_onCrumblePathClicked) { - m_onCrumblePathClicked = false; - showObject(obj); - } - return; - } - - if (m_updateObjectQueryIds.contains(queryId)) { - m_updateObjectQueryIds.removeOne(queryId); - QmlDebugObjectReference obj - = qvariant_cast<QmlDebugObjectReference>(result); - m_clientProxy->addObjectToTree(obj); - if (m_updateObjectQueryIds.empty()) - showObject(obj); - return; - } - - if (m_debugQuery != queryId) - return; - - m_debugQuery = 0; - QString text = result.toString(); - if (!text.isEmpty()) - QToolTip::showText(QCursor::pos(), text); -} - -bool InspectorUi::isConnected() const -{ - return m_clientProxy; -} - -void InspectorUi::connected(ClientProxy *clientProxy) -{ - if (m_clientProxy) - disconnect(m_clientProxy, SIGNAL(result(quint32,QVariant)), - this, SLOT(onResult(quint32,QVariant))); - m_clientProxy = clientProxy; - if (m_clientProxy) - connect(m_clientProxy, SIGNAL(result(quint32,QVariant)), - SLOT(onResult(quint32,QVariant))); - using namespace QmlDebug::Constants; - //first check for the name of the tools client - if (m_clientProxy->toolsClient()->objectName() == Constants::QML_INSPECTOR) { - m_toolBar->setZoomToolEnabled(false); - } else if (m_clientProxy->engineDebugClient()->objectName() == QML_DEBUGGER - && m_clientProxy->engineDebugClient()->serviceVersion() - >= CURRENT_SUPPORTED_VERSION) { - //fall back for the intermediate case - //REMOVE THIS SOON - m_toolBar->setZoomToolEnabled(false); - } else { - m_toolBar->setZoomToolEnabled(true); - } - QmlJS::Snapshot snapshot = QmlJS::ModelManagerInterface::instance()->snapshot(); - for (QHash<QString, QmlJSLiveTextPreview *>::const_iterator it - = m_textPreviews.constBegin(); - it != m_textPreviews.constEnd(); ++it) { - Document::Ptr doc = snapshot.document(it.key()); - it.value()->resetInitialDoc(doc); - } - - if (Debugger::DebuggerEngine *debuggerEngine - = clientProxy->qmlAdapter()->debuggerEngine()) { - m_projectFinder.setProjectDirectory( - debuggerEngine->startParameters().projectSourceDirectory); - m_projectFinder.setProjectFiles( - debuggerEngine->startParameters().projectSourceFiles); - m_projectFinder.setSysroot(debuggerEngine->startParameters().sysroot); - } - - connectSignals(); - enable(); - resetViews(); - - initializeDocuments(); - - QHashIterator<QString, QmlJSLiveTextPreview *> iter(m_textPreviews); - while (iter.hasNext()) { - iter.next(); - iter.value()->setClientProxy(m_clientProxy); - iter.value()->updateDebugIds(); - } -} - -void InspectorUi::disconnected() -{ - disconnectSignals(); - disable(); - - resetViews(); - - applyChangesToQmlInspectorHelper(false); - - QHashIterator<QString, QmlJSLiveTextPreview *> iter(m_textPreviews); - while (iter.hasNext()) { - iter.next(); - iter.value()->setClientProxy(0); - } - m_clientProxy = 0; - m_propertyInspector->clear(); - m_pendingPreviewDocumentNames.clear(); -} - -void InspectorUi::onRootContext(const QVariant &value) -{ - if (m_crumblePath->dataForLastIndex().toInt() < 0) { - m_clientProxy->fetchRootObjects( - qvariant_cast<QmlDebugContextReference>( - value), true); - } else { - for (int i = 1; i < m_crumblePath->length(); i++) { - m_updateObjectQueryIds - << m_clientProxy->fetchContextObject( - m_crumblePath->dataForIndex(i).toInt()); - } - } -} - -void InspectorUi::objectTreeReady() -{ - if (m_crumblePath->dataForLastIndex().toInt() >= 0) { - selectItems(QList<QmlDebugObjectReference>() << - m_clientProxy->objectReferenceForId( - m_crumblePath->dataForLastIndex().toInt())); - } else { - showRoot(); - } -} - -void InspectorUi::updateEngineList() -{ - QList<QmlDebugEngineReference> engines = m_clientProxy->engines(); - - //#warning update the QML engines combo - - if (engines.isEmpty()) - qWarning("qmldebugger: no engines found!"); - else { - const QmlDebugEngineReference engine = engines.first(); - m_clientProxy->queryEngineContext(engine.debugId()); - } -} - -void InspectorUi::changeSelectedItems( - const QList<QmlDebugObjectReference> &objects) -{ - if (!m_propertyInspector->contentsValid()) - return; - if (m_selectionCallbackExpected) { - m_selectionCallbackExpected = false; - return; - } - m_cursorPositionChangedExternally = true; - - // QmlJSLiveTextPreview doesn't provide valid references, only correct - // debugIds. We need to remap them - QList <QmlDebugObjectReference> realList; - foreach (const QmlDebugObjectReference &obj, objects) { - QmlDebugObjectReference clientRef - = m_clientProxy->objectReferenceForId(obj.debugId()); - realList << clientRef; - } - - m_clientProxy->setSelectedItemsByObjectId(realList); - selectItems(realList); -} - -void InspectorUi::initializeDocuments() -{ - if (!QmlJS::ModelManagerInterface::instance() || !m_clientProxy) - return; - - Core::EditorManager *em = Core::EditorManager::instance(); - m_loadedSnapshot = QmlJS::ModelManagerInterface::instance()->snapshot(); - - if (!m_listeningToEditorManager) { - m_listeningToEditorManager = true; - connect(em, SIGNAL(editorAboutToClose(Core::IEditor*)), - this, SLOT(removePreviewForEditor(Core::IEditor*))); - connect(em, SIGNAL(editorOpened(Core::IEditor*)), - this, SLOT(createPreviewForEditor(Core::IEditor*))); - connect(QmlJS::ModelManagerInterface::instance(), - SIGNAL(documentChangedOnDisk(QmlJS::Document::Ptr)), - this, SLOT(updatePendingPreviewDocuments(QmlJS::Document::Ptr))); - } - - // initial update - foreach (Core::IEditor *editor, em->openedEditors()) { - createPreviewForEditor(editor); - } - - applyChangesToQmlInspectorHelper(true); -} - -void InspectorUi::serverReloaded() -{ - QmlJS::Snapshot snapshot = QmlJS::ModelManagerInterface::instance()->snapshot(); - m_loadedSnapshot = snapshot; - for (QHash<QString, QmlJSLiveTextPreview *>::const_iterator it - = m_textPreviews.constBegin(); - it != m_textPreviews.constEnd(); ++it) { - Document::Ptr doc = snapshot.document(it.key()); - it.value()->resetInitialDoc(doc); - } - m_clientProxy->refreshObjectTree(); -} - - -void InspectorUi::removePreviewForEditor(Core::IEditor *oldEditor) -{ - if (QmlJSLiveTextPreview *preview - = m_textPreviews.value(oldEditor->document()->fileName())) { - preview->unassociateEditor(oldEditor); - } -} - -QmlJSLiveTextPreview *InspectorUi::createPreviewForEditor( - Core::IEditor *newEditor) -{ - QmlJSLiveTextPreview *preview = 0; - - if (m_clientProxy - && m_clientProxy->isConnected() - && newEditor - && newEditor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID - ) - { - QString filename = newEditor->document()->fileName(); - QmlJS::Document::Ptr doc = QmlJS::ModelManagerInterface::instance()->snapshot().document(filename); - if (!doc) { - if (filename.endsWith(".qml")) { - // add to list of docs that we have to update when - // snapshot figures out that there's a new document - m_pendingPreviewDocumentNames.append(filename); - } - return 0; - } - if (!doc->qmlProgram()) - return 0; - - QmlJS::Document::Ptr initdoc = m_loadedSnapshot.document(filename); - if (!initdoc) - initdoc = doc; - - if (m_textPreviews.contains(filename)) { - preview = m_textPreviews.value(filename); - preview->associateEditor(newEditor); - } else { - preview = new QmlJSLiveTextPreview(doc, initdoc, m_clientProxy, - this); - connect(preview, - SIGNAL(selectedItemsChanged(QList<QmlDebugObjectReference>)), - SLOT(changeSelectedItems(QList<QmlDebugObjectReference>))); - connect(preview, SIGNAL(reloadQmlViewerRequested()), - m_clientProxy, SLOT(reloadQmlViewer())); - connect(preview, - SIGNAL(disableLivePreviewRequested()), - SLOT(disableLivePreview())); - - m_textPreviews.insert(newEditor->document()->fileName(), preview); - preview->associateEditor(newEditor); - preview->updateDebugIds(); - } - } - - return preview; -} - -void InspectorUi::resetViews() -{ - m_propertyInspector->clear(); - m_crumblePath->clear(); -} - -void InspectorUi::reloadQmlViewer() -{ - if (m_clientProxy) - m_clientProxy->reloadQmlViewer(); -} - -QmlDebugObjectReference InspectorUi::findParentRecursive( - int goalDebugId, const QList<QmlDebugObjectReference > &objectsToSearch) -{ - if (goalDebugId == -1) - return QmlDebugObjectReference(); - - foreach (const QmlDebugObjectReference &possibleParent, objectsToSearch) { - // Am I a root object? No parent - if ( possibleParent.debugId() == goalDebugId - && possibleParent.parentId() < 0) - return QmlDebugObjectReference(); - - // Is the goal one of my children? - foreach (const QmlDebugObjectReference &child, - possibleParent.children()) - if ( child.debugId() == goalDebugId ) { - m_clientProxy->insertObjectInTreeIfNeeded(child); - return possibleParent; - } - - // no luck? pass this on - QmlDebugObjectReference candidate = findParentRecursive( - goalDebugId, possibleParent.children()); - if (candidate.debugId() != -1) - return candidate; - } - - return QmlDebugObjectReference(); -} - -inline QString displayName(const QmlDebugObjectReference &obj) -{ - // special! state names - if (obj.className() == "State") { - foreach (const QmlDebugPropertyReference &prop, obj.properties()) { - if (prop.name() == "name") - return prop.value().toString(); - } - } - - // has id? - if (!obj.idString().isEmpty()) - return obj.idString(); - - // return the simplified class name then - QString objTypeName = obj.className(); - QString declarativeString("QDeclarative"); - if (objTypeName.startsWith(declarativeString)) { - objTypeName - = objTypeName.mid(declarativeString.length()).section('_',0,0); - } - return QString("<%1>").arg(objTypeName); -} - -void InspectorUi::selectItems( - const QList<QmlDebugObjectReference> &objectReferences) -{ - foreach (const QmlDebugObjectReference &objref, objectReferences) { - int debugId = objref.debugId(); - if (debugId != -1) { - // select only the first valid element of the list - if (!m_clientProxy->isObjectBeingWatched(debugId)) - m_clientProxy->removeAllObjectWatches(); - //Check if the object is complete - if (objref.needsMoreData()) - m_showObjectQueryId = m_clientProxy->fetchContextObject(objref); - else - showObject(objref); - break; - } - } -} - -void InspectorUi::showObject(const QmlDebugObjectReference &obj) -{ - m_clientProxy->addObjectWatch(obj.debugId()); - QList <QmlDebugObjectReference> selectionList; - selectionList << obj; - m_propertyInspector->setCurrentObjects(selectionList); - populateCrumblePath(obj); - gotoObjectReferenceDefinition(obj); - Debugger::QmlAdapter *qmlAdapter = m_clientProxy->qmlAdapter(); - if (qmlAdapter) - qmlAdapter->setCurrentSelectedDebugInfo(obj.debugId(), displayName(obj)); - m_clientProxy->setSelectedItemsByDebugId(QList<int>() << obj.debugId()); -} - -bool InspectorUi::isRoot(const QmlDebugObjectReference &obj) const -{ - foreach (const QmlDebugObjectReference &rootObj, - m_clientProxy->rootObjectReference()) - if (obj.debugId() == rootObj.debugId() && obj.parentId() < 0) - return true; - return false; -} - -void InspectorUi::populateCrumblePath(const QmlDebugObjectReference &objRef) -{ - QStringList crumbleStrings; - QList <int> crumbleData; - - // first find path by climbing the hierarchy - QmlDebugObjectReference ref = objRef; - crumbleData << objRef.debugId(); - crumbleStrings << displayName(objRef); - - while ((!isRoot(ref)) && (ref.debugId()!=-1)) { - ref = findParentRecursive(ref.debugId(), - m_clientProxy->rootObjectReference()); - crumbleData.push_front( ref.debugId() ); - crumbleStrings.push_front( displayName(ref) ); - } - //Prepend Root - crumbleData.push_front(-1); - crumbleStrings.push_front(QLatin1String("/")); - - m_crumblePath->updateContextPath(crumbleStrings, crumbleData); - crumbleStrings.clear(); - crumbleData.clear(); - - // now append the children - foreach (const QmlDebugObjectReference &child, objRef.children()) { - crumbleData.push_back(child.debugId()); - crumbleStrings.push_back( displayName(child) ); - } - - m_crumblePath->addChildren(crumbleStrings, crumbleData); -} - -void InspectorUi::showRoot() -{ - QStringList crumbleStrings; - QList <int> crumbleData; - - crumbleData << -1; - crumbleStrings << QLatin1String("/"); - - m_crumblePath->updateContextPath(crumbleStrings, crumbleData); - crumbleStrings.clear(); - crumbleData.clear(); - - // now append the children - foreach (const QmlDebugObjectReference &child, - m_clientProxy->rootObjectReference()) { - if (child.parentId() != -1) - continue; - crumbleData.push_back(child.debugId()); - crumbleStrings.push_back( displayName(child) ); - } - - m_crumblePath->addChildren(crumbleStrings, crumbleData); - m_propertyInspector->clear(); - Debugger::QmlAdapter *qmlAdapter = m_clientProxy->qmlAdapter(); - if (qmlAdapter) - qmlAdapter->setCurrentSelectedDebugInfo(-1, QLatin1String("/")); -} - -void InspectorUi::selectItems(const QList<int> &objectIds) -{ - QList<QmlDebugObjectReference> objectReferences; - foreach (int objectId, objectIds) - { - QmlDebugObjectReference ref - = m_clientProxy->objectReferenceForId(objectId); - if (ref.debugId() == objectId) - objectReferences.append(ref); - } - if (objectReferences.length() > 0) - selectItems(objectReferences); -} - -void InspectorUi::changePropertyValue(int debugId, const QString &propertyName, - const QString &valueExpression, - bool isLiteral) -{ - QmlDebugObjectReference obj = m_clientProxy->objectReferenceForId(debugId); - m_clientProxy->setBindingForObject(debugId, propertyName, valueExpression, - isLiteral, obj.source().url().toString(), - obj.source().lineNumber()); -} - -void InspectorUi::enable() -{ - m_toolBar->enable(); - m_crumblePath->clear(); - m_propertyInspector->clear(); -} - -void InspectorUi::disable() -{ - m_toolBar->disable(); - m_crumblePath->clear(); - m_propertyInspector->clear(); -} - -QmlDebugObjectReference InspectorUi::objectReferenceForLocation( - const QString &fileName, int cursorPosition) const -{ - Core::EditorManager *editorManager = Core::EditorManager::instance(); - Core::IEditor *editor = editorManager->openEditor(fileName); - TextEditor::ITextEditor *textEditor - = qobject_cast<TextEditor::ITextEditor*>(editor); - - if (textEditor && m_clientProxy - && textEditor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) { - if (cursorPosition == -1) - cursorPosition = textEditor->position(); - TextEditor::BaseTextEditor *baseTextEditor = - static_cast<TextEditor::BaseTextEditor*>(editor); - QPlainTextEdit *editWidget - = qobject_cast<QPlainTextEdit*>(baseTextEditor->widget()); - - QmlJSTools::SemanticInfo semanticInfo = getSemanticInfo(editWidget); - - if (QmlJS::AST::Node *node - = semanticInfo.declaringMemberNoProperties(cursorPosition)) { - if (QmlJS::AST::UiObjectMember *objMember - = node->uiObjectMemberCast()) { - return m_clientProxy->objectReferenceForLocation( - objMember->firstSourceLocation().startLine, - objMember->firstSourceLocation().startColumn); - } - } - } - return QmlDebugObjectReference(); -} - -void InspectorUi::gotoObjectReferenceDefinition( - const QmlDebugObjectReference &obj) -{ - if (m_cursorPositionChangedExternally) { - m_cursorPositionChangedExternally = false; - return; - } - - QmlDebugFileReference source = obj.source(); - - const QString fileName = m_projectFinder.findFile(source.url()); - - Core::EditorManager *editorManager = Core::EditorManager::instance(); - Core::IEditor *currentEditor = editorManager->currentEditor(); - Core::IEditor *editor = editorManager->openEditor(fileName); - TextEditor::ITextEditor *textEditor - = qobject_cast<TextEditor::ITextEditor*>(editor); - - if (currentEditor != editor) - m_selectionCallbackExpected = true; - - if (textEditor) { - QmlDebugObjectReference ref = objectReferenceForLocation(fileName); - if (ref.debugId() != obj.debugId()) { - m_selectionCallbackExpected = true; - editorManager->addCurrentPositionToNavigationHistory(); - textEditor->gotoLine(source.lineNumber()); - textEditor->widget()->setFocus(); - } - } -} - -void InspectorUi::setupDockWidgets() -{ - Debugger::DebuggerMainWindow *mw = Debugger::DebuggerPlugin::mainWindow(); - - m_toolBar->createActions(); - m_toolBar->setObjectName("QmlInspectorToolbar"); - mw->setToolBar(Debugger::QmlLanguage, m_toolBar->widget()); - - m_crumblePath = new ContextCrumblePath; - m_crumblePath->setStyleSheet(QLatin1String("background: #9B9B9B")); - m_crumblePath->setObjectName("QmlContextPath"); - m_crumblePath->setWindowTitle(tr("Context Path")); - connect(m_crumblePath, SIGNAL(elementClicked(QVariant)), - SLOT(crumblePathElementClicked(QVariant))); - - m_propertyInspector = new QmlJSPropertyInspector; - - QWidget *inspectorWidget = new QWidget; - inspectorWidget->setWindowTitle(tr("QML Inspector")); - inspectorWidget->setObjectName(Debugger::Constants::DOCKWIDGET_QML_INSPECTOR); - - QWidget *pathAndFilterWidget = new Utils::StyledBar(); - pathAndFilterWidget->setStyleSheet(QLatin1String("background: #9B9B9B")); - pathAndFilterWidget->setMaximumHeight(m_crumblePath->height()); - - QHBoxLayout *pathAndFilterLayout = new QHBoxLayout(pathAndFilterWidget); - pathAndFilterLayout->setMargin(0); - pathAndFilterLayout->setSpacing(0); - pathAndFilterLayout->addWidget(m_crumblePath); - - QVBoxLayout *wlay = new QVBoxLayout(inspectorWidget); - wlay->setMargin(0); - wlay->setSpacing(0); - inspectorWidget->setLayout(wlay); - wlay->addWidget(pathAndFilterWidget); - wlay->addWidget(m_propertyInspector); - wlay->addWidget(new Core::FindToolBarPlaceHolder(inspectorWidget)); - - QDockWidget *dock - = mw->createDockWidget(Debugger::QmlLanguage, inspectorWidget); - dock->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea); - dock->setTitleBarWidget(new QWidget(dock)); - - mw->addStagedMenuEntries(); - - Aggregation::Aggregate *aggregate = new Aggregation::Aggregate(); - aggregate->add(m_propertyInspector); - aggregate->add(new Find::TreeViewFind(m_propertyInspector)); -} - -void InspectorUi::crumblePathElementClicked(const QVariant &data) -{ - bool ok; - const int debugId = data.toInt(&ok); - if (!ok || debugId == -2) - return; - - if (debugId == -1) - return showRoot(); - - QList<int> debugIds; - debugIds << debugId; - - m_onCrumblePathClicked = true; - selectItems(debugIds); -} - -bool InspectorUi::showExperimentalWarning() -{ - return m_settings->showLivePreviewWarning(); -} - -void InspectorUi::setShowExperimentalWarning(bool value) -{ - m_settings->setShowLivePreviewWarning(value); -} - -InspectorUi *InspectorUi::instance() -{ - return m_instance; -} - -QString InspectorUi::findFileInProject(const QUrl &url) const -{ - return m_projectFinder.findFile(url); -} - -void InspectorUi::setApplyChangesToQmlInspector(bool applyChanges) -{ - emit livePreviewActivated(applyChanges); - applyChangesToQmlInspectorHelper(applyChanges); -} - -void InspectorUi::applyChangesToQmlInspectorHelper(bool applyChanges) -{ - QHashIterator<QString, QmlJSLiveTextPreview *> iter(m_textPreviews); - while (iter.hasNext()) { - iter.next(); - iter.value()->setApplyChangesToQmlInspector(applyChanges); - } -} - -void InspectorUi::updatePendingPreviewDocuments(QmlJS::Document::Ptr doc) -{ - int idx = -1; - idx = m_pendingPreviewDocumentNames.indexOf(doc->fileName()); - - if (idx == -1) - return; - - Core::EditorManager *em = Core::EditorManager::instance(); - QList<Core::IEditor *> editors - = em->editorsForFileName(doc->fileName()); - - if (editors.isEmpty()) - return; - - m_pendingPreviewDocumentNames.removeAt(idx); - - QmlJSLiveTextPreview *preview = createPreviewForEditor(editors.first()); - editors.removeFirst(); - - foreach (Core::IEditor *editor, editors) - preview->associateEditor(editor); -} - -void InspectorUi::disableLivePreview() -{ - setApplyChangesToQmlInspector(false); -} - -void InspectorUi::connectSignals() -{ - connect(m_propertyInspector, - SIGNAL(changePropertyValue(int,QString,QString,bool)), - this, SLOT(changePropertyValue(int,QString,QString,bool))); - - connect(m_clientProxy, - SIGNAL(propertyChanged(int,QByteArray,QVariant)), - m_propertyInspector, - SLOT(propertyValueChanged(int,QByteArray,QVariant))); - - connect(m_clientProxy, - SIGNAL(selectedItemsChanged(QList<QmlDebugObjectReference>)), - this, SLOT(selectItems(QList<QmlDebugObjectReference>))); - connect(m_clientProxy, SIGNAL(enginesChanged()), - this, SLOT(updateEngineList())); - connect(m_clientProxy, SIGNAL(serverReloaded()), - this, SLOT(serverReloaded())); - connect(m_clientProxy, SIGNAL(objectTreeUpdated()), - this, SLOT(objectTreeReady())); - connect(m_clientProxy, SIGNAL(rootContext(QVariant)), - this, SLOT(onRootContext(QVariant))); - connect(m_clientProxy, SIGNAL(connected()), - this, SLOT(enable())); - connect(m_clientProxy, SIGNAL(disconnected()), - this, SLOT(disable())); - - connect(m_clientProxy, SIGNAL(selectToolActivated()), - m_toolBar, SLOT(activateSelectTool())); - connect(m_clientProxy, SIGNAL(zoomToolActivated()), - m_toolBar, SLOT(activateZoomTool())); - connect(m_clientProxy, SIGNAL(designModeBehaviorChanged(bool)), - m_toolBar, SLOT(setDesignModeBehavior(bool))); - connect(m_clientProxy, SIGNAL(showAppOnTopChanged(bool)), - m_toolBar, SLOT(setShowAppOnTop(bool))); - connect(m_clientProxy, SIGNAL(animationSpeedChanged(qreal)), - m_toolBar, SLOT(setAnimationSpeed(qreal))); - connect(m_clientProxy, SIGNAL(animationPausedChanged(bool)), - m_toolBar, SLOT(setAnimationPaused(bool))); - - connect(m_toolBar, SIGNAL(applyChangesFromQmlFileTriggered(bool)), - this, SLOT(setApplyChangesToQmlInspector(bool))); - - connect(m_toolBar, SIGNAL(designModeSelected(bool)), - m_clientProxy, SLOT(setDesignModeBehavior(bool))); - connect(m_toolBar, SIGNAL(reloadSelected()), - m_clientProxy, SLOT(reloadQmlViewer())); - connect(m_toolBar, SIGNAL(animationSpeedChanged(qreal)), - m_clientProxy, SLOT(setAnimationSpeed(qreal))); - connect(m_toolBar, SIGNAL(animationPausedChanged(bool)), - m_clientProxy, SLOT(setAnimationPaused(bool))); - connect(m_toolBar, SIGNAL(zoomToolSelected()), - m_clientProxy, SLOT(changeToZoomTool())); - connect(m_toolBar, SIGNAL(selectToolSelected()), - m_clientProxy, SLOT(changeToSelectTool())); - connect(m_toolBar, SIGNAL(showAppOnTopSelected(bool)), - m_clientProxy, SLOT(showAppOnTop(bool))); -} - -void InspectorUi::disconnectSignals() -{ - m_propertyInspector->disconnect(this); - - m_clientProxy->disconnect(m_propertyInspector); - m_clientProxy->disconnect(this); - m_clientProxy->disconnect(m_toolBar); - - m_toolBar->disconnect(this); - m_toolBar->disconnect(m_clientProxy); - m_toolBar->disconnect(m_propertyInspector); -} diff --git a/src/plugins/qmljsinspector/qmljsinspector.h b/src/plugins/qmljsinspector/qmljsinspector.h deleted file mode 100644 index e7864a0bb8..0000000000 --- a/src/plugins/qmljsinspector/qmljsinspector.h +++ /dev/null @@ -1,192 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** -** GNU Lesser General Public License Usage -** -** 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. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ - -#ifndef QMLJSINSPECTOR_H -#define QMLJSINSPECTOR_H - -#include <coreplugin/editormanager/ieditor.h> -#include <utils/fileinprojectfinder.h> - -#include <qmldebug/baseenginedebugclient.h> - -#include <qmljs/qmljsdocument.h> -#include <qmljs/parser/qmljsastfwd_p.h> - -#include <debugger/debuggerconstants.h> - -#include <QAction> -#include <QObject> - -using namespace QmlDebug; - -namespace ProjectExplorer { -class Project; -class Environment; -} - -namespace TextEditor { -class ITextEditor; -} - -namespace Core { -class IContext; -} - -namespace QmlJS { -class ModelManagerInterface; -} - -namespace QmlJSInspector { -namespace Internal { - -class QmlJsInspectorToolBar; -class QmlJSPropertyInspector; -class ClientProxy; -class InspectorSettings; -class ContextCrumblePath; -class QmlJSLiveTextPreview; - -class InspectorUi : public QObject -{ - Q_OBJECT - -public: - enum DebugMode { - StandaloneMode, - CppProjectWithQmlEngines, - QmlProjectWithCppPlugins - }; - - InspectorUi(QObject *parent = 0); - virtual ~InspectorUi(); - - void saveSettings() const; - void restoreSettings(); - - bool showExperimentalWarning(); - void setShowExperimentalWarning(bool value); - - static InspectorUi *instance(); - - QString findFileInProject(const QUrl &fileUrl) const; - - void setupUi(); - bool isConnected() const; - void connected(ClientProxy *clientProxy); - void disconnected(); - void setDebuggerEngine(QObject *qmlEngine); - -signals: - void statusMessage(const QString &text); - void livePreviewActivated(bool isActivated); - -public slots: - void reloadQmlViewer(); - void serverReloaded(); - void setApplyChangesToQmlInspector(bool applyChanges); - void onResult(quint32 queryId, const QVariant &result); - -private slots: - void enable(); - void disable(); - void gotoObjectReferenceDefinition(const QmlDebugObjectReference &obj); - void selectItems(const QList<QmlDebugObjectReference> &objectReferences); - void selectItems(const QList<int> &objectIds); - void changeSelectedItems(const QList<QmlDebugObjectReference> &objects); - void changePropertyValue(int debugId,const QString &propertyName, - const QString &valueExpression, bool isLiteral); - void objectTreeReady(); - void onRootContext(const QVariant &value); - - void updateEngineList(); - - void removePreviewForEditor(Core::IEditor *newEditor); - QmlJSLiveTextPreview *createPreviewForEditor(Core::IEditor *newEditor); - - void disableLivePreview(); - void crumblePathElementClicked(const QVariant &data); - - void updatePendingPreviewDocuments(QmlJS::Document::Ptr doc); - void showDebuggerTooltip(const QPoint &mousePos, - TextEditor::ITextEditor *editor, int cursorPos); - void onEngineStateChanged(Debugger::DebuggerState state); - -private: - void showRoot(); - void resetViews(); - - void initializeDocuments(); - void applyChangesToQmlInspectorHelper(bool applyChanges); - void setupDockWidgets(); - QString filenameForShadowBuildFile(const QString &filename) const; - void populateCrumblePath(const QmlDebugObjectReference &objRef); - bool isRoot(const QmlDebugObjectReference &obj) const; - QmlDebugObjectReference objectReferenceForLocation( - const QString &fileName, int cursorPosition = -1) const; - - void connectSignals(); - void disconnectSignals(); - - void showObject(const QmlDebugObjectReference &obj); - - QmlDebugObjectReference findParentRecursive( - int goalDebugId, - const QList<QmlDebugObjectReference > &objectsToSearch); -private: - bool m_listeningToEditorManager; - QmlJsInspectorToolBar *m_toolBar; - ContextCrumblePath *m_crumblePath; - QmlJSPropertyInspector *m_propertyInspector; - - InspectorSettings *m_settings; - ClientProxy *m_clientProxy; - quint32 m_debugQuery; - quint32 m_showObjectQueryId; - QList<quint32> m_updateObjectQueryIds; - - // Qml/JS integration - QHash<QString, QmlJSLiveTextPreview *> m_textPreviews; - QmlJS::Snapshot m_loadedSnapshot; //the snapshot loaded by the viewer - - QStringList m_pendingPreviewDocumentNames; - Utils::FileInProjectFinder m_projectFinder; - - static InspectorUi *m_instance; - bool m_selectionCallbackExpected; - bool m_cursorPositionChangedExternally; - bool m_onCrumblePathClicked; -}; - -} // Internal -} // QmlJSInspector - -#endif // QMLJSINSPECTOR_H diff --git a/src/plugins/qmljsinspector/qmljsinspector.pro b/src/plugins/qmljsinspector/qmljsinspector.pro deleted file mode 100644 index d3fdf652d8..0000000000 --- a/src/plugins/qmljsinspector/qmljsinspector.pro +++ /dev/null @@ -1,51 +0,0 @@ -TEMPLATE = lib -TARGET = QmlJSInspector -INCLUDEPATH += . -DEPENDPATH += . -QT += network -greaterThan(QT_MAJOR_VERSION, 4) { - QT += quick1 -} else { - QT += declarative -} - -DEFINES += QMLJSINSPECTOR_LIBRARY - -HEADERS += \ -qmljsinspector_global.h \ -qmljsinspectorconstants.h \ -qmljsinspectorplugin.h \ -qmljsclientproxy.h \ -qmljsinspector.h \ -qmljsinspectortoolbar.h \ -qmljslivetextpreview.h \ -basetoolsclient.h \ -qmljscontextcrumblepath.h \ -qmljsinspectorsettings.h \ -qmljspropertyinspector.h \ -declarativetoolsclient.h \ -qmltoolsclient.h - -SOURCES += \ -qmljsinspectorplugin.cpp \ -qmljsclientproxy.cpp \ -qmljsinspector.cpp \ -qmljsinspectortoolbar.cpp \ -qmljslivetextpreview.cpp \ -basetoolsclient.cpp \ -qmljscontextcrumblepath.cpp \ -qmljsinspectorsettings.cpp \ -qmljspropertyinspector.cpp \ -declarativetoolsclient.cpp \ -qmltoolsclient.cpp - -include(../../../share/qtcreator/qml/qmljsdebugger/protocol/protocol.pri) - -RESOURCES += qmljsinspector.qrc - -include(../../qtcreatorplugin.pri) -include(../../libs/qmldebug/qmldebug.pri) -include(../../libs/qmleditorwidgets/qmleditorwidgets.pri) - -include(../../plugins/debugger/debugger.pri) -include(../../plugins/qmljstools/qmljstools.pri) diff --git a/src/plugins/qmljsinspector/qmljsinspector.qbs b/src/plugins/qmljsinspector/qmljsinspector.qbs deleted file mode 100644 index c83ef3caca..0000000000 --- a/src/plugins/qmljsinspector/qmljsinspector.qbs +++ /dev/null @@ -1,59 +0,0 @@ -import qbs.base 1.0 - -import "../QtcPlugin.qbs" as QtcPlugin - -QtcPlugin { - name: "QmlJSInspector" - - Depends { name: "qt"; submodules: ['widgets', 'quick1'] } - Depends { name: "Core" } - Depends { name: "Debugger" } - Depends { name: "LanguageUtils" } - Depends { name: "TextEditor" } - Depends { name: "QmlJS" } - Depends { name: "QmlJSTools" } - Depends { name: "QmlEditorWidgets" } - Depends { name: "QmlDebug" } - - - Depends { name: "cpp" } - cpp.includePaths: [ - ".", - "../../libs/qmleditorwidgets", - "../../../share/qtcreator/qml/qmljsdebugger/protocol", - "../../shared/symbianutils", - "..", - "../../libs", - buildDirectory - ] - - files: [ - "basetoolsclient.h", - "declarativetoolsclient.h", - "qmljsinspector_global.h", - "qmljsinspectorconstants.h", - "qmljsinspectorplugin.h", - "qmljsclientproxy.h", - "qmljsinspector.h", - "qmljsinspectortoolbar.h", - "qmljslivetextpreview.h", - "qmltoolsclient.h", - "qmljscontextcrumblepath.h", - "qmljsinspectorsettings.h", - "qmljspropertyinspector.h", - "../../../share/qtcreator/qml/qmljsdebugger/protocol/inspectorprotocol.h", - "basetoolsclient.cpp", - "declarativetoolsclient.cpp", - "qmljsinspectorplugin.cpp", - "qmljsclientproxy.cpp", - "qmljsinspector.cpp", - "qmljsinspectortoolbar.cpp", - "qmljslivetextpreview.cpp", - "qmltoolsclient.cpp", - "qmljscontextcrumblepath.cpp", - "qmljsinspectorsettings.cpp", - "qmljspropertyinspector.cpp", - "qmljsinspector.qrc", - ] -} - diff --git a/src/plugins/qmljsinspector/qmljsinspector.qrc b/src/plugins/qmljsinspector/qmljsinspector.qrc deleted file mode 100644 index 51f4e888ab..0000000000 --- a/src/plugins/qmljsinspector/qmljsinspector.qrc +++ /dev/null @@ -1,20 +0,0 @@ -<RCC> - <qresource prefix="/qml"> - <file>images/from-qml.png</file> - <file>images/pause.png</file> - <file>images/reload.png</file> - <file>images/play.png</file> - <file>images/select.png</file> - <file>images/to-qml.png</file> - <file>images/select-marquee.png</file> - <file>images/zoom.png</file> - <file>images/select-small.png</file> - <file>images/play-small.png</file> - <file>images/to-qml-small.png</file> - <file>images/pause-small.png</file> - <file>images/from-qml-small.png</file> - <file>images/zoom-small.png</file> - <file>images/select-marquee-small.png</file> - <file>images/app-on-top.png</file> - </qresource> -</RCC> diff --git a/src/plugins/qmljsinspector/qmljsinspector_global.h b/src/plugins/qmljsinspector/qmljsinspector_global.h deleted file mode 100644 index 897c08f7fd..0000000000 --- a/src/plugins/qmljsinspector/qmljsinspector_global.h +++ /dev/null @@ -1,43 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** -** GNU Lesser General Public License Usage -** -** 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. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ -#ifndef QMLINSPECTOR_GLOBAL_H -#define QMLINSPECTOR_GLOBAL_H - -#include <QtGlobal> - -#if defined(QMLJSINSPECTOR_LIBRARY) -# define QMLINSPECTOR_EXPORT Q_DECL_EXPORT -#else -# define QMLINSPECTOR_EXPORT Q_DECL_IMPORT -#endif - -#endif // QMLINSPECTOR_GLOBAL_H diff --git a/src/plugins/qmljsinspector/qmljsinspectorconstants.h b/src/plugins/qmljsinspector/qmljsinspectorconstants.h deleted file mode 100644 index 906b200e4f..0000000000 --- a/src/plugins/qmljsinspector/qmljsinspectorconstants.h +++ /dev/null @@ -1,69 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** -** GNU Lesser General Public License Usage -** -** 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. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ - -#ifndef QMLJSINSPECTORCONSTANTS_H -#define QMLJSINSPECTORCONSTANTS_H - -namespace QmlJSInspector { -namespace Constants { - -const char INFO_EXPERIMENTAL[] = "QmlInspector.Experimental"; -const char INFO_OUT_OF_SYNC[] = "QmlInspector.OutOfSyncWarning"; - -const char PLAY_ACTION[] = "QmlInspector.Play"; -const char SELECT_ACTION[] = "QmlInspector.Select"; -const char ZOOM_ACTION[] = "QmlInspector.Zoom"; -const char FROM_QML_ACTION[] = "QmlInspector.FromQml"; -const char SHOW_APP_ON_TOP_ACTION[] = "QmlInspector.ShowAppOnTop"; - -// Settings -const char S_QML_INSPECTOR [] = "QML.Inspector"; -const char S_LIVE_PREVIEW_WARNING_KEY[] = "ShowLivePreview"; - -const char ALWAYS_ADJUST_COLUMNS_WIDTHS[] = "AlwaysAdjustColumnWidths"; - -const char QML_INSPECTOR[] = "QmlInspector"; -const char QDECLARATIVE_OBSERVER_MODE[] = "QDeclarativeObserverMode"; - -enum DesignTool { - NoTool = 0, - SelectionToolMode = 1, - MarqueeSelectionToolMode = 2, - MoveToolMode = 3, - ResizeToolMode = 4, - ZoomMode = 6 -}; - -} // namespace Constants -} // namespace QmlJSInspector - -#endif // QMLJSINSPECTORCONSTANTS_H diff --git a/src/plugins/qmljsinspector/qmljsinspectorplugin.cpp b/src/plugins/qmljsinspector/qmljsinspectorplugin.cpp deleted file mode 100644 index 5ffa439440..0000000000 --- a/src/plugins/qmljsinspector/qmljsinspectorplugin.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** -** GNU Lesser General Public License Usage -** -** 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. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ - -#include "qmljsinspectorplugin.h" - -#include "qmljsclientproxy.h" -#include "qmljsinspector.h" -#include "qmljsinspectorconstants.h" -#include "qmljsinspectortoolbar.h" - -#include <coreplugin/coreconstants.h> -#include <coreplugin/icontext.h> -#include <coreplugin/icore.h> -#include <coreplugin/imode.h> -#include <coreplugin/modemanager.h> -#include <debugger/debuggerconstants.h> -#include <debugger/qml/qmladapter.h> -#include <extensionsystem/pluginmanager.h> -#include <utils/qtcassert.h> - -#include <QStringList> -#include <QtPlugin> -#include <QTimer> - -#include <QHBoxLayout> -#include <QToolButton> - -#include <QDebug> - -using namespace QmlJSInspector::Internal; -using namespace QmlJSInspector::Constants; - -InspectorPlugin::InspectorPlugin() - : IPlugin() - , m_clientProxy(0) -{ - m_inspectorUi = new InspectorUi(this); -} - -InspectorPlugin::~InspectorPlugin() -{ -} - -InspectorUi *InspectorPlugin::inspector() const -{ - return m_inspectorUi; -} - -ExtensionSystem::IPlugin::ShutdownFlag InspectorPlugin::aboutToShutdown() -{ - m_inspectorUi->saveSettings(); - return SynchronousShutdown; -} - -bool InspectorPlugin::initialize(const QStringList &arguments, - QString *errorString) -{ - Q_UNUSED(arguments); - Q_UNUSED(errorString); - - return true; -} - -void InspectorPlugin::extensionsInitialized() -{ - ExtensionSystem::PluginManager *pluginManager - = ExtensionSystem::PluginManager::instance(); - - connect(pluginManager, SIGNAL(objectAdded(QObject*)), - SLOT(objectAdded(QObject*))); - connect(Core::ModeManager::instance(), - SIGNAL(currentModeAboutToChange(Core::IMode*)), - this, SLOT(modeAboutToChange(Core::IMode*))); -} - -void InspectorPlugin::objectAdded(QObject *object) -{ - Debugger::QmlAdapter *adapter = qobject_cast<Debugger::QmlAdapter *>(object); - if (adapter) { - //Disconnect inspector plugin when qml adapter emits disconnected - connect(adapter, SIGNAL(disconnected()), this, SLOT(disconnect())); - m_clientProxy = new ClientProxy(adapter); - if (m_clientProxy->isConnected()) { - clientProxyConnected(); - } else { - connect(m_clientProxy, SIGNAL(connected()), - this, SLOT(clientProxyConnected())); - } - return; - } - - if (object->objectName() == QLatin1String("QmlEngine")) - m_inspectorUi->setDebuggerEngine(object); -} - -void InspectorPlugin::disconnect() -{ - if (m_inspectorUi->isConnected()) { - m_inspectorUi->disconnected(); - delete m_clientProxy; - m_clientProxy = 0; - } -} - -void InspectorPlugin::clientProxyConnected() -{ - m_inspectorUi->connected(m_clientProxy); -} - -void InspectorPlugin::modeAboutToChange(Core::IMode *newMode) -{ - QTC_ASSERT(newMode, return); - - if (newMode->id() == Debugger::Constants::MODE_DEBUG) { - m_inspectorUi->setupUi(); - - // Make sure we're not called again. - QObject::disconnect(Core::ModeManager::instance(), - SIGNAL(currentModeAboutToChange(Core::IMode*)), - this, SLOT(modeAboutToChange(Core::IMode*))); - } -} - -Q_EXPORT_PLUGIN(InspectorPlugin) diff --git a/src/plugins/qmljsinspector/qmljsinspectorplugin.h b/src/plugins/qmljsinspector/qmljsinspectorplugin.h deleted file mode 100644 index 5ac4c6267f..0000000000 --- a/src/plugins/qmljsinspector/qmljsinspectorplugin.h +++ /dev/null @@ -1,88 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** -** GNU Lesser General Public License Usage -** -** 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. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ -#ifndef QMLJSINSPECTORPLUGIN_H -#define QMLJSINSPECTORPLUGIN_H - -#include <extensionsystem/iplugin.h> -#include <qmljs/qmljsmodelmanagerinterface.h> - -#include <QObject> -#include <QPointer> -#include <QTimer> - -namespace Core { -class IMode; -} // namespace Core - -namespace QmlJSInspector { -namespace Internal { - -class ClientProxy; -class InspectorUi; - -class InspectorPlugin : public ExtensionSystem::IPlugin -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" - FILE "QmlJSInspector.json") - -public: - InspectorPlugin(); - virtual ~InspectorPlugin(); - - //static InspectorPlugin *instance(); - - InspectorUi *inspector() const; - - // ExtensionSystem::IPlugin interface - virtual bool initialize(const QStringList &arguments, QString *errorString); - virtual void extensionsInitialized(); - virtual ExtensionSystem::IPlugin::ShutdownFlag aboutToShutdown(); - -private slots: - void objectAdded(QObject *object); - void disconnect(); - void clientProxyConnected(); - void modeAboutToChange(Core::IMode *mode); - -private: - void createActions(); - -private: - ClientProxy *m_clientProxy; - InspectorUi *m_inspectorUi; -}; - -} // namespace Internal -} // namespace QmlJSInspector - -#endif // QMLINSPECTORPLUGIN_H diff --git a/src/plugins/qmljsinspector/qmljsinspectorsettings.cpp b/src/plugins/qmljsinspector/qmljsinspectorsettings.cpp deleted file mode 100644 index 68e54a1381..0000000000 --- a/src/plugins/qmljsinspector/qmljsinspectorsettings.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** -** GNU Lesser General Public License Usage -** -** 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. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ - -#include "qmljsinspectorsettings.h" -#include "qmljsinspectorconstants.h" -#include <QSettings> - -namespace QmlJSInspector { -namespace Internal { - -using namespace QmlJSInspector::Constants; - -InspectorSettings::InspectorSettings(QObject *parent) - : QObject(parent), - m_showLivePreviewWarning(true) -{ -} - -void InspectorSettings::restoreSettings(QSettings *settings) -{ - settings->beginGroup(QLatin1String(S_QML_INSPECTOR)); - m_showLivePreviewWarning - = settings->value(QLatin1String(S_LIVE_PREVIEW_WARNING_KEY), - true).toBool(); - settings->endGroup(); -} - -void InspectorSettings::saveSettings(QSettings *settings) const -{ - settings->beginGroup(QLatin1String(S_QML_INSPECTOR)); - settings->setValue(QLatin1String(S_LIVE_PREVIEW_WARNING_KEY), - m_showLivePreviewWarning); - settings->endGroup(); -} - -bool InspectorSettings::showLivePreviewWarning() const -{ - return m_showLivePreviewWarning; -} - -void InspectorSettings::setShowLivePreviewWarning(bool value) -{ - m_showLivePreviewWarning = value; -} - -} // namespace Internal -} // namespace QmlJSInspector diff --git a/src/plugins/qmljsinspector/qmljsinspectorsettings.h b/src/plugins/qmljsinspector/qmljsinspectorsettings.h deleted file mode 100644 index 1eb5ffdec2..0000000000 --- a/src/plugins/qmljsinspector/qmljsinspectorsettings.h +++ /dev/null @@ -1,63 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** -** GNU Lesser General Public License Usage -** -** 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. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ - -#ifndef INSPECTORSETTINGS_H -#define INSPECTORSETTINGS_H - -#include <QObject> - -QT_FORWARD_DECLARE_CLASS(QSettings) - -namespace QmlJSInspector { -namespace Internal { - -class InspectorSettings : public QObject -{ - Q_OBJECT - -public: - InspectorSettings(QObject *parent = 0); - - void restoreSettings(QSettings *settings); - void saveSettings(QSettings *settings) const; - - bool showLivePreviewWarning() const; - void setShowLivePreviewWarning(bool value); - -private: - bool m_showLivePreviewWarning; -}; - -} // namespace Internal -} // namespace QmlJSInspector - -#endif // INSPECTORSETTINGS_H diff --git a/src/plugins/qmljsinspector/qmljsinspectortoolbar.cpp b/src/plugins/qmljsinspector/qmljsinspectortoolbar.cpp deleted file mode 100644 index f365fa17a9..0000000000 --- a/src/plugins/qmljsinspector/qmljsinspectortoolbar.cpp +++ /dev/null @@ -1,373 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** -** GNU Lesser General Public License Usage -** -** 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. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ - -#include "qmljsinspectortoolbar.h" - -#include "qmljsinspectorconstants.h" - -#include <coreplugin/actionmanager/actionmanager.h> -#include <coreplugin/actionmanager/command.h> -#include <coreplugin/id.h> -#include <coreplugin/icore.h> -#include <debugger/debuggerconstants.h> -#include <debugger/debuggermainwindow.h> -#include <debugger/debuggerplugin.h> -#include <extensionsystem/pluginmanager.h> -#include <projectexplorer/projectexplorerconstants.h> - -#include <utils/styledbar.h> -#include <utils/savedaction.h> - -#include <QAction> -#include <QActionGroup> -#include <QHBoxLayout> -#include <QMenu> -#include <QToolButton> -#include <QLineEdit> - -namespace QmlJSInspector { -namespace Internal { - -static QToolButton *toolButton(QAction *action) -{ - QToolButton *button = new QToolButton; - button->setDefaultAction(action); - return button; -} - -QmlJsInspectorToolBar::QmlJsInspectorToolBar(QObject *parent) : - QObject(parent), - m_fromQmlAction(0), - m_playAction(0), - m_selectAction(0), - m_zoomAction(0), - m_showAppOnTopAction(0), - m_playSpeedMenuActions(0), - m_playIcon(QIcon(QLatin1String(":/qml/images/play-small.png"))), - m_pauseIcon(QIcon(QLatin1String(":/qml/images/pause-small.png"))), - m_emitSignals(true), - m_paused(false), - m_animationSpeed(1.0f), - m_designModeActive(false), - m_activeTool(NoTool), - m_barWidget(0), - m_zoomActionEnable(true) -{ -} - -void QmlJsInspectorToolBar::setEnabled(bool value) -{ - m_fromQmlAction->setEnabled(value); - m_showAppOnTopAction->setEnabled(value); - m_playAction->setEnabled(value); - m_selectAction->setEnabled(value); - m_zoomAction->setEnabled(value && m_zoomActionEnable); -} - -void QmlJsInspectorToolBar::enable() -{ - setEnabled(true); - m_emitSignals = false; - setAnimationSpeed(1.0f); - m_designModeActive = false; - updateDesignModeActions(NoTool); - m_emitSignals = true; -} - -void QmlJsInspectorToolBar::disable() -{ - setAnimationSpeed(1.0f); - m_designModeActive = false; - updateDesignModeActions(NoTool); - setEnabled(false); -} - -void QmlJsInspectorToolBar::activateSelectTool() -{ - updateDesignModeActions(SelectionToolMode); -} - -void QmlJsInspectorToolBar::activateZoomTool() -{ - updateDesignModeActions(ZoomMode); -} - -void QmlJsInspectorToolBar::setAnimationSpeed(qreal slowDownFactor) -{ - if (m_animationSpeed == slowDownFactor) - return; - - m_emitSignals = false; - m_animationSpeed = slowDownFactor; - - foreach (QAction *action, m_playSpeedMenuActions->actions()) { - if (action->data().toReal() == slowDownFactor) { - action->setChecked(true); - break; - } - } - - m_emitSignals = true; -} - -void QmlJsInspectorToolBar::setAnimationPaused(bool paused) -{ - if (m_paused == paused) - return; - - m_paused = paused; - updatePlayAction(); -} - -void QmlJsInspectorToolBar::setDesignModeBehavior(bool inDesignMode) -{ - m_emitSignals = false; - m_designModeActive = inDesignMode; - updateDesignModeActions(m_activeTool); - m_emitSignals = true; -} - -void QmlJsInspectorToolBar::setShowAppOnTop(bool showAppOnTop) -{ - m_emitSignals = false; - m_showAppOnTopAction->setChecked(showAppOnTop); - m_emitSignals = true; -} - -void QmlJsInspectorToolBar::setZoomToolEnabled(bool enable) -{ - m_zoomActionEnable = enable; - m_zoomAction->setEnabled(m_zoomActionEnable); -} - -void QmlJsInspectorToolBar::createActions() -{ - using namespace Constants; - - Core::Context context(Debugger::Constants::C_QMLDEBUGGER); - Core::ActionManager *am = Core::ICore::actionManager(); - - m_fromQmlAction = new Utils::SavedAction(this); - m_fromQmlAction->setDefaultValue(false); - m_fromQmlAction->setSettingsKey(QLatin1String(S_QML_INSPECTOR), - QLatin1String(FROM_QML_ACTION)); - m_fromQmlAction->setText(tr("Apply Changes on Save")); - m_fromQmlAction->setCheckable(true); - m_fromQmlAction->setIcon(QIcon(QLatin1String(":/qml/images/from-qml-small.png"))); - - m_showAppOnTopAction = new Utils::SavedAction(this); - m_showAppOnTopAction->setDefaultValue(false); - m_showAppOnTopAction->setSettingsKey(QLatin1String(S_QML_INSPECTOR), - QLatin1String(SHOW_APP_ON_TOP_ACTION)); - m_showAppOnTopAction->setText(tr("Show application on top")); - m_showAppOnTopAction->setCheckable(true); - m_showAppOnTopAction->setIcon(QIcon(QLatin1String(":/qml/images/app-on-top.png"))); - - m_playAction = - new QAction(m_pauseIcon, tr("Play/Pause Animations"), this); - m_selectAction = - new QAction(QIcon(QLatin1String(":/qml/images/select-small.png")), - tr("Select"), this); - m_zoomAction = - new QAction(QIcon(QLatin1String(":/qml/images/zoom-small.png")), - tr("Zoom"), this); - - m_selectAction->setCheckable(true); - m_zoomAction->setCheckable(true); - - Core::Command *command - = am->registerAction(m_playAction, PLAY_ACTION, context); - command->setAttribute(Core::Command::CA_UpdateIcon); - am->registerAction(m_selectAction, SELECT_ACTION, context); - am->registerAction(m_zoomAction, ZOOM_ACTION, context); - am->registerAction(m_fromQmlAction, FROM_QML_ACTION, context); - am->registerAction(m_showAppOnTopAction, SHOW_APP_ON_TOP_ACTION, context); - - m_barWidget = new QWidget; - - QMenu *playSpeedMenu = new QMenu(m_barWidget); - m_playSpeedMenuActions = new QActionGroup(this); - m_playSpeedMenuActions->setExclusive(true); - QAction *speedAction = playSpeedMenu->addAction(tr("1x"), - this, SLOT(changeAnimationSpeed())); - speedAction->setCheckable(true); - speedAction->setChecked(true); - speedAction->setData(1.0f); - m_playSpeedMenuActions->addAction(speedAction); - - speedAction = playSpeedMenu->addAction(tr("0.5x"), - this, SLOT(changeAnimationSpeed())); - speedAction->setCheckable(true); - speedAction->setData(2.0f); - m_playSpeedMenuActions->addAction(speedAction); - - speedAction = playSpeedMenu->addAction(tr("0.25x"), - this, SLOT(changeAnimationSpeed())); - speedAction->setCheckable(true); - speedAction->setData(4.0f); - m_playSpeedMenuActions->addAction(speedAction); - - speedAction = playSpeedMenu->addAction(tr("0.125x"), - this, SLOT(changeAnimationSpeed())); - speedAction->setCheckable(true); - speedAction->setData(8.0f); - m_playSpeedMenuActions->addAction(speedAction); - - speedAction = playSpeedMenu->addAction(tr("0.1x"), - this, SLOT(changeAnimationSpeed())); - speedAction->setCheckable(true); - speedAction->setData(10.0f); - m_playSpeedMenuActions->addAction(speedAction); - - QHBoxLayout *toolBarLayout = new QHBoxLayout(m_barWidget); - toolBarLayout->setMargin(0); - toolBarLayout->setSpacing(0); - - // QML Helpers - toolBarLayout->addWidget(toolButton(am->command(FROM_QML_ACTION)->action())); - toolBarLayout->addWidget( - toolButton(am->command(SHOW_APP_ON_TOP_ACTION)->action())); - m_playButton = toolButton(am->command(PLAY_ACTION)->action()); - m_playButton->setMenu(playSpeedMenu); - toolBarLayout->addWidget(m_playButton); - - // Inspector - toolBarLayout->addWidget(new Utils::StyledSeparator); - toolBarLayout->addWidget(toolButton(am->command(SELECT_ACTION)->action())); - toolBarLayout->addWidget(toolButton(am->command(ZOOM_ACTION)->action())); - toolBarLayout->addWidget(new Utils::StyledSeparator); - - connect(m_fromQmlAction, SIGNAL(triggered()), - SLOT(activateFromQml())); - connect(m_showAppOnTopAction, SIGNAL(triggered()), - SLOT(showAppOnTopClick())); - connect(m_playAction, SIGNAL(triggered()), - SLOT(activatePlayOnClick())); - connect(m_selectAction, SIGNAL(triggered(bool)), - SLOT(selectToolTriggered(bool))); - connect(m_zoomAction, SIGNAL(triggered(bool)), - SLOT(zoomToolTriggered(bool))); - - readSettings(); - connect(Core::ICore::instance(), - SIGNAL(saveSettingsRequested()), SLOT(writeSettings())); -} - -void QmlJsInspectorToolBar::readSettings() -{ - QSettings *settings = Core::ICore::settings(); - m_fromQmlAction->readSettings(settings); - m_showAppOnTopAction->readSettings(settings); -} - -void QmlJsInspectorToolBar::writeSettings() const -{ - QSettings *settings = Core::ICore::settings(); - m_fromQmlAction->writeSettings(settings); - m_showAppOnTopAction->writeSettings(settings); -} - -QWidget *QmlJsInspectorToolBar::widget() const -{ - return m_barWidget; -} - -void QmlJsInspectorToolBar::changeAnimationSpeed() -{ - QAction *action = static_cast<QAction*>(sender()); - - m_animationSpeed = action->data().toReal(); - emit animationSpeedChanged(m_animationSpeed); - - updatePlayAction(); -} - -void QmlJsInspectorToolBar::activatePlayOnClick() -{ - m_paused = !m_paused; - emit animationPausedChanged(m_paused); - updatePlayAction(); -} - -void QmlJsInspectorToolBar::updatePlayAction() -{ - m_playAction->setIcon(m_paused ? m_playIcon : m_pauseIcon); -} - -void QmlJsInspectorToolBar::selectToolTriggered(bool checked) -{ - if (m_designModeActive != checked) { - m_designModeActive = checked; - emit designModeSelected(checked); - } - - if (checked) - emit selectToolSelected(); - updateDesignModeActions(SelectionToolMode); -} - -void QmlJsInspectorToolBar::zoomToolTriggered(bool checked) -{ - if (m_designModeActive != checked) { - m_designModeActive = checked; - emit designModeSelected(checked); - } - - if (checked) - emit zoomToolSelected(); - - updateDesignModeActions(ZoomMode); -} - -void QmlJsInspectorToolBar::showAppOnTopClick() -{ - if (m_emitSignals) - emit showAppOnTopSelected(m_showAppOnTopAction->isChecked()); -} - -void QmlJsInspectorToolBar::activateFromQml() -{ - if (m_emitSignals) - emit applyChangesFromQmlFileTriggered(m_fromQmlAction->isChecked()); -} - -void QmlJsInspectorToolBar::updateDesignModeActions(DesignTool activeTool) -{ - m_activeTool = activeTool; - m_selectAction->setChecked(m_designModeActive - && (m_activeTool == SelectionToolMode)); - m_zoomAction->setChecked(m_designModeActive - && (m_activeTool == ZoomMode)); -} - -} // namespace Internal -} // namespace QmlJSInspector diff --git a/src/plugins/qmljsinspector/qmljsinspectortoolbar.h b/src/plugins/qmljsinspector/qmljsinspectortoolbar.h deleted file mode 100644 index c9bf5061f4..0000000000 --- a/src/plugins/qmljsinspector/qmljsinspectortoolbar.h +++ /dev/null @@ -1,147 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** -** GNU Lesser General Public License Usage -** -** 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. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ - -#ifndef QMLJSINSPECTORTOOLBAR_H -#define QMLJSINSPECTORTOOLBAR_H - -#include <debugger/debuggerconstants.h> - -#include <QObject> -#include <QIcon> - -QT_BEGIN_NAMESPACE -class QAction; -class QActionGroup; -class QToolButton; -QT_END_NAMESPACE - -namespace Utils { -class StyledBar; -class SavedAction; -} - -namespace QmlJSInspector { - -namespace Internal { - -class QmlJsInspectorToolBar : public QObject -{ - Q_OBJECT - -public: - enum DesignTool { - NoTool = 0, - SelectionToolMode = 1, - MarqueeSelectionToolMode = 2, - MoveToolMode = 3, - ResizeToolMode = 4, - ZoomMode = 6 - }; - - explicit QmlJsInspectorToolBar(QObject *parent = 0); - void createActions(); - QWidget *widget() const; - void readSettings(); - void setZoomToolEnabled(bool enable); - -public slots: - void writeSettings() const; - void setEnabled(bool value); - void enable(); - void disable(); - - void activateSelectTool(); - void activateZoomTool(); - - void setAnimationSpeed(qreal slowDownFactor); - void setAnimationPaused(bool paused); - - void setDesignModeBehavior(bool inDesignMode); - void setShowAppOnTop(bool showAppOnTop); - -signals: - void applyChangesFromQmlFileTriggered(bool isChecked); - - void designModeSelected(bool); - void reloadSelected(); - void selectToolSelected(); - void zoomToolSelected(); - - void showAppOnTopSelected(bool isChecked); - - void animationSpeedChanged(qreal slowdownFactor); - void animationPausedChanged(bool paused); - -private slots: - void activatePlayOnClick(); - void selectToolTriggered(bool checked); - void zoomToolTriggered(bool checked); - - void showAppOnTopClick(); - - void changeAnimationSpeed(); - - void activateFromQml(); - - void updatePlayAction(); - -private: - void updateDesignModeActions(DesignTool activeTool); - - Utils::SavedAction *m_fromQmlAction; - QAction *m_playAction; - QAction *m_selectAction; - QAction *m_zoomAction; - - Utils::SavedAction *m_showAppOnTopAction; - - QActionGroup *m_playSpeedMenuActions; - - QToolButton *m_playButton; - QIcon m_playIcon; - QIcon m_pauseIcon; - - bool m_emitSignals; - bool m_paused; - qreal m_animationSpeed; - - bool m_designModeActive; - DesignTool m_activeTool; - - QWidget *m_barWidget; - bool m_zoomActionEnable; -}; - -} // namespace Internal -} // namespace QmlJSInspector - -#endif // QMLJSINSPECTORTOOLBAR_H diff --git a/src/plugins/qmljsinspector/qmljspropertyinspector.cpp b/src/plugins/qmljsinspector/qmljspropertyinspector.cpp deleted file mode 100644 index 5d978da1aa..0000000000 --- a/src/plugins/qmljsinspector/qmljspropertyinspector.cpp +++ /dev/null @@ -1,627 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** -** GNU Lesser General Public License Usage -** -** 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. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ -#include "qmljspropertyinspector.h" -#include "qmljsinspectorconstants.h" - -#include <debugger/debuggerconstants.h> -#include <extensionsystem/pluginmanager.h> -#include <coreplugin/icore.h> - -#include <QHeaderView> -#include <QItemDelegate> -#include <QLineEdit> -#include <QDoubleValidator> -#include <QPainter> - -// expression editor -#include <QContextMenuEvent> -#include <QVBoxLayout> - -// context menu -#include <QAction> -#include <QMenu> - -#include <utils/qtcassert.h> -#include <utils/savedaction.h> - -const int PROPERTY_NAME_COLUMN = 0; -const int PROPERTY_TYPE_COLUMN = 1; -const int PROPERTY_VALUE_COLUMN = 2; - -namespace QmlJSInspector { -namespace Internal { - -// ************************************************************************* -// PropertyEdit -// ************************************************************************* - -class PropertyEditDelegate : public QItemDelegate -{ -public: - explicit PropertyEditDelegate(QObject *parent=0) : QItemDelegate(parent), - m_treeWidget(dynamic_cast<QmlJSPropertyInspector *>(parent)) {} - - QWidget *createEditor(QWidget *parent, - const QStyleOptionViewItem &option, - const QModelIndex &index) const - { - Q_UNUSED(option); - if (index.column() != PROPERTY_VALUE_COLUMN) - return 0; - - switch (m_treeWidget->getTypeFor(index.row())) { - - case QmlJSPropertyInspector::BooleanType: { - // invert the bool, skip editor - int objectId = m_treeWidget->getData(index.row(), - PROPERTY_NAME_COLUMN, - Qt::UserRole).toInt(); - QString propertyName - = m_treeWidget->getData(index.row(), - PROPERTY_NAME_COLUMN, - Qt::DisplayRole).toString(); - bool propertyValue - = m_treeWidget->getData(index.row(), PROPERTY_VALUE_COLUMN, - Qt::DisplayRole).toBool(); - m_treeWidget->propertyValueEdited(objectId, propertyName, - !propertyValue?"true":"false", - true); - return 0; - } - - case QmlJSPropertyInspector::NumberType: { - QLineEdit *editor = new QLineEdit(parent); - editor->setValidator(new QDoubleValidator(editor)); - return editor; - } - - default: { - return new QLineEdit(parent); - } - } - - return 0; - } - - void setEditorData(QWidget *editor, const QModelIndex &index) const - { - QVariant data = m_treeWidget->getData(index.row(), PROPERTY_VALUE_COLUMN, - Qt::DisplayRole); - QLineEdit *lineEdit = static_cast<QLineEdit*>(editor); - lineEdit->setText(data.toString()); - } - - void setModelData(QWidget *editor, QAbstractItemModel *model, - const QModelIndex &index) const - { - Q_UNUSED(model); - - int objectId = m_treeWidget->getData(index.row(), PROPERTY_NAME_COLUMN, - Qt::UserRole).toInt(); - if (objectId == -1) - return; - - QString propertyName = m_treeWidget->getData(index.row(), - PROPERTY_NAME_COLUMN, - Qt::DisplayRole).toString(); - QLineEdit *lineEdit = static_cast<QLineEdit*>(editor); - QString propertyValue = lineEdit->text(); - m_treeWidget->propertyValueEdited(objectId, propertyName, propertyValue, - true); - lineEdit->clearFocus(); - } - - void updateEditorGeometry(QWidget *editor, - const QStyleOptionViewItem &option, - const QModelIndex &index) const - { - Q_UNUSED(index); - QLineEdit *lineEdit = static_cast<QLineEdit*>(editor); - lineEdit->setGeometry(option.rect); - } - -private: - QmlJSPropertyInspector *m_treeWidget; - -}; -// ************************************************************************* -// expressionEdit -// ************************************************************************* - -ExpressionEdit::ExpressionEdit(const QString &title, QDialog *parent) - : QDialog(parent) - , m_buttonBox(new QDialogButtonBox(QDialogButtonBox::Ok - | QDialogButtonBox::Cancel)) - , m_exprInput(new QLineEdit(this)) -{ - setWindowTitle(title); - - QVBoxLayout *vertLayout = new QVBoxLayout; - m_exprInput->setMinimumWidth(550); - connect(m_exprInput,SIGNAL(returnPressed()),this,SLOT(accept())); - vertLayout->addWidget(m_exprInput); - vertLayout->addWidget(m_buttonBox); - setLayout(vertLayout); - - connect(m_buttonBox, SIGNAL(accepted()), this, SLOT(accept())); - connect(m_buttonBox, SIGNAL(rejected()), this, SLOT(reject())); -} - -QString ExpressionEdit::expression() const -{ - return m_exprInput->text(); -} - -void ExpressionEdit::setItemData(int objectId, const QString &propertyName) -{ - m_debugId = objectId; - m_paramName = propertyName; -} - -void ExpressionEdit::accept() -{ - QDialog::accept(); - emit dataChanged(m_debugId, m_paramName, expression()); -} - -// ************************************************************************* -// color chooser -// ************************************************************************* - -inline QString extendedNameFromColor(QColor color) -{ - int alphaValue = color.alpha(); - if (alphaValue < 255) - return QLatin1String("#") - + QString("%1").arg(alphaValue, 2, 16, QChar('0')) - + color.name().right(6) ; - else - return color.name(); -} - -inline QString extendedNameFromColor(QVariant color) { - return extendedNameFromColor(QColor(color.value<QColor>())); -} - -inline QColor colorFromExtendedName(QString name) { - QRegExp validator("#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})"); - if (validator.exactMatch(name)) { - return QColor(validator.cap(2).toInt(0,16), - validator.cap(3).toInt(0,16), - validator.cap(4).toInt(0,16), - validator.cap(1).toInt(0,16)); - } - return QColor(name); -} - -ColorChooserDialog::ColorChooserDialog(const QString &title, QDialog *parent) - : QDialog(parent) -{ - setWindowTitle(title); - - QVBoxLayout *vertLayout = new QVBoxLayout; - m_mainFrame = new QmlEditorWidgets::CustomColorDialog(this); - setLayout(vertLayout); - - setFixedSize(m_mainFrame->size()); - - connect(m_mainFrame,SIGNAL(accepted(QColor)),this,SLOT(acceptColor(QColor))); - connect(m_mainFrame,SIGNAL(rejected()),this,SLOT(reject())); -} - -void ColorChooserDialog::setItemData(int objectId, const QString &propertyName, - const QString &colorName) -{ - m_debugId = objectId; - m_paramName = propertyName; - m_mainFrame->setColor(QColor(colorName)); -} - -void ColorChooserDialog::acceptColor(const QColor &color) -{ - QDialog::accept(); - emit dataChanged(m_debugId, m_paramName, - QChar('\"') + color.name() + QChar('\"')); -} - -// ************************************************************************* -// QmlJSObjectTree -// ************************************************************************* -inline QString cleanPropertyValue(QString propertyValue) -{ - if (propertyValue == QString("<unknown value>")) - return QString(); - if (propertyValue == QString("<unnamed object>")) - return QString(); - return propertyValue; -} - -// ************************************************************************* -// QmlJSPropertyInspectorModel -// ************************************************************************* -QmlJSPropertyInspectorModel::QmlJSPropertyInspectorModel() - : QStandardItemModel() - , m_contentsValid(false) -{ -} - -Qt::ItemFlags QmlJSPropertyInspectorModel::flags(const QModelIndex &index) const -{ - return m_contentsValid ? QStandardItemModel::flags(index) : Qt::ItemFlags(); -} - -QVariant QmlJSPropertyInspectorModel::headerData( - int section, Qt::Orientation orient, int role) const -{ - if (orient == Qt::Horizontal && role == Qt::DisplayRole) { - switch (section) { - case PROPERTY_NAME_COLUMN: return tr("Name"); - case PROPERTY_VALUE_COLUMN: return tr("Value"); - case PROPERTY_TYPE_COLUMN: return tr("Type"); - }; - } - return QStandardItemModel::headerData(section, orient, role); -} - -void QmlJSPropertyInspectorModel::setContentsValid(bool contentsValid) -{ - m_contentsValid = contentsValid; -} - -bool QmlJSPropertyInspectorModel::contentsValid() const -{ - return m_contentsValid; -} - -QmlJSPropertyInspector::QmlJSPropertyInspector(QWidget *parent) - : Utils::BaseTreeView(parent) -{ - setItemDelegateForColumn(PROPERTY_VALUE_COLUMN, - new PropertyEditDelegate(this)); - - setModel(&m_model); - //Add an empty Row to make the headers visible! - addRow(QString(), QString(), QString(), -1, false); - - m_adjustColumnsAction = new Utils::SavedAction(this); - m_adjustColumnsAction->setText(tr("Always Adjust Column Widths to Contents")); - m_adjustColumnsAction->setCheckable(true); - m_adjustColumnsAction->setValue(false); - m_adjustColumnsAction->setDefaultValue(false); - m_adjustColumnsAction->setSettingsKey(QLatin1String(Constants::S_QML_INSPECTOR), - QLatin1String(Constants::ALWAYS_ADJUST_COLUMNS_WIDTHS)); - readSettings(); - connect(Core::ICore::instance(), - SIGNAL(saveSettingsRequested()), SLOT(writeSettings())); - - setAlwaysAdjustColumnsAction(m_adjustColumnsAction); - - QAction *act = qobject_cast<QAction *>( - ExtensionSystem::PluginManager::instance()->getObjectByName( - QLatin1String(Debugger::Constants::USE_ALTERNATING_ROW_COLORS))); - if (act) { - setAlternatingRowColors(act->isChecked()); - connect(act, SIGNAL(toggled(bool)), - SLOT(setAlternatingRowColorsHelper(bool))); - } -} - -void QmlJSPropertyInspector::readSettings() -{ - QSettings *settings = Core::ICore::settings(); - m_adjustColumnsAction->readSettings(settings); -} - -void QmlJSPropertyInspector::writeSettings() const -{ - QSettings *settings = Core::ICore::settings(); - m_adjustColumnsAction->writeSettings(settings); -} - -void QmlJSPropertyInspector::addBaseContextActions(QMenu *menu) -{ - QAction *act = qobject_cast<QAction *>( - ExtensionSystem::PluginManager::instance()->getObjectByName( - QLatin1String(Debugger::Constants::SORT_STRUCT_MEMBERS))); - if (act) - menu->addAction(act); - Utils::BaseTreeView::addBaseContextActions(menu); - - act = qobject_cast<QAction *>( - ExtensionSystem::PluginManager::instance()->getObjectByName( - QLatin1String(Debugger::Constants::SETTINGS_DIALOG))); - if (act) - menu->addAction(act); -} - -void QmlJSPropertyInspector::clear() -{ - m_model.removeRows(0, m_model.rowCount()); - m_currentObjects.clear(); -} - -void QmlJSPropertyInspector::setContentsValid(bool contentsValid) -{ - m_model.setContentsValid(contentsValid); -} - -bool QmlJSPropertyInspector::contentsValid() const -{ - return m_model.contentsValid(); -} - -void QmlJSPropertyInspector::setCurrentObjects( - const QList<QmlDebugObjectReference> &objectList) -{ - if (objectList.isEmpty()) - return; - - clear(); - - foreach (const QmlDebugObjectReference &obj, objectList) { - m_currentObjects << obj.debugId(); - buildPropertyTree(obj); - } -} - -QVariant QmlJSPropertyInspector::getData(int row, int column, int role) const -{ - return m_model.data(m_model.index(row, column), role); -} - -QmlJSPropertyInspector::PropertyType -QmlJSPropertyInspector::getTypeFor(int row) const -{ - return static_cast<QmlJSPropertyInspector::PropertyType>( - m_model.data(m_model.index(row, PROPERTY_TYPE_COLUMN), - Qt::UserRole).toInt()); -} - -void QmlJSPropertyInspector::propertyValueChanged(int debugId, - const QByteArray &propertyName, - const QVariant &propertyValue) -{ - if (m_model.rowCount() == 0) - return; - - QString propertyNameS = QString(propertyName); - for (int i = 0; i < m_model.rowCount(); i++) { - if (m_model.data(m_model.index(i, PROPERTY_NAME_COLUMN), - Qt::DisplayRole).toString() == propertyNameS && - m_model.data(m_model.index(i, PROPERTY_NAME_COLUMN), - Qt::UserRole).toInt() == debugId) { - QString oldData = m_model.data(m_model.index(i, PROPERTY_VALUE_COLUMN), - Qt::DisplayRole).toString(); - QString newData = propertyValue.toString(); - if (QString(propertyValue.typeName()) == "QColor") - newData = extendedNameFromColor(propertyValue); - if (oldData != newData) { - m_model.setData(m_model.index(i, PROPERTY_VALUE_COLUMN), newData, - Qt::DisplayRole); - m_model.item(i, PROPERTY_VALUE_COLUMN)->setToolTip(newData); - m_model.item(i, PROPERTY_NAME_COLUMN)->setForeground(QBrush(Qt::red)); - m_model.item(i, PROPERTY_VALUE_COLUMN)->setForeground(QBrush(Qt::red)); - m_model.item(i, PROPERTY_TYPE_COLUMN)->setForeground(QBrush(Qt::red)); - if (getTypeFor(i) == QmlJSPropertyInspector::ColorType) - setColorIcon(i); - } - break; - } - } -} - -void QmlJSPropertyInspector::propertyValueEdited(const int objectId, - const QString &propertyName, - const QString &propertyValue, - bool isLiteral) -{ - emit changePropertyValue(objectId, propertyName, propertyValue, isLiteral); -} - -void QmlJSPropertyInspector::buildPropertyTree(const QmlDebugObjectReference &obj) -{ - // Strip off the misleading metadata - QString objTypeName = obj.className(); - QString declarativeString("QDeclarative"); - if (objTypeName.startsWith(declarativeString)) { - objTypeName = objTypeName.mid(declarativeString.length()).section('_', - 0, 0); - } - - // class - addRow(QString("class"), - objTypeName, - QString("qmlType"), - obj.debugId(), - false); - - // id - if (!obj.idString().isEmpty()) { - addRow(QString("id"), - obj.idString(), - QString("idString"), - obj.debugId(), - false); - } - - foreach (const QmlDebugPropertyReference &prop, obj.properties()) { - QString propertyName = prop.name(); - QString propertyValue = prop.value().toString(); - - if (cleanPropertyValue(propertyValue).isEmpty()) - continue; - - if (prop.valueTypeName() == "QColor") { - propertyValue = extendedNameFromColor(prop.value()); - } - - addRow(propertyName, propertyValue, prop.valueTypeName(), obj.debugId(), - prop.hasNotifySignal()); - } - - m_model.setHeaderData(PROPERTY_NAME_COLUMN, Qt::Horizontal,QVariant("name")); - m_model.setHeaderData(PROPERTY_VALUE_COLUMN, Qt::Horizontal,QVariant("value")); - m_model.setHeaderData(PROPERTY_TYPE_COLUMN, Qt::Horizontal,QVariant("type")); - - QAction *act = qobject_cast<QAction *>( - ExtensionSystem::PluginManager::instance()->getObjectByName( - QLatin1String(Debugger::Constants::SORT_STRUCT_MEMBERS))); - if (act && act->isChecked()) - m_model.sort(PROPERTY_NAME_COLUMN); -} - -void QmlJSPropertyInspector::addRow(const QString &name,const QString &value, - const QString &type, const int debugId, - bool editable) -{ - QStandardItem *nameColumn = new QStandardItem(name); - nameColumn->setToolTip(name); - nameColumn->setData(QVariant(debugId),Qt::UserRole); - nameColumn->setEditable(false); - - QStandardItem *valueColumn = new QStandardItem(value); - valueColumn->setToolTip(value); - valueColumn->setEditable(editable); - valueColumn->setData(QVariant(editable),Qt::UserRole+1); - - QStandardItem *typeColumn = new QStandardItem(type); - typeColumn->setToolTip(type); - typeColumn->setEditable(false); - - // encode type for easy lookup - QmlJSPropertyInspector::PropertyType typeCode - = QmlJSPropertyInspector::OtherType; - if (type == "bool") - typeCode = QmlJSPropertyInspector::BooleanType; - else if (type == "qreal") - typeCode = QmlJSPropertyInspector::NumberType; - else if (type == "QString") - typeCode = QmlJSPropertyInspector::StringType; - else if (type == "QColor") - typeCode = QmlJSPropertyInspector::ColorType; - - typeColumn->setData(typeCode, Qt::UserRole); - - QList<QStandardItem *> newRow; - newRow << nameColumn << typeColumn << valueColumn; - m_model.appendRow(newRow); - - if (typeCode == QmlJSPropertyInspector::ColorType) - setColorIcon(m_model.indexFromItem(valueColumn).row()); -} - -void QmlJSPropertyInspector::setColorIcon(int row) -{ - QStandardItem *item = m_model.item(row, PROPERTY_VALUE_COLUMN); - QColor color = colorFromExtendedName(item->data(Qt::DisplayRole).toString()); - - int recomendedLength = viewOptions().decorationSize.height() - 2; - - QPixmap colorpix(recomendedLength, recomendedLength); - QPainter p(&colorpix); - if (color.alpha() != 255) - p.fillRect(1,1, recomendedLength -2, recomendedLength - 2, Qt::white); - p.fillRect(1, 1, recomendedLength - 2, recomendedLength - 2, color); - p.setPen(Qt::black); - p.drawRect(0, 0, recomendedLength - 1, recomendedLength - 1); - item->setIcon(colorpix); -} - -void QmlJSPropertyInspector::contextMenuEvent(QContextMenuEvent *ev) -{ - QMenu menu; - QModelIndex itemIndex = indexAt(ev->pos()); - bool isEditable = false; - bool isColor = false; - if (itemIndex.isValid()) { - isEditable = m_model.item(itemIndex.row(), PROPERTY_VALUE_COLUMN)->isEditable(); - isColor = (getTypeFor(itemIndex.row()) == QmlJSPropertyInspector::ColorType); - } - - QAction exprAction(tr("Enter expression"), this); - if (isEditable) - menu.addAction(&exprAction); - - QAction colorAction(tr("Choose color"), this); - if (isColor) - menu.addAction(&colorAction); - addBaseContextActions(&menu); - - QAction *action = menu.exec(ev->globalPos()); - if (action == 0) - return; - - if (action == &exprAction) - openExpressionEditor(itemIndex); - if (action == &colorAction) - openColorSelector(itemIndex); - handleBaseContextAction(action); -} - -void QmlJSPropertyInspector::openExpressionEditor(const QModelIndex &itemIndex) -{ - const QString propertyName = getData(itemIndex.row(), PROPERTY_NAME_COLUMN, - Qt::DisplayRole).toString(); - const QString dialogText = tr("JavaScript expression for %1").arg(propertyName); - const int objectId = getData(itemIndex.row(), PROPERTY_NAME_COLUMN, - Qt::UserRole).toInt(); - - ExpressionEdit *expressionDialog = new ExpressionEdit(dialogText); - expressionDialog->setItemData(objectId, propertyName); - - connect(expressionDialog, SIGNAL(dataChanged(int,QString,QString)), - this, SLOT(propertyValueEdited(int,QString,QString))); - - expressionDialog->show(); -} - -void QmlJSPropertyInspector::openColorSelector(const QModelIndex &itemIndex) -{ - const QString propertyName = getData(itemIndex.row(), PROPERTY_NAME_COLUMN, - Qt::DisplayRole).toString(); - const QString dialogText = tr("Color selection for %1").arg(propertyName); - const int objectId = getData(itemIndex.row(), PROPERTY_NAME_COLUMN, - Qt::UserRole).toInt(); - const QString propertyValue = getData(itemIndex.row(), PROPERTY_VALUE_COLUMN, - Qt::DisplayRole).toString(); - - ColorChooserDialog *colorDialog = new ColorChooserDialog(dialogText); - colorDialog->setItemData(objectId, propertyName, propertyValue); - - connect(colorDialog, SIGNAL(dataChanged(int,QString,QString)), - this, SLOT(propertyValueEdited(int,QString,QString))); - - colorDialog->show(); -} - -} // Internal -} // QmlJSInspector diff --git a/src/plugins/qmljsinspector/qmljspropertyinspector.h b/src/plugins/qmljsinspector/qmljspropertyinspector.h deleted file mode 100644 index 64366d2f91..0000000000 --- a/src/plugins/qmljsinspector/qmljspropertyinspector.h +++ /dev/null @@ -1,172 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** -** GNU Lesser General Public License Usage -** -** 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. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ -#ifndef PROPERTYINSPECTOR_H -#define PROPERTYINSPECTOR_H - -#include <qmldebug/baseenginedebugclient.h> -#include <utils/basetreeview.h> -#include <QStandardItemModel> - -#include <QDialog> -#include <QDialogButtonBox> - -#include "customcolordialog.h" - -using namespace QmlDebug; - -namespace Utils { -class SavedAction; -} - -namespace QmlJSInspector { -namespace Internal { - -class PropertyEditDelegate; - -class ExpressionEdit : public QDialog -{ - Q_OBJECT -public: - explicit ExpressionEdit(const QString &title, QDialog *parent = 0); - - QString expression() const; - void setItemData(int objectId, const QString &propertyName); - - virtual void accept(); - -signals: - void dataChanged(int debugId, const QString ¶mName, - const QString &newExpression); - -private: - QDialogButtonBox *m_buttonBox; - QLineEdit *m_exprInput; - int m_debugId; - QString m_paramName; -}; - -class ColorChooserDialog : public QDialog -{ - Q_OBJECT -public: - explicit ColorChooserDialog(const QString &title, QDialog *parent = 0); - - void setItemData(int objectId,const QString &propertyName, - const QString &colorName); - -public slots: - void acceptColor(const QColor &color); - -signals: - void dataChanged(int debugId, const QString ¶mName, - const QString &newExpression); - - -private: - int m_debugId; - QString m_paramName; - QmlEditorWidgets::CustomColorDialog *m_mainFrame; -}; - -class QmlJSPropertyInspectorModel : public QStandardItemModel -{ - Q_OBJECT -public: - QmlJSPropertyInspectorModel(); - void setContentsValid(bool contentsValid); - bool contentsValid() const; - -protected: - Qt::ItemFlags flags(const QModelIndex &index) const; - QVariant headerData(int section, Qt::Orientation orientation, int role) const; - -private: - bool m_contentsValid; -}; - -class QmlJSPropertyInspector : public Utils::BaseTreeView -{ - Q_OBJECT -public: - enum PropertyType - { - BooleanType, - NumberType, - StringType, - ColorType, - OtherType - }; - - explicit QmlJSPropertyInspector(QWidget *parent = 0); - void readSettings(); - void addBaseContextActions(QMenu *menu); - void clear(); - void setContentsValid(bool contentsValid); - bool contentsValid() const; - -signals: - void changePropertyValue(int debugId, QString propertyName, - QString valueExpression, bool isLiteral); - void customContextMenuRequested(const QPoint &pos); - -public slots: - void writeSettings() const; - void setCurrentObjects(const QList<QmlDebugObjectReference> &); - void propertyValueEdited(const int objectId,const QString &propertyName, - const QString &propertyValue, bool isLiteral = false); - void propertyValueChanged(int debugId, const QByteArray &propertyName, - const QVariant &propertyValue); - - void openExpressionEditor(const QModelIndex &itemIndex); - void openColorSelector(const QModelIndex &itemIndex); - -private: - friend class PropertyEditDelegate; - void buildPropertyTree(const QmlDebugObjectReference &); - void addRow(const QString &name, const QString &value, const QString &type, - const int debugId = -1, bool editable = true); - void setColorIcon(int row); - - QVariant getData(int row, int column, int role) const; - QmlJSPropertyInspector::PropertyType getTypeFor(int row) const; - - void contextMenuEvent(QContextMenuEvent *ev); - - QmlJSPropertyInspectorModel m_model; - QList<int> m_currentObjects; - Utils::SavedAction *m_adjustColumnsAction; -}; - -} // Internal -} // QmlJSInspector - -#endif diff --git a/src/plugins/qmljsinspector/qmltoolsclient.cpp b/src/plugins/qmljsinspector/qmltoolsclient.cpp deleted file mode 100644 index 5e0e6ef12e..0000000000 --- a/src/plugins/qmljsinspector/qmltoolsclient.cpp +++ /dev/null @@ -1,332 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** GNU Lesser General Public License Usage -** -** 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. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ - -#include "qmltoolsclient.h" -#include "qmljsclientproxy.h" -#include "qmljsinspectorconstants.h" - -//INSPECTOR SERVICE PROTOCOL -// <HEADER><COMMAND><DATA> -// <HEADER> : <type{request, response, event}><requestId/eventId>[<response_success_bool>] -// <COMMAND> : {"enable", "disable", "select", "setAnimationSpeed", -// "showAppOnTop", "createObject", "destroyObject", "moveObject", -// "clearCache"} -// <DATA> : select: <debugIds_int_list> -// setAnimationSpeed: <speed_real> -// showAppOnTop: <set_bool> -// createObject: <qml_string><parentId_int><imports_string_list><filename_string> -// destroyObject: <debugId_int> -// moveObject: <debugId_int><newParentId_int> -// clearCache: void - -const char REQUEST[] = "request"; -const char RESPONSE[] = "response"; -const char EVENT[] = "event"; -const char ENABLE[] = "enable"; -const char DISABLE[] = "disable"; -const char SELECT[] = "select"; -const char RELOAD[] = "reload"; -const char SET_ANIMATION_SPEED[] = "setAnimationSpeed"; -const char SHOW_APP_ON_TOP[] = "showAppOnTop"; -const char CREATE_OBJECT[] = "createObject"; -const char DESTROY_OBJECT[] = "destroyObject"; -const char MOVE_OBJECT[] = "moveObject"; -const char CLEAR_CACHE[] = "clearCache"; - -namespace QmlJSInspector { -namespace Internal { - -QmlToolsClient::QmlToolsClient(QmlDebugConnection *client) - : BaseToolsClient(client, QLatin1String(Constants::QML_INSPECTOR)), - m_connection(client), - m_requestId(0), - m_slowDownFactor(1) -{ - setObjectName(name()); -} - -void QmlToolsClient::messageReceived(const QByteArray &message) -{ - QDataStream ds(message); - - QByteArray type; - int requestId; - ds >> type >> requestId; - - if (type == QByteArray(RESPONSE)) { - bool success = false; - ds >> success; - log(LogReceive, type, QString(QLatin1String("requestId: %1 success: %2")) - .arg(QString::number(requestId)).arg(QString::number(success))); - } else if (type == QByteArray(EVENT)) { - QByteArray event; - ds >> event; - if (event == QByteArray(SELECT)) { - m_currentDebugIds.clear(); - QList<int> debugIds; - ds >> debugIds; - log(LogReceive, type + ':' + event, - QString("%1 [list of debug ids]").arg(debugIds.count())); - foreach (int debugId, debugIds) { - if (debugId != -1) - m_currentDebugIds << debugId; - } - emit currentObjectsChanged(m_currentDebugIds); - } - } else { - log(LogReceive, type, QLatin1String("Warning: Not handling message")); - } -} - -QList<int> QmlToolsClient::currentObjects() const -{ - return m_currentDebugIds; -} - -void QmlToolsClient::setCurrentObjects(const QList<int> &debugIds) -{ - if (!m_connection || !m_connection->isConnected()) - return; - - if (debugIds == m_currentDebugIds) - return; - - m_currentDebugIds = debugIds; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray(REQUEST) << m_requestId++ - << QByteArray(SELECT) << m_currentDebugIds; - - log(LogSend, SELECT, QString("%1 [list of ids]").arg(debugIds.length())); - - sendMessage(message); -} - -void QmlToolsClient::setObjectIdList( - const QList<QmlDebugObjectReference> &/*objectRoots*/) -{ - //NOT IMPLEMENTED -} - -void QmlToolsClient::clearComponentCache() -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray(REQUEST) << m_requestId++ - << QByteArray(CLEAR_CACHE); - - log(LogSend, CLEAR_CACHE); - - sendMessage(message); -} - -void QmlToolsClient::reloadViewer() -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray(REQUEST) << m_requestId++ - << QByteArray(RELOAD); - - log(LogSend, RELOAD); - - sendMessage(message); -} - -void QmlToolsClient::setDesignModeBehavior(bool inDesignMode) -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray(REQUEST) << m_requestId++; - if (inDesignMode) - ds << QByteArray(ENABLE); - else - ds << QByteArray(DISABLE); - - log(LogSend, ENABLE, QLatin1String(inDesignMode ? "true" : "false")); - - sendMessage(message); -} - -void QmlToolsClient::setAnimationSpeed(qreal slowDownFactor) -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray(REQUEST) << m_requestId++ - << QByteArray(SET_ANIMATION_SPEED) << slowDownFactor; - - log(LogSend, SET_ANIMATION_SPEED, QString::number(slowDownFactor)); - - sendMessage(message); - //Cache non-zero values - if (slowDownFactor) - m_slowDownFactor = slowDownFactor; -} - -void QmlToolsClient::setAnimationPaused(bool paused) -{ - if (paused) - setAnimationSpeed(0); - else - setAnimationSpeed(m_slowDownFactor); -} - -void QmlToolsClient::changeToSelectTool() -{ -// NOT IMPLEMENTED -} - -void QmlToolsClient::changeToSelectMarqueeTool() -{ -// NOT IMPLEMENTED -} - -void QmlToolsClient::changeToZoomTool() -{ -// NOT IMPLEMENTED -} - -void QmlToolsClient::showAppOnTop(bool showOnTop) -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray(REQUEST) << m_requestId++ - << QByteArray(SHOW_APP_ON_TOP) << showOnTop; - - log(LogSend, SHOW_APP_ON_TOP, QLatin1String(showOnTop ? "true" : "false")); - - sendMessage(message); -} - -void QmlToolsClient::createQmlObject(const QString &qmlText, - int parentDebugId, - const QStringList &imports, - const QString &filename, int order) -{ - if (!m_connection || !m_connection->isConnected()) - return; - - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray(REQUEST) << m_requestId++ - << QByteArray(CREATE_OBJECT) - << qmlText - << parentDebugId - << imports - << filename - << order; - - log(LogSend, CREATE_OBJECT, QString("%1 %2 [%3] %4").arg(qmlText, - QString::number(parentDebugId), - imports.join(","), filename)); - - sendMessage(message); -} - -void QmlToolsClient::destroyQmlObject(int debugId) -{ - if (!m_connection || !m_connection->isConnected()) - return; - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray(REQUEST) << m_requestId++ - << QByteArray(DESTROY_OBJECT) << debugId; - - log(LogSend, DESTROY_OBJECT, QString::number(debugId)); - - sendMessage(message); -} - -void QmlToolsClient::reparentQmlObject(int debugId, int newParent) -{ - if (!m_connection || !m_connection->isConnected()) - return; - QByteArray message; - QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray(REQUEST) << m_requestId++ - << QByteArray(MOVE_OBJECT) << debugId << newParent; - - log(LogSend, MOVE_OBJECT, QString("%1 %2").arg(QString::number(debugId), - QString::number(newParent))); - - sendMessage(message); -} - - -void QmlToolsClient::applyChangesToQmlFile() -{ - if (!m_connection || !m_connection->isConnected()) - return; - - // TODO -} - -void QmlToolsClient::applyChangesFromQmlFile() -{ - if (!m_connection || !m_connection->isConnected()) - return; - - // TODO -} - -void QmlToolsClient::log(LogDirection direction, - const QByteArray &message, - const QString &extra) -{ - QString msg; - if (direction == LogSend) - msg += QLatin1String(" sending "); - else - msg += QLatin1String(" receiving "); - - msg += message; - msg += QLatin1Char(' '); - msg += extra; - emit logActivity(name(), msg); -} - -} // namespace Internal -} // namespace QmlJSInspector diff --git a/src/plugins/qmljsinspector/qmltoolsclient.h b/src/plugins/qmljsinspector/qmltoolsclient.h deleted file mode 100644 index 776bb788d9..0000000000 --- a/src/plugins/qmljsinspector/qmltoolsclient.h +++ /dev/null @@ -1,89 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** GNU Lesser General Public License Usage -** -** 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. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -**************************************************************************/ - -#ifndef QMLTOOLSCLIENT_H -#define QMLTOOLSCLIENT_H - -#include "basetoolsclient.h" -namespace QmlJSInspector { -namespace Internal { - -class QmlToolsClient : public BaseToolsClient -{ - Q_OBJECT -public: - explicit QmlToolsClient(QmlDebug::QmlDebugConnection *client); - - void setCurrentObjects(const QList<int> &debugIds); - void reloadViewer(); - void setDesignModeBehavior(bool inDesignMode); - void setAnimationSpeed(qreal slowDownFactor); - void setAnimationPaused(bool paused); - void changeToSelectTool(); - void changeToSelectMarqueeTool(); - void changeToZoomTool(); - void showAppOnTop(bool showOnTop); - - void createQmlObject(const QString &qmlText, int parentDebugId, - const QStringList &imports, const QString &filename, - int order); - void destroyQmlObject(int debugId); - void reparentQmlObject(int debugId, int newParent); - - void applyChangesToQmlFile(); - void applyChangesFromQmlFile(); - - QList<int> currentObjects() const; - - // ### Qt 4.8: remove if we can have access to qdeclarativecontextdata or id's - void setObjectIdList(const QList<QmlDebug::QmlDebugObjectReference> &objectRoots); - - void clearComponentCache(); - -protected: - void messageReceived(const QByteArray &); - -private: - void log(LogDirection direction, - const QByteArray &message, - const QString &extra = QString()); - -private: - QList<int> m_currentDebugIds; - QmlDebug::QmlDebugConnection *m_connection; - int m_requestId; - qreal m_slowDownFactor; -}; - -} // namespace Internal -} // namespace QmlJSInspector - -#endif // QMLTOOLSCLIENT_H |