diff --git a/src/plugins/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp index 536deb0bf7a8c45e80c8434c95bdaff9e6a076f1..8104601d0dbceef1ff356daa8d1ff04c4860b74c 100644 --- a/src/plugins/qmljseditor/qmljseditor.cpp +++ b/src/plugins/qmljseditor/qmljseditor.cpp @@ -845,6 +845,94 @@ void QmlJSTextEditor::updateUsesNow() } setExtraSelections(CodeSemanticsSelection, selections); + + setSelectedElement(); +} + +class SelectedElement: protected Visitor +{ + unsigned cursorPosition; + UiObjectMember *selectedMember; + +public: + SelectedElement() + : cursorPosition(0), selectedMember(0) {} + + UiObjectMember *operator()(Node *root, unsigned position) + { + cursorPosition = position; + selectedMember = 0; + Node::accept(root, this); + return selectedMember; + } + +protected: + UiObjectInitializer *initializer(UiObjectMember *member) const + { + if (UiObjectDefinition *def = cast<UiObjectDefinition *>(member)) + return def->initializer; + else if (UiObjectBinding *binding = cast<UiObjectBinding *>(member)) + return binding->initializer; + return 0; + } + + bool isIdBinding(UiObjectMember *member) const + { + if (UiScriptBinding *script = cast<UiScriptBinding *>(member)) { + if (! script->qualifiedId) + return false; + else if (! script->qualifiedId->name) + return false; + else if (script->qualifiedId->next) + return false; + + const QString propertyName = script->qualifiedId->name->asString(); + + if (propertyName == QLatin1String("id")) + return true; + } + + return false; + } + + virtual void postVisit(Node *ast) + { + if (selectedMember) + return; // nothing to do, we already have the result. + + if (UiObjectMember *member = ast->uiObjectMemberCast()) { + unsigned begin = member->firstSourceLocation().begin(); + unsigned end = member->lastSourceLocation().end(); + + if (cursorPosition >= begin && cursorPosition <= end) { + if (UiObjectInitializer *init = initializer(member)) { + for (UiObjectMemberList *it = init->members; it; it = it->next) { + if (isIdBinding(it->member)) { + selectedMember = member; + break; + } + } + } + } + } + } +}; + +void QmlJSTextEditor::setSelectedElement() +{ + QTextCursor tc = textCursor(); + tc.movePosition(QTextCursor::StartOfWord); + tc.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); + QString wordAtCursor = tc.selectedText(); + + int offset = -1; + if (Document::Ptr doc = m_semanticInfo.document) { + SelectedElement selectedMember; + if (UiObjectMember *m = selectedMember(doc->qmlProgram(), textCursor().position())) { + offset = m->firstSourceLocation().begin(); + } + } + emit selectedElementChanged(offset, wordAtCursor); } void QmlJSTextEditor::updateMethodBoxToolTip() diff --git a/src/plugins/qmljseditor/qmljseditor.h b/src/plugins/qmljseditor/qmljseditor.h index 6d561053ce020e22a7511fd9223b105da0fc7d1d..fd1309971646e5030b9bdab52592acb5720f152e 100644 --- a/src/plugins/qmljseditor/qmljseditor.h +++ b/src/plugins/qmljseditor/qmljseditor.h @@ -30,6 +30,8 @@ #ifndef QMLJSEDITOR_H #define QMLJSEDITOR_H +#include "qmljseditor_global.h" + #include <qmljs/qmljsdocument.h> #include <qmljs/qmljsscanner.h> #include <texteditor/basetexteditor.h> @@ -199,7 +201,7 @@ private: QmlJS::ModelManagerInterface *m_modelManager; }; -class QmlJSTextEditor : public TextEditor::BaseTextEditor +class QMLJSEDITOR_EXPORT QmlJSTextEditor : public TextEditor::BaseTextEditor { Q_OBJECT @@ -213,6 +215,9 @@ public: int documentRevision() const; bool isOutdated() const; +signals: + void selectedElementChanged(int offset, const QString &wordAtCursor); + public slots: void followSymbolUnderCursor(); virtual void setFontSettings(const TextEditor::FontSettings &); @@ -256,6 +261,7 @@ private: virtual void indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar); bool isClosingBrace(const QList<QmlJS::Token> &tokens) const; + void setSelectedElement(); QString wordUnderCursor() const; SemanticHighlighter::Source currentSource(bool force = false); diff --git a/src/plugins/qmljsinspector/images/color-picker.png b/src/plugins/qmljsinspector/images/color-picker.png new file mode 100644 index 0000000000000000000000000000000000000000..73d9ae3dfc40995337e3a0762831fa908e390120 Binary files /dev/null and b/src/plugins/qmljsinspector/images/color-picker.png differ diff --git a/src/plugins/qmljsinspector/images/from-qml.png b/src/plugins/qmljsinspector/images/from-qml.png new file mode 100644 index 0000000000000000000000000000000000000000..e3a6e24c1994c04a9a15513af6f94fd6ee159ee2 Binary files /dev/null and b/src/plugins/qmljsinspector/images/from-qml.png differ diff --git a/src/plugins/qmljsinspector/images/logo.png b/src/plugins/qmljsinspector/images/logo.png deleted file mode 100644 index 5ac14a5a81cea8a3482acf218b71df807bc11a26..0000000000000000000000000000000000000000 Binary files a/src/plugins/qmljsinspector/images/logo.png and /dev/null differ diff --git a/src/plugins/qmljsinspector/images/pause.png b/src/plugins/qmljsinspector/images/pause.png new file mode 100644 index 0000000000000000000000000000000000000000..c5d33a2d04b7ae11b35e88e4ef8033057a809093 Binary files /dev/null and b/src/plugins/qmljsinspector/images/pause.png differ diff --git a/src/plugins/qmljsinspector/images/play.png b/src/plugins/qmljsinspector/images/play.png new file mode 100644 index 0000000000000000000000000000000000000000..af75fcdb6285032ce073ab90bb1648d19d372b3f Binary files /dev/null and b/src/plugins/qmljsinspector/images/play.png differ diff --git a/src/plugins/qmljsinspector/images/reload.png b/src/plugins/qmljsinspector/images/reload.png new file mode 100644 index 0000000000000000000000000000000000000000..b5afefb32bc95115c47e8a31b96b96e10c1f6eea Binary files /dev/null and b/src/plugins/qmljsinspector/images/reload.png differ diff --git a/src/plugins/qmljsinspector/images/select-marquee.png b/src/plugins/qmljsinspector/images/select-marquee.png new file mode 100644 index 0000000000000000000000000000000000000000..a28381f117653497bff3245a2712acd341b545f9 Binary files /dev/null and b/src/plugins/qmljsinspector/images/select-marquee.png differ diff --git a/src/plugins/qmljsinspector/images/select.png b/src/plugins/qmljsinspector/images/select.png new file mode 100644 index 0000000000000000000000000000000000000000..5b0376f6f7e0a725ff5d236a8767cf0d733eafd7 Binary files /dev/null and b/src/plugins/qmljsinspector/images/select.png differ diff --git a/src/plugins/qmljsinspector/images/to-qml.png b/src/plugins/qmljsinspector/images/to-qml.png new file mode 100644 index 0000000000000000000000000000000000000000..84ff48fa951f40bdc013ec8eaa71a39ad7f6f0ea Binary files /dev/null and b/src/plugins/qmljsinspector/images/to-qml.png differ diff --git a/src/plugins/qmljsinspector/images/zoom.png b/src/plugins/qmljsinspector/images/zoom.png new file mode 100644 index 0000000000000000000000000000000000000000..4abf31444006ba1d80eb508c24e8cd0b0606d8f8 Binary files /dev/null and b/src/plugins/qmljsinspector/images/zoom.png differ diff --git a/src/plugins/qmljsinspector/qmlinspectortoolbar.cpp b/src/plugins/qmljsinspector/qmlinspectortoolbar.cpp new file mode 100644 index 0000000000000000000000000000000000000000..94f32c6a2437778feaa7bf1b18b9b667ecc71cc6 --- /dev/null +++ b/src/plugins/qmljsinspector/qmlinspectortoolbar.cpp @@ -0,0 +1,275 @@ +#include "qmlinspectortoolbar.h" +#include "qmljsinspectorconstants.h" + +#include <extensionsystem/pluginmanager.h> +#include <coreplugin/icore.h> +#include <debugger/debuggeruiswitcher.h> +#include <projectexplorer/projectexplorerconstants.h> +#include <coreplugin/actionmanager/actionmanager.h> +#include <coreplugin/actionmanager/command.h> + +#include <QHBoxLayout> +#include <QAction> +#include <QToolButton> + +namespace QmlJSInspector { +namespace Internal { + +static QToolButton *createToolButton(QAction *action) +{ + QToolButton *button = new QToolButton; + button->setDefaultAction(action); + return button; +} + +QmlInspectorToolbar::QmlInspectorToolbar(QObject *parent) : + QObject(parent), + m_reloadAction(0), + m_playAction(0), + m_pauseAction(0), + m_selectAction(0), + m_selectMarqueeAction(0), + m_zoomAction(0), + m_colorPickerAction(0), + m_toQmlAction(0), + m_fromQmlAction(0), + m_emitSignals(true), + m_isRunning(false), + m_activeTool(NoTool) +{ + +} + +void QmlInspectorToolbar::setEnabled(bool value) +{ + m_reloadAction->setEnabled(value); + m_playAction->setEnabled(value); + m_pauseAction->setEnabled(value); + m_selectAction->setEnabled(value); + m_selectMarqueeAction->setEnabled(value); + m_zoomAction->setEnabled(value); + m_colorPickerAction->setEnabled(value); + m_toQmlAction->setEnabled(value); + m_fromQmlAction->setEnabled(value); +} + +void QmlInspectorToolbar::enable() +{ + setEnabled(true); +} + +void QmlInspectorToolbar::disable() +{ + changeAnimationSpeed(1.0f); + activateSelectTool(); + setEnabled(false); +} + +void QmlInspectorToolbar::activateColorPicker() +{ + m_emitSignals = false; + activateColorPickerOnClick(); + m_emitSignals = true; +} + +void QmlInspectorToolbar::activateSelectTool() +{ + m_emitSignals = false; + activateSelectToolOnClick(); + m_emitSignals = true; +} + +void QmlInspectorToolbar::activateMarqueeSelectTool() +{ + m_emitSignals = false; + activateMarqueeSelectToolOnClick(); + m_emitSignals = true; +} + +void QmlInspectorToolbar::activateZoomTool() +{ + m_emitSignals = false; + activateZoomOnClick(); + m_emitSignals = true; +} + +void QmlInspectorToolbar::changeAnimationSpeed(qreal slowdownFactor) +{ + m_emitSignals = false; + if (slowdownFactor == 0) { + activatePauseOnClick(); + } else { + activatePlayOnClick(); + } + m_emitSignals = true; +} + +void QmlInspectorToolbar::createActions(const Core::Context &context) +{ + Core::ICore *core = Core::ICore::instance(); + Core::ActionManager *am = core->actionManager(); + ExtensionSystem::PluginManager *pluginManager = ExtensionSystem::PluginManager::instance(); + Debugger::DebuggerUISwitcher *uiSwitcher = pluginManager->getObject<Debugger::DebuggerUISwitcher>(); + + m_reloadAction = new QAction(QIcon(":/qml/images/reload.png"), "Reload", this); + m_reloadAction->setDisabled(true); + + m_playAction = new QAction(QIcon(":/qml/images/play.png"), tr("Play animations"), this); + m_pauseAction = new QAction(QIcon(":/qml/images/pause.png"), tr("Pause animations"), this); + m_selectAction = new QAction(QIcon(":/qml/images/select.png"), tr("Select"), this); + m_selectMarqueeAction = new QAction(QIcon(":/qml/images/select-marquee.png"), tr("Select (Marquee)"), this); + m_zoomAction = new QAction(QIcon(":/qml/images/zoom.png"), tr("Zoom"), this); + m_colorPickerAction = new QAction(QIcon(":/qml/images/color-picker.png"), tr("Color Picker"), this); + m_toQmlAction = new QAction(QIcon(":/qml/images/to-qml.png"), tr("Apply Changes to QML Viewer"), this); + m_fromQmlAction = new QAction(QIcon(":/qml/images/from-qml.png"), tr("Apply Changes to Document"), this); + m_playAction->setCheckable(true); + m_playAction->setChecked(true); + m_pauseAction->setCheckable(true); + m_selectAction->setCheckable(true); + m_selectMarqueeAction->setCheckable(true); + m_zoomAction->setCheckable(true); + m_colorPickerAction->setCheckable(true); + + am->registerAction(m_reloadAction, QmlJSInspector::Constants::RELOAD_ACTION, context); + am->registerAction(m_playAction, QmlJSInspector::Constants::PLAY_ACTION, context); + am->registerAction(m_pauseAction, QmlJSInspector::Constants::PAUSE_ACTION, context); + am->registerAction(m_selectAction, QmlJSInspector::Constants::SELECT_ACTION, context); + am->registerAction(m_selectMarqueeAction, QmlJSInspector::Constants::SELECT_MARQUEE_ACTION, context); + am->registerAction(m_zoomAction, QmlJSInspector::Constants::ZOOM_ACTION, context); + am->registerAction(m_colorPickerAction, QmlJSInspector::Constants::COLOR_PICKER_ACTION, context); + am->registerAction(m_toQmlAction, QmlJSInspector::Constants::TO_QML_ACTION, context); + am->registerAction(m_fromQmlAction, QmlJSInspector::Constants::FROM_QML_ACTION, context); + + QWidget *configBar = new QWidget; + configBar->setProperty("topBorder", true); + + QHBoxLayout *configBarLayout = new QHBoxLayout(configBar); + configBarLayout->setMargin(0); + configBarLayout->setSpacing(5); + + configBarLayout->addWidget(createToolButton(am->command(ProjectExplorer::Constants::DEBUG)->action())); + configBarLayout->addWidget(createToolButton(am->command(ProjectExplorer::Constants::STOP)->action())); + configBarLayout->addWidget(createToolButton(am->command(QmlJSInspector::Constants::RELOAD_ACTION)->action())); + configBarLayout->addWidget(createToolButton(am->command(QmlJSInspector::Constants::PLAY_ACTION)->action())); + configBarLayout->addWidget(createToolButton(am->command(QmlJSInspector::Constants::PAUSE_ACTION)->action())); + + configBarLayout->addWidget(createToolButton(am->command(QmlJSInspector::Constants::SELECT_ACTION)->action())); + configBarLayout->addWidget(createToolButton(am->command(QmlJSInspector::Constants::SELECT_MARQUEE_ACTION)->action())); + + configBarLayout->addWidget(createToolButton(am->command(QmlJSInspector::Constants::ZOOM_ACTION)->action())); + configBarLayout->addWidget(createToolButton(am->command(QmlJSInspector::Constants::COLOR_PICKER_ACTION)->action())); + + configBarLayout->addWidget(createToolButton(am->command(QmlJSInspector::Constants::TO_QML_ACTION)->action())); + configBarLayout->addWidget(createToolButton(am->command(QmlJSInspector::Constants::FROM_QML_ACTION)->action())); + + configBarLayout->addStretch(); + + uiSwitcher->setToolbar(QmlJSInspector::Constants::LANG_QML, configBar); + setEnabled(false); + + connect(m_colorPickerAction, SIGNAL(triggered()), SLOT(activateColorPickerOnClick())); + + connect(m_playAction, SIGNAL(triggered()), SLOT(activatePlayOnClick())); + connect(m_pauseAction, SIGNAL(triggered()), SLOT(activatePauseOnClick())); + + connect(m_zoomAction, SIGNAL(triggered()), SLOT(activateZoomOnClick())); + connect(m_colorPickerAction, SIGNAL(triggered()), SLOT(activateColorPickerOnClick())); + connect(m_selectAction, SIGNAL(triggered()), SLOT(activateSelectToolOnClick())); + connect(m_selectMarqueeAction, SIGNAL(triggered()), SLOT(activateMarqueeSelectToolOnClick())); + + connect(m_toQmlAction, SIGNAL(triggered()), SLOT(activateToQml())); + connect(m_fromQmlAction, SIGNAL(triggered()), SLOT(activateFromQml())); +} + +void QmlInspectorToolbar::activatePlayOnClick() +{ + m_pauseAction->setChecked(false); + if (!m_isRunning) { + m_playAction->setChecked(true); + m_isRunning = true; + if (m_emitSignals) + emit animationSpeedChanged(1.0f); + } +} + +void QmlInspectorToolbar::activatePauseOnClick() +{ + m_playAction->setChecked(false); + if (m_isRunning) { + m_isRunning = false; + m_pauseAction->setChecked(true); + if (m_emitSignals) + emit animationSpeedChanged(0.0f); + } +} + +void QmlInspectorToolbar::activateColorPickerOnClick() +{ + m_zoomAction->setChecked(false); + m_selectAction->setChecked(false); + m_selectMarqueeAction->setChecked(false); + + m_colorPickerAction->setChecked(true); + if (m_activeTool != ColorPickerMode) { + m_activeTool = ColorPickerMode; + if (m_emitSignals) + emit colorPickerSelected(); + } +} + +void QmlInspectorToolbar::activateSelectToolOnClick() +{ + m_zoomAction->setChecked(false); + m_selectMarqueeAction->setChecked(false); + m_colorPickerAction->setChecked(false); + + m_selectAction->setChecked(true); + if (m_activeTool != SelectionToolMode) { + m_activeTool = SelectionToolMode; + if (m_emitSignals) + emit selectToolSelected(); + } +} + +void QmlInspectorToolbar::activateMarqueeSelectToolOnClick() +{ + m_zoomAction->setChecked(false); + m_selectAction->setChecked(false); + m_colorPickerAction->setChecked(false); + + m_selectMarqueeAction->setChecked(true); + if (m_activeTool != MarqueeSelectionToolMode) { + m_activeTool = MarqueeSelectionToolMode; + if (m_emitSignals) + emit marqueeSelectToolSelected(); + } +} + +void QmlInspectorToolbar::activateZoomOnClick() +{ + m_selectAction->setChecked(false); + m_selectMarqueeAction->setChecked(false); + m_colorPickerAction->setChecked(false); + + m_zoomAction->setChecked(true); + if (m_activeTool != ZoomMode) { + m_activeTool = ZoomMode; + if (m_emitSignals) + emit zoomToolSelected(); + } +} + +void QmlInspectorToolbar::activateFromQml() +{ + if (m_emitSignals) + emit applyChangesFromQmlFileSelected(); +} + +void QmlInspectorToolbar::activateToQml() +{ + if (m_emitSignals) + emit applyChangesToQmlFileSelected(); +} + +} // namespace Internal +} // namespace QmlJSInspector diff --git a/src/plugins/qmljsinspector/qmlinspectortoolbar.h b/src/plugins/qmljsinspector/qmlinspectortoolbar.h new file mode 100644 index 0000000000000000000000000000000000000000..09427b5e0398ef69488fd707c960fe421fdbc3d1 --- /dev/null +++ b/src/plugins/qmljsinspector/qmlinspectortoolbar.h @@ -0,0 +1,85 @@ +#ifndef QMLINSPECTORTOOLBAR_H +#define QMLINSPECTORTOOLBAR_H + +#include <QObject> + +QT_FORWARD_DECLARE_CLASS(QAction); + +namespace Core { + class Context; +} + +namespace QmlJSInspector { +namespace Internal { + +class QmlInspectorToolbar : public QObject +{ + Q_OBJECT +public: + enum DesignTool { + NoTool = 0, + SelectionToolMode = 1, + MarqueeSelectionToolMode = 2, + MoveToolMode = 3, + ResizeToolMode = 4, + ColorPickerMode = 5, + ZoomMode = 6 + }; + + explicit QmlInspectorToolbar(QObject *parent = 0); + void createActions(const Core::Context &context); + +public slots: + void setEnabled(bool value); + void enable(); + void disable(); + + void activateColorPicker(); + void activateSelectTool(); + void activateMarqueeSelectTool(); + void activateZoomTool(); + void changeAnimationSpeed(qreal slowdownFactor); + +signals: + void animationSpeedChanged(qreal slowdownFactor = 1.0f); + + void colorPickerSelected(); + void selectToolSelected(); + void marqueeSelectToolSelected(); + void zoomToolSelected(); + + void applyChangesToQmlFileSelected(); + void applyChangesFromQmlFileSelected(); + +private slots: + void activatePlayOnClick(); + void activatePauseOnClick(); + void activateColorPickerOnClick(); + void activateSelectToolOnClick(); + void activateMarqueeSelectToolOnClick(); + void activateZoomOnClick(); + + void activateFromQml(); + void activateToQml(); + +private: + QAction *m_reloadAction; + QAction *m_playAction; + QAction *m_pauseAction; + QAction *m_selectAction; + QAction *m_selectMarqueeAction; + QAction *m_zoomAction; + QAction *m_colorPickerAction; + QAction *m_toQmlAction; + QAction *m_fromQmlAction; + + bool m_emitSignals; + bool m_isRunning; + DesignTool m_activeTool; + +}; + +} // namespace Internal +} // namespace QmlJSInspector + +#endif // QMLINSPECTORTOOLBAR_H diff --git a/src/plugins/qmljsinspector/qmljsclientproxy.cpp b/src/plugins/qmljsinspector/qmljsclientproxy.cpp index 6138feaece6cb063e94741352a8b66a86d0189fd..b5e22eb0e69b4bbe8015409cf8dc84bb52815c49 100644 --- a/src/plugins/qmljsinspector/qmljsclientproxy.cpp +++ b/src/plugins/qmljsinspector/qmljsclientproxy.cpp @@ -29,6 +29,7 @@ #include "qmljsclientproxy.h" #include "qmljsdebuggerclient.h" #include "qmljsprivateapi.h" +#include "qmljsdesigndebugclient.h" #include <utils/qtcassert.h> @@ -44,6 +45,7 @@ ClientProxy::ClientProxy(QObject *parent) : QObject(parent), m_conn(0), m_client(0), + m_designClient(0), m_engineQuery(0), m_contextQuery(0), m_objectTreeQuery(0) @@ -63,17 +65,29 @@ bool ClientProxy::connectToViewer(const QString &host, quint16 port) return false; qDebug() << Q_FUNC_INFO; - if (m_client) { -#warning disconnect selectedItemsChanged here -#if 0 - disconnect(m_client, SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>)), - this, SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>))); -#endif + if (m_designClient) { + + disconnect(m_designClient, SIGNAL(currentObjectsChanged(QList<QDeclarativeDebugObjectReference>)), + this, SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>))); + disconnect(m_designClient, + SIGNAL(colorPickerActivated()), this, SIGNAL(colorPickerActivated())); + disconnect(m_designClient, + SIGNAL(zoomToolActivated()), this, SIGNAL(zoomToolActivated())); + disconnect(m_designClient, + SIGNAL(selectToolActivated()), this, SIGNAL(selectToolActivated())); + disconnect(m_designClient, + SIGNAL(selectMarqueeToolActivated()), this, SIGNAL(selectMarqueeToolActivated())); + disconnect(m_designClient, + + SIGNAL(animationSpeedChanged(qreal)), this, SIGNAL(animationSpeedChanged(qreal))); emit aboutToDisconnect(); delete m_client; m_client = 0; + + delete m_designClient; + m_designClient = 0; } if (m_conn) { @@ -145,14 +159,23 @@ void ClientProxy::connectionStateChanged() if (!m_client) { qDebug() << "CREATING ENGINE"; m_client = new QDeclarativeEngineDebug(m_conn, this); + m_designClient = new QmlJSDesignDebugClient(m_conn, this); emit connected(m_client); -#warning add support for selectedItemsChanged here -#if 0 - connect(m_client, - SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>)), + connect(m_designClient, + SIGNAL(currentObjectsChanged(QList<QDeclarativeDebugObjectReference>)), SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>))); -#endif + connect(m_designClient, + SIGNAL(colorPickerActivated()), SIGNAL(colorPickerActivated())); + connect(m_designClient, + SIGNAL(zoomToolActivated()), SIGNAL(zoomToolActivated())); + connect(m_designClient, + SIGNAL(selectToolActivated()), SIGNAL(selectToolActivated())); + connect(m_designClient, + SIGNAL(selectMarqueeToolActivated()), SIGNAL(selectMarqueeToolActivated())); + connect(m_designClient, + SIGNAL(animationSpeedChanged(qreal)), SIGNAL(animationSpeedChanged(qreal))); + } (void) new DebuggerClient(m_conn); @@ -180,19 +203,30 @@ bool ClientProxy::isUnconnected() const return (!m_conn || m_conn->state() == QAbstractSocket::UnconnectedState); } -void ClientProxy::setSelectedItemByObjectId(int engineId, const QDeclarativeDebugObjectReference &objectRef) +void ClientProxy::setSelectedItemsByObjectId(const QList<QDeclarativeDebugObjectReference> &objectRefs) +{ + if (isConnected() && m_designClient) + m_designClient->setSelectedItemsByObjectId(objectRefs); +} + +QDeclarativeDebugObjectReference ClientProxy::objectReferenceForId(int debugId) const +{ + return objectReferenceForId(debugId, m_rootObject); +} + +QDeclarativeDebugObjectReference ClientProxy::objectReferenceForId(int debugId, + const QDeclarativeDebugObjectReference &objectRef) const { - Q_UNUSED(engineId); - Q_UNUSED(objectRef); - -#ifdef __GNUC__ -# warning implement ClientProxy::setSelectedItemByObjectId -#endif - qDebug() << "TODO:" << Q_FUNC_INFO; -#if 0 - if (isConnected()) - m_client->setSelectedItemByObjectId(engineId, objectRef); -#endif + if (objectRef.debugId() == debugId) + return objectRef; + + foreach(const QDeclarativeDebugObjectReference &child, objectRef.children()) { + QDeclarativeDebugObjectReference result = objectReferenceForId(debugId, child); + if (result.debugId() == debugId) + return result; + } + + return QDeclarativeDebugObjectReference(); } QList<QDeclarativeDebugObjectReference> ClientProxy::objectReferences(const QUrl &url) const @@ -287,20 +321,42 @@ void ClientProxy::objectTreeFetched(QDeclarativeDebugQuery::State state) emit objectTreeUpdated(m_rootObject); } -void ClientProxy::reloadQmlViewer(int engineId) +void ClientProxy::reloadQmlViewer() { -#ifdef __GNUC__ -# warning implement ClientProxy::reloadQmlViewer -#endif - Q_UNUSED(engineId); - qDebug() << "TODO:" << Q_FUNC_INFO; -#if 0 - if (m_client && m_conn->isConnected()) { - m_client->reloadQmlViewer(engineId); - } -#endif + if (m_designClient && m_conn->isConnected()) + m_designClient->reloadViewer(); +} + +void ClientProxy::setAnimationSpeed(qreal slowdownFactor) +{ + if (m_designClient && m_conn->isConnected()) + m_designClient->setAnimationSpeed(slowdownFactor); +} + +void ClientProxy::changeToColorPickerTool() +{ + if (m_designClient && m_conn->isConnected()) + m_designClient->changeToColorPickerTool(); +} + +void ClientProxy::changeToZoomTool() +{ + if (m_designClient && m_conn->isConnected()) + m_designClient->changeToZoomTool(); +} +void ClientProxy::changeToSelectTool() +{ + if (m_designClient && m_conn->isConnected()) + m_designClient->changeToSelectTool(); } +void ClientProxy::changeToSelectMarqueeTool() +{ + if (m_designClient && m_conn->isConnected()) + m_designClient->changeToSelectMarqueeTool(); +} + + void ClientProxy::reloadEngines() { if (m_engineQuery) { diff --git a/src/plugins/qmljsinspector/qmljsclientproxy.h b/src/plugins/qmljsinspector/qmljsclientproxy.h index 4ba30cd25b76c2786bebbe638f2e7f3989c2fb75..26dc2164db39f11ccc993cf70eae1ad58e0d3f21 100644 --- a/src/plugins/qmljsinspector/qmljsclientproxy.h +++ b/src/plugins/qmljsinspector/qmljsclientproxy.h @@ -46,6 +46,7 @@ namespace QmlJSInspector { namespace Internal { class InspectorPlugin; +class QmlJSDesignDebugClient; class ClientProxy : public QObject { @@ -60,12 +61,13 @@ public: bool isLiteralValue); // returns the object references for the given url. - QList<QDeclarativeDebugObjectReference> objectReferences(const QUrl &url) const; + QList<QDeclarativeDebugObjectReference> objectReferences(const QUrl &url = QUrl()) const; + QDeclarativeDebugObjectReference objectReferenceForId(int debugId) const; bool isConnected() const; bool isUnconnected() const; - void setSelectedItemByObjectId(int engineId, const QDeclarativeDebugObjectReference &objectRef); + void setSelectedItemsByObjectId(const QList<QDeclarativeDebugObjectReference> &objectRefs); bool connectToViewer(const QString &host, quint16 port); void disconnectFromViewer(); @@ -85,9 +87,21 @@ signals: void aboutToDisconnect(); void disconnected(); + void colorPickerActivated(); + void selectToolActivated(); + void selectMarqueeToolActivated(); + void zoomToolActivated(); + void animationSpeedChanged(qreal slowdownFactor); + public slots: void queryEngineContext(int id); - void reloadQmlViewer(int engineId); + void reloadQmlViewer(); + + void setAnimationSpeed(qreal slowdownFactor = 1.0f); + void changeToColorPickerTool(); + void changeToZoomTool(); + void changeToSelectTool(); + void changeToSelectMarqueeTool(); private slots: void contextChanged(); @@ -100,6 +114,7 @@ private slots: private: void reloadEngines(); QList<QDeclarativeDebugObjectReference> objectReferences(const QUrl &url, const QDeclarativeDebugObjectReference &objectRef) const; + QDeclarativeDebugObjectReference objectReferenceForId(int debugId, const QDeclarativeDebugObjectReference &ref) const; private: explicit ClientProxy(QObject *parent = 0); @@ -109,6 +124,7 @@ private: QDeclarativeDebugConnection *m_conn; QDeclarativeEngineDebug *m_client; + QmlJSDesignDebugClient *m_designClient; QDeclarativeDebugEnginesQuery *m_engineQuery; QDeclarativeDebugRootContextQuery *m_contextQuery; diff --git a/src/plugins/qmljsinspector/qmljsdelta.cpp b/src/plugins/qmljsinspector/qmljsdelta.cpp index 50392d0725200398cddda45f62cda7c29d4cabf3..0966ebd28bcb979bd32bc420e12a2785577c0fef 100644 --- a/src/plugins/qmljsinspector/qmljsdelta.cpp +++ b/src/plugins/qmljsinspector/qmljsdelta.cpp @@ -38,84 +38,42 @@ using namespace QmlJS; using namespace QmlJS::AST; using namespace QmlJSInspector::Internal; -namespace { +UiObjectMember *ScriptBindingParser::parent(UiScriptBinding *script) const +{ return _parent.value(script); } -class ScriptBindingParser : protected Visitor -{ - QList<UiObjectMember *> objectStack; - QHash<UiScriptBinding *, UiObjectMember *> _parent; - QHash<UiObjectMember *, UiScriptBinding *> _id; - QHash<UiScriptBinding *, QDeclarativeDebugObjectReference> _idBindings; - -public: - - QmlJS::Document::Ptr doc; - QList<UiScriptBinding *> scripts; - - ScriptBindingParser(Document::Ptr doc, const QList<QDeclarativeDebugObjectReference> &objectReferences = QList<QDeclarativeDebugObjectReference>()); - void process(); - - UiObjectMember *parent(UiScriptBinding *script) const - { return _parent.value(script); } - - UiScriptBinding *id(UiObjectMember *parent) const - { return _id.value(parent); } - - QList<UiScriptBinding *> ids() const - { return _id.values(); } - - QDeclarativeDebugObjectReference objectReferenceForPosition(const QUrl &url, int line, int col) const; - - QDeclarativeDebugObjectReference objectReferenceForScriptBinding(UiScriptBinding *binding) const; - - QDeclarativeDebugObjectReference objectReferenceForOffset(unsigned int offset); - - QString header(UiObjectMember *member) const - { - if (member) { - if (UiObjectDefinition *def = cast<UiObjectDefinition *>(member)) { - const int begin = def->firstSourceLocation().begin(); - const int end = def->initializer->lbraceToken.begin(); - return doc->source().mid(begin, end - begin); - } else if (UiObjectBinding *binding = cast<UiObjectBinding *>(member)) { - const int begin = binding->firstSourceLocation().begin(); - const int end = binding->initializer->lbraceToken.begin(); - return doc->source().mid(begin, end - begin); - } - } +UiScriptBinding *ScriptBindingParser::id(UiObjectMember *parent) const +{ return _id.value(parent); } - return QString(); - } +QList<UiScriptBinding *> ScriptBindingParser::ids() const +{ return _id.values(); } - QString scriptCode(UiScriptBinding *script) const - { - if (script) { - const int begin = script->statement->firstSourceLocation().begin(); - const int end = script->statement->lastSourceLocation().end(); +QString ScriptBindingParser::header(UiObjectMember *member) const +{ + if (member) { + if (UiObjectDefinition *def = cast<UiObjectDefinition *>(member)) { + const int begin = def->firstSourceLocation().begin(); + const int end = def->initializer->lbraceToken.begin(); + return doc->source().mid(begin, end - begin); + } else if (UiObjectBinding *binding = cast<UiObjectBinding *>(member)) { + const int begin = binding->firstSourceLocation().begin(); + const int end = binding->initializer->lbraceToken.begin(); return doc->source().mid(begin, end - begin); } - - return QString(); } -protected: - QDeclarativeDebugObjectReference objectReference(const QString &id) const; - - virtual bool visit(UiObjectDefinition *ast); - virtual void endVisit(UiObjectDefinition *); - virtual bool visit(UiObjectBinding *ast); - virtual void endVisit(UiObjectBinding *); - virtual bool visit(UiScriptBinding *ast); - -private: - QList<QDeclarativeDebugObjectReference> objectReferences; - QDeclarativeDebugObjectReference m_foundObjectReference; - unsigned int m_searchElementOffset; - -}; + return QString(); +} +QString ScriptBindingParser::scriptCode(UiScriptBinding *script) const +{ + if (script) { + const int begin = script->statement->firstSourceLocation().begin(); + const int end = script->statement->lastSourceLocation().end(); + return doc->source().mid(begin, end - begin); + } -} // end of anonymous namespace + return QString(); +} static bool isLiteralValue(ExpressionNode *expr) { diff --git a/src/plugins/qmljsinspector/qmljsdelta.h b/src/plugins/qmljsinspector/qmljsdelta.h index 9a6d356c2698f237cb5df4cd7040d2a74b073c5e..ef8b9454b61b8cd84c9b52ae6e130f5793916c0f 100644 --- a/src/plugins/qmljsinspector/qmljsdelta.h +++ b/src/plugins/qmljsinspector/qmljsdelta.h @@ -33,11 +33,61 @@ #include "qmljsprivateapi.h" #include <qmljs/qmljsdocument.h> +#include <qmljs/parser/qmljsastvisitor_p.h> #include <qmljs/parser/qmljsastfwd_p.h> +#include <qmljs/parser/qmljsast_p.h> + +using namespace QmlJS; +using namespace QmlJS::AST; namespace QmlJSInspector { namespace Internal { +class ScriptBindingParser : protected Visitor +{ +public: + QmlJS::Document::Ptr doc; + QList<UiScriptBinding *> scripts; + + ScriptBindingParser(Document::Ptr doc, + const QList<QDeclarativeDebugObjectReference> &objectReferences = QList<QDeclarativeDebugObjectReference>()); + void process(); + + UiObjectMember *parent(UiScriptBinding *script) const; + UiScriptBinding *id(UiObjectMember *parent) const; + QList<UiScriptBinding *> ids() const; + + QDeclarativeDebugObjectReference objectReferenceForPosition(const QUrl &url, int line, int col) const; + + QDeclarativeDebugObjectReference objectReferenceForScriptBinding(UiScriptBinding *binding) const; + + QDeclarativeDebugObjectReference objectReferenceForOffset(unsigned int offset); + + QString header(UiObjectMember *member) const; + + QString scriptCode(UiScriptBinding *script) const; + +protected: + QDeclarativeDebugObjectReference objectReference(const QString &id) const; + + virtual bool visit(UiObjectDefinition *ast); + virtual void endVisit(UiObjectDefinition *); + virtual bool visit(UiObjectBinding *ast); + virtual void endVisit(UiObjectBinding *); + virtual bool visit(UiScriptBinding *ast); + +private: + QList<UiObjectMember *> objectStack; + QHash<UiScriptBinding *, UiObjectMember *> _parent; + QHash<UiObjectMember *, UiScriptBinding *> _id; + QHash<UiScriptBinding *, QDeclarativeDebugObjectReference> _idBindings; + + QList<QDeclarativeDebugObjectReference> objectReferences; + QDeclarativeDebugObjectReference m_foundObjectReference; + unsigned int m_searchElementOffset; +}; + + class Delta { public: diff --git a/src/plugins/qmljsinspector/qmljsdesigndebugclient.cpp b/src/plugins/qmljsinspector/qmljsdesigndebugclient.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3642b7273649a636efd4c72a8316d93ec90e1fc0 --- /dev/null +++ b/src/plugins/qmljsinspector/qmljsdesigndebugclient.cpp @@ -0,0 +1,213 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmljsdesigndebugclient.h" +#include "qmljsclientproxy.h" +#include "qmljsinspectorconstants.h" + +namespace QmlJSInspector { +namespace Internal { + +QmlJSDesignDebugClient::QmlJSDesignDebugClient(QDeclarativeDebugConnection *client, + QObject */*parent*/) + : QDeclarativeDebugClient(QLatin1String("QDeclarativeDesignMode"), client) , + m_connection(client) +{ + setEnabled(true); +} + +void QmlJSDesignDebugClient::messageReceived(const QByteArray &message) +{ + QDataStream ds(message); + + QByteArray type; + ds >> type; + + QList<QDeclarativeDebugObjectReference> references; + + if (type == "CURRENT_OBJECTS_CHANGED") { + int objectCount; + ds >> objectCount; + for(int i = 0; i < objectCount; ++i) { + int debugId; + ds >> debugId; + if (debugId != -1) { + QDeclarativeDebugObjectReference ref = ClientProxy::instance()->objectReferenceForId(debugId); + if (ref.debugId() != -1) + references << ref; + } + } + emit currentObjectsChanged(references); + } else if (type == "TOOL_CHANGED") { + int toolId; + ds >> toolId; + + if (toolId == Constants::ColorPickerMode) { + emit colorPickerActivated(); + } else if (toolId == Constants::ZoomMode) { + emit zoomToolActivated(); + } else if (toolId == Constants::SelectionToolMode) { + emit selectToolActivated(); + } else if (toolId == Constants::MarqueeSelectionToolMode) { + emit selectMarqueeToolActivated(); + } + } else if (type == "ANIMATION_SPEED_CHANGED") { + qreal slowdownFactor; + ds >> slowdownFactor; + emit animationSpeedChanged(slowdownFactor); + } +} + +void QmlJSDesignDebugClient::setSelectedItemsByObjectId(const QList<QDeclarativeDebugObjectReference> &objects) +{ + if (!m_connection || !m_connection->isConnected()) + return; + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + ds << QByteArray("SET_CURRENT_OBJECTS") + << objects.length(); + + foreach(const QDeclarativeDebugObjectReference &ref, objects) { + ds << ref.debugId(); + } + + sendMessage(message); +} + +void QmlJSDesignDebugClient::reloadViewer() +{ + if (!m_connection || !m_connection->isConnected()) + return; + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + ds << QByteArray("RELOAD"); + sendMessage(message); +} + +void QmlJSDesignDebugClient::setAnimationSpeed(qreal slowdownFactor) +{ + if (!m_connection || !m_connection->isConnected()) + return; + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + ds << QByteArray("SET_ANIMATION_SPEED") + << slowdownFactor; + + sendMessage(message); +} + +void QmlJSDesignDebugClient::changeToColorPickerTool() +{ + if (!m_connection || !m_connection->isConnected()) + return; + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + ds << QByteArray("CHANGE_TOOL") + << QByteArray("COLOR_PICKER"); + sendMessage(message); +} + +void QmlJSDesignDebugClient::changeToSelectTool() +{ + if (!m_connection || !m_connection->isConnected()) + return; + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + ds << QByteArray("CHANGE_TOOL") + << QByteArray("SELECT"); + sendMessage(message); +} + +void QmlJSDesignDebugClient::changeToSelectMarqueeTool() +{ + if (!m_connection || !m_connection->isConnected()) + return; + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + ds << QByteArray("CHANGE_TOOL") + << QByteArray("SELECT_MARQUEE"); + sendMessage(message); +} + +void QmlJSDesignDebugClient::changeToZoomTool() +{ + if (!m_connection || !m_connection->isConnected()) + return; + + QByteArray message; + QDataStream ds(&message, QIODevice::WriteOnly); + + ds << QByteArray("CHANGE_TOOL") + << QByteArray("ZOOM"); + sendMessage(message); +} + +void QmlJSDesignDebugClient::applyChangesToQmlFile() +{ + if (!m_connection || !m_connection->isConnected()) + return; + + // TODO +} + +void QmlJSDesignDebugClient::applyChangesFromQmlFile() +{ + if (!m_connection || !m_connection->isConnected()) + return; + + // TODO +} + + +} // namespace Internal +} // namespace QmlJSInspector diff --git a/src/plugins/qmljsinspector/qmljsdesigndebugclient.h b/src/plugins/qmljsinspector/qmljsdesigndebugclient.h new file mode 100644 index 0000000000000000000000000000000000000000..71529300ee9227bcf9da01f15fe7ee38203a7ba1 --- /dev/null +++ b/src/plugins/qmljsinspector/qmljsdesigndebugclient.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLJSDESIGNDEBUGCLIENT_H +#define QMLJSDESIGNDEBUGCLIENT_H + +#include "private/qdeclarativedebug_p.h" +#include "private/qdeclarativedebugclient_p.h" + +namespace QmlJSInspector { +namespace Internal { + +class QmlJSDesignDebugClient : public QDeclarativeDebugClient +{ + Q_OBJECT +public: + QmlJSDesignDebugClient(QDeclarativeDebugConnection *client, + QObject *parent = 0); + + void setSelectedItemsByObjectId(const QList<QDeclarativeDebugObjectReference> &objects); + void reloadViewer(); + void setAnimationSpeed(qreal slowdownFactor); + void changeToColorPickerTool(); + void changeToSelectTool(); + void changeToSelectMarqueeTool(); + void changeToZoomTool(); + + void applyChangesToQmlFile(); + void applyChangesFromQmlFile(); + +signals: + void currentObjectsChanged(const QList<QDeclarativeDebugObjectReference> ¤tObjects); + void colorPickerActivated(); + void selectToolActivated(); + void selectMarqueeToolActivated(); + void zoomToolActivated(); + void animationSpeedChanged(qreal slowdownFactor); + +protected: + virtual void messageReceived(const QByteArray &); + +private: + QDeclarativeDebugConnection *m_connection; +}; + +} // namespace Internal +} // namespace QmlJSInspector + +#endif // QMLJSDESIGNDEBUGCLIENT_H diff --git a/src/plugins/qmljsinspector/qmljsinspector.cpp b/src/plugins/qmljsinspector/qmljsinspector.cpp index f62e28e89b80a0705981deedd72cf01ac7dc6e64..90367afb3767c10d7b94c6f352c066a7aec90a76 100644 --- a/src/plugins/qmljsinspector/qmljsinspector.cpp +++ b/src/plugins/qmljsinspector/qmljsinspector.cpp @@ -31,6 +31,8 @@ #include "qmljsclientproxy.h" #include "qmljsinspectorcontext.h" #include "qmljsdelta.h" +#include "qmljslivetextpreview.h" +#include "qmljsprivateapi.h" #include <qmljs/qmljsmodelmanagerinterface.h> #include <qmljs/qmljsdocument.h> @@ -77,9 +79,6 @@ #include <extensionsystem/pluginmanager.h> -#include <private/qdeclarativedebug_p.h> -#include <private/qdeclarativedebugclient_p.h> - #include <QtCore/QDebug> #include <QtCore/QStringList> #include <QtCore/QTimer> @@ -125,7 +124,9 @@ Inspector::Inspector(QObject *parent) #warning set up the context widget QWidget *contextWidget = 0; - m_context = new Internal::InspectorContext(contextWidget); + m_context = new InspectorContext(contextWidget); + + m_textPreview = new QmlJSLiveTextPreview(this); connect(m_clientProxy, SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>)), SLOT(setSelectedItemsByObjectReference(QList<QDeclarativeDebugObjectReference>))); @@ -181,14 +182,9 @@ void Inspector::updateEngineList() } } -void Inspector::changeSelectedItem(int engineId, const QDeclarativeDebugObjectReference &objectRef) +void Inspector::changeSelectedItems(const QList<QDeclarativeDebugObjectReference> &objects) { - Q_UNUSED(engineId); - Q_UNUSED(objectRef); - - qDebug() << "TODO:" << Q_FUNC_INFO; - -#warning implement setSelectedItemByObjectId + m_clientProxy->setSelectedItemsByObjectId(objects); } void Inspector::shutdown() @@ -206,7 +202,7 @@ void Inspector::pollInspector() const quint16 port = quint16(m_runConfigurationDebugData.serverPort); if (m_clientProxy->connectToViewer(host, port)) { -#warning get the QML/JS documents from the snapshot here + m_textPreview->updateDocuments(); m_connectionTimer->stop(); m_connectionAttempts = 0; } else if (m_connectionAttempts == MaxConnectionAttempts) { @@ -498,13 +494,9 @@ void Inspector::debuggerStateChanged(int newState) updateMenuActions(); } - void Inspector::reloadQmlViewer() { - qDebug() << Q_FUNC_INFO; - qDebug() << "TODO: set up the current engine id and restart the viewer"; -#warning set up the current engine id - // m_clientProxy->reloadQmlViewer(currentEngineId); + m_clientProxy->reloadQmlViewer(); } void Inspector::setSimpleDockWidgetArrangement() @@ -561,10 +553,6 @@ void Inspector::gotoObjectReferenceDefinition(const QDeclarativeDebugObjectRefer return; qDebug() << Q_FUNC_INFO << "selecting" << obj.className() << obj.debugId() << obj.source().url(); -#warning update the rewriter -#if 0 - m_rewriter->setActiveObject(obj); -#endif Core::EditorManager *editorManager = Core::EditorManager::instance(); Core::IEditor *editor = editorManager->openEditor(fileName, QString(), Core::EditorManager::NoModeSwitch); @@ -608,14 +596,3 @@ bool Inspector::addQuotesForData(const QVariant &value) const return false; } - -void Inspector::documentUpdated(QmlJS::Document::Ptr doc) -{ - Core::ICore *core = Core::ICore::instance(); - const int dbgcontext = core->uniqueIDManager()->uniqueIdentifier(Debugger::Constants::C_DEBUGMODE); - - if (! core->hasContext(dbgcontext)) - return; - - qDebug() << "TODO: compute the delta changes for:" << doc->fileName(); -} diff --git a/src/plugins/qmljsinspector/qmljsinspector.h b/src/plugins/qmljsinspector/qmljsinspector.h index 0b0778b576a7c9db2a909568153c6f26cbc74a9f..228011280be7b639692cdf4c5dec538eaa595f74 100644 --- a/src/plugins/qmljsinspector/qmljsinspector.h +++ b/src/plugins/qmljsinspector/qmljsinspector.h @@ -59,6 +59,7 @@ namespace Internal { class ClientProxy; class InspectorContext; +class QmlJSLiveTextPreview; class Inspector : public QObject { @@ -104,7 +105,7 @@ private slots: void pollInspector(); void setSelectedItemsByObjectReference(QList<QDeclarativeDebugObjectReference> objectReferences); - void changeSelectedItem(int engineId, const QDeclarativeDebugObjectReference &object); + void changeSelectedItems(const QList<QDeclarativeDebugObjectReference> &objects); void updateMenuActions(); void connected(QDeclarativeEngineDebug *client); @@ -114,8 +115,6 @@ private slots: void disconnectWidgets(); void disconnected(); - void documentUpdated(QmlJS::Document::Ptr doc); - private: Debugger::DebuggerRunControl *createDebuggerRunControl(ProjectExplorer::RunConfiguration *runConfig, const QString &executableFile = QString(), @@ -141,6 +140,9 @@ private: bool m_simultaneousCppAndQmlDebugMode; DebugMode m_debugMode; ClientProxy *m_clientProxy; + + // Qml/JS integration + QmlJSLiveTextPreview *m_textPreview; }; } // Internal diff --git a/src/plugins/qmljsinspector/qmljsinspector.pro b/src/plugins/qmljsinspector/qmljsinspector.pro index d89b2fe6ac6973be553e6496bbe62beb9e4ccb66..22f65cf3a98333726796afa59081d61c22679cca 100644 --- a/src/plugins/qmljsinspector/qmljsinspector.pro +++ b/src/plugins/qmljsinspector/qmljsinspector.pro @@ -17,7 +17,10 @@ qmljsinspectorcontext.h \ qmljsinspectorplugin.h \ qmljsclientproxy.h \ qmljsinspector.h \ -qmljsdelta.h +qmljsdelta.h \ +qmlinspectortoolbar.h \ +qmljslivetextpreview.h \ +qmljsdesigndebugclient.h SOURCES += \ qmljsdebuggerclient.cpp \ @@ -25,7 +28,10 @@ qmljsinspectorcontext.cpp \ qmljsinspectorplugin.cpp \ qmljsclientproxy.cpp \ qmljsinspector.cpp \ -qmljsdelta.cpp +qmljsdelta.cpp \ +qmlinspectortoolbar.cpp \ +qmljslivetextpreview.cpp \ +qmljsdesigndebugclient.cpp OTHER_FILES += QmlJSInspector.pluginspec RESOURCES += qmljsinspector.qrc diff --git a/src/plugins/qmljsinspector/qmljsinspector.qrc b/src/plugins/qmljsinspector/qmljsinspector.qrc index 45e8ddaad5d1b5e26b94e9a90d69e48eb5502cc4..fb5c57ff314ddb3144caf114c97c41e112f2b4d8 100644 --- a/src/plugins/qmljsinspector/qmljsinspector.qrc +++ b/src/plugins/qmljsinspector/qmljsinspector.qrc @@ -1,6 +1,13 @@ <RCC> - <qresource prefix="/qmlinspector" > - <file>images/logo.png</file> + <qresource prefix="/qml"> + <file>images/color-picker.png</file> + <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> </qresource> </RCC> - diff --git a/src/plugins/qmljsinspector/qmljsinspectorconstants.h b/src/plugins/qmljsinspector/qmljsinspectorconstants.h index ee04ce02afc7ef8f257c9344cdb86066a8280430..4870cf4b56743bcc4926e1a00d19d9a822bd8617 100644 --- a/src/plugins/qmljsinspector/qmljsinspectorconstants.h +++ b/src/plugins/qmljsinspector/qmljsinspectorconstants.h @@ -30,26 +30,49 @@ #define QMLJSINSPECTORCONSTANTS_H namespace QmlJSInspector { - namespace Constants { - const char * const RUN = "QmlInspector.Run"; - const char * const STOP = "QmlInspector.Stop"; +namespace Constants { - const char * const C_INSPECTOR = "QmlInspector"; - const char * const COMPLETE_THIS = "QmlInspector.CompleteThis"; +const char * const RUN = "QmlInspector.Run"; +const char * const STOP = "QmlInspector.Stop"; - const char * const M_DEBUG_SIMULTANEOUSLY = "QmlInspector.Menu.SimultaneousDebug"; +const char * const C_INSPECTOR = "QmlInspector"; +const char * const COMPLETE_THIS = "QmlInspector.CompleteThis"; - const char * const LANG_QML = "QML"; +const char * const M_DEBUG_SIMULTANEOUSLY = "QmlInspector.Menu.SimultaneousDebug"; - // settings - const char * const S_QML_INSPECTOR = "QML.Inspector"; - const char * const S_EXTERNALPORT_KEY = "ExternalPort"; - const char * const S_EXTERNALURL_KEY = "ExternalUrl"; - const char * const S_SHOW_UNINSPECTABLE_ITEMS = "ShowUninspectableProperties"; - const char * const S_SHOW_UNWATCHABLE_PROPERTIES = "ShowUninspectableItem"; - const char * const S_GROUP_PROPERTIES_BY_ITEM_TYPE = "GroupPropertiesByItemType"; +const char * const LANG_QML = "QML"; - } -} +const char * const RELOAD_ACTION = "QmlInspector.Reload"; +const char * const PLAY_ACTION = "QmlInspector.Play"; +const char * const PAUSE_ACTION = "QmlInspector.Pause"; +const char * const SELECT_ACTION = "QmlInspector.Select"; +const char * const SELECT_MARQUEE_ACTION = "QmlInspector.SelectMarquee"; +const char * const ZOOM_ACTION = "QmlInspector.Zoom"; +const char * const COLOR_PICKER_ACTION = "QmlInspector.ColorPicker"; +const char * const TO_QML_ACTION = "QmlInspector.ToQml"; +const char * const FROM_QML_ACTION = "QmlInspector.FromQml"; + +// settings +const char * const S_QML_INSPECTOR = "QML.Inspector"; +const char * const S_EXTERNALPORT_KEY = "ExternalPort"; +const char * const S_EXTERNALURL_KEY = "ExternalUrl"; +const char * const S_SHOW_UNINSPECTABLE_ITEMS = "ShowUninspectableProperties"; +const char * const S_SHOW_UNWATCHABLE_PROPERTIES = "ShowUninspectableItem"; +const char * const S_GROUP_PROPERTIES_BY_ITEM_TYPE = "GroupPropertiesByItemType"; + +const char * const ARG_DESIGNMODE = "-designmode"; + +enum DesignTool { + NoTool = 0, + SelectionToolMode = 1, + MarqueeSelectionToolMode = 2, + MoveToolMode = 3, + ResizeToolMode = 4, + ColorPickerMode = 5, + ZoomMode = 6 +}; + +} // namespace Constants +} // namespace Qml #endif diff --git a/src/plugins/qmljsinspector/qmljsinspectorplugin.cpp b/src/plugins/qmljsinspector/qmljsinspectorplugin.cpp index dbff04b33e90149e4999619a92101b549a43aa30..3513f7df512d71fd5f7122bb662fa6f5fc4a2d03 100644 --- a/src/plugins/qmljsinspector/qmljsinspectorplugin.cpp +++ b/src/plugins/qmljsinspector/qmljsinspectorplugin.cpp @@ -31,6 +31,7 @@ #include "qmljsinspectorplugin.h" #include "qmljsinspector.h" #include "qmljsclientproxy.h" +#include "qmlinspectortoolbar.h" #include <debugger/debuggeruiswitcher.h> #include <debugger/debuggerconstants.h> @@ -87,6 +88,7 @@ InspectorPlugin::InspectorPlugin() _clientProxy = new ClientProxy(this); _inspector = new Inspector(this); + m_toolbar = new QmlInspectorToolbar(this); } InspectorPlugin::~InspectorPlugin() @@ -158,28 +160,23 @@ void InspectorPlugin::extensionsInitialized() connect(pex, SIGNAL(aboutToExecuteProject(ProjectExplorer::Project*, QString)), SLOT(activateDebuggerForProject(ProjectExplorer::Project*, QString))); } + m_toolbar->createActions(Core::Context(C_INSPECTOR)); - QWidget *configBar = new QWidget; - configBar->setProperty("topBorder", true); + connect(_clientProxy, SIGNAL(connected(QDeclarativeEngineDebug*)), m_toolbar, SLOT(enable())); + connect(_clientProxy, SIGNAL(disconnected()), m_toolbar, SLOT(disable())); - QHBoxLayout *configBarLayout = new QHBoxLayout(configBar); - configBarLayout->setMargin(0); - configBarLayout->setSpacing(5); + connect(m_toolbar, SIGNAL(animationSpeedChanged(qreal)), _clientProxy, SLOT(setAnimationSpeed(qreal))); + connect(m_toolbar, SIGNAL(colorPickerSelected()), _clientProxy, SLOT(changeToColorPickerTool())); + connect(m_toolbar, SIGNAL(zoomToolSelected()), _clientProxy, SLOT(changeToZoomTool())); + connect(m_toolbar, SIGNAL(selectToolSelected()), _clientProxy, SLOT(changeToSelectTool())); + connect(m_toolbar, SIGNAL(marqueeSelectToolSelected()), _clientProxy, SLOT(changeToSelectMarqueeTool())); - Core::ICore *core = Core::ICore::instance(); - Core::ActionManager *am = core->actionManager(); - configBarLayout->addWidget(createToolButton(am->command(ProjectExplorer::Constants::DEBUG)->action())); - configBarLayout->addWidget(createToolButton(am->command(ProjectExplorer::Constants::STOP)->action())); - - configBarLayout->addStretch(); - - uiSwitcher->setToolbar(LANG_QML, configBar); - - if (QmlJS::ModelManagerInterface *m = InspectorPlugin::instance()->modelManager()) { - connect(m, SIGNAL(documentUpdated(QmlJS::Document::Ptr)), - _inspector, SLOT(documentUpdated(QmlJS::Document::Ptr))); - } + connect(_clientProxy, SIGNAL(colorPickerActivated()), m_toolbar, SLOT(activateColorPicker())); + connect(_clientProxy, SIGNAL(selectToolActivated()), m_toolbar, SLOT(activateSelectTool())); + connect(_clientProxy, SIGNAL(selectMarqueeToolActivated()), m_toolbar, SLOT(activateMarqueeSelectTool())); + connect(_clientProxy, SIGNAL(zoomToolActivated()), m_toolbar, SLOT(activateZoomTool())); + connect(_clientProxy, SIGNAL(animationSpeedChanged(qreal)), m_toolbar, SLOT(changeAnimationSpeed(qreal))); } void InspectorPlugin::activateDebuggerForProject(ProjectExplorer::Project *project, const QString &runMode) diff --git a/src/plugins/qmljsinspector/qmljsinspectorplugin.h b/src/plugins/qmljsinspector/qmljsinspectorplugin.h index b4056ae9b0d45aaf99fd4d1e9a076ef20bdf4302..d1696b0668fa95ad6167ec13f2de81c3c4edee76 100644 --- a/src/plugins/qmljsinspector/qmljsinspectorplugin.h +++ b/src/plugins/qmljsinspector/qmljsinspectorplugin.h @@ -49,6 +49,7 @@ namespace ProjectExplorer { namespace QmlJSInspector { namespace Internal { +class QmlInspectorToolbar; class ClientProxy; class Inspector; @@ -78,9 +79,13 @@ public slots: private slots: void prepareDebugger(Core::IMode *mode); +private: + void createActions(); + private: ClientProxy *_clientProxy; Inspector *_inspector; + QmlInspectorToolbar *m_toolbar; }; } // end of namespace Internal diff --git a/src/plugins/qmljsinspector/qmljslivetextpreview.cpp b/src/plugins/qmljsinspector/qmljslivetextpreview.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9cb2b354a76889c39c1b720a8a4fe561ea75e7b9 --- /dev/null +++ b/src/plugins/qmljsinspector/qmljslivetextpreview.cpp @@ -0,0 +1,124 @@ +#include <typeinfo> + +#include "qmljsclientproxy.h" +#include "qmljslivetextpreview.h" +#include "qmljsdelta.h" +#include "qmljsprivateapi.h" + +#include <qmljseditor/qmljseditorconstants.h> +#include <qmljseditor/qmljseditor.h> +#include <extensionsystem/pluginmanager.h> + +#include <coreplugin/icore.h> +#include <coreplugin/editormanager/ieditor.h> +#include <coreplugin/uniqueidmanager.h> +#include <coreplugin/editormanager/editormanager.h> + +#include <debugger/debuggerconstants.h> + +#include <QDebug> + +using namespace QmlJS::AST; + +namespace QmlJSInspector { +namespace Internal { + +QmlJSLiveTextPreview::QmlJSLiveTextPreview(QObject *parent) : + QObject(parent) +{ + Core::EditorManager *editorManager = Core::EditorManager::instance(); + connect(editorManager->instance(), SIGNAL(currentEditorChanged(Core::IEditor*)), + SLOT(setEditor(Core::IEditor*))); +} + +QmlJS::ModelManagerInterface *QmlJSLiveTextPreview::modelManager() +{ + return ExtensionSystem::PluginManager::instance()->getObject<QmlJS::ModelManagerInterface>(); +} + +void QmlJSLiveTextPreview::updateDocuments() +{ + if (!modelManager()) + return; + + m_snapshot = modelManager()->snapshot(); + + // initial update + foreach (QmlJS::Document::Ptr doc, m_snapshot) { + documentChanged(doc); + } + + connect(modelManager(), SIGNAL(documentChangedOnDisk(QmlJS::Document::Ptr)), + SLOT(documentChanged(QmlJS::Document::Ptr))); +} + +void QmlJSLiveTextPreview::changeSelectedElement(int offset, const QString &wordAtCursor) +{ + qDebug() << __FUNCTION__ << offset << wordAtCursor; + + if (!m_currentEditor) + return; + + ClientProxy *clientProxy = ClientProxy::instance(); + QUrl url = QUrl::fromLocalFile(m_currentEditor.data()->file()->fileName()); + QmlJS::Document::Ptr doc = modelManager()->snapshot().document(m_currentEditor.data()->file()->fileName()); + ScriptBindingParser info(doc, clientProxy->objectReferences(url)); + + QDeclarativeDebugObjectReference objectRef; + + QList<QDeclarativeDebugObjectReference> refs = clientProxy->objectReferences(); + foreach (const QDeclarativeDebugObjectReference &ref, refs) { + if (ref.idString() == wordAtCursor) { + objectRef = ref; + qDebug() << "yes"; + break; + } + } + + if (objectRef.debugId() == -1 && offset >= 0) { + objectRef = info.objectReferenceForOffset(offset); + + qDebug() << "====================="; + qDebug() << objectRef.className() << objectRef.source().url() << objectRef.source().lineNumber() << offset; + qDebug() << "====================="; + } + + if (objectRef.debugId() != -1) + emit selectedItemsChanged(QList<QDeclarativeDebugObjectReference>() << objectRef); +} + +void QmlJSLiveTextPreview::setEditor(Core::IEditor *editor) +{ + if (!m_currentEditor.isNull()) { + disconnect(m_currentEditor.data(), SIGNAL(selectedElementChanged(int, QString)), this, SLOT(changeSelectedElement(int, QString))); + m_currentEditor.clear(); + m_previousDoc.clear(); + } + if (editor) { + m_currentEditor = qobject_cast<QmlJSEditor::Internal::QmlJSTextEditor*>(editor->widget()); + if (m_currentEditor) { + connect(m_currentEditor.data(), SIGNAL(selectedElementChanged(int, QString)), SLOT(changeSelectedElement(int, QString))); + m_previousDoc = m_snapshot.document(editor->file()->fileName()); + } + } +} + +void QmlJSLiveTextPreview::documentChanged(QmlJS::Document::Ptr doc) +{ + Core::ICore *core = Core::ICore::instance(); + const int dbgcontext = core->uniqueIDManager()->uniqueIdentifier(Debugger::Constants::C_DEBUGMODE); + + if (! core->hasContext(dbgcontext)) + return; + + if (doc && m_previousDoc) { + qDebug() << "Doc, prevDoc:" << doc->fileName() << m_previousDoc->fileName(); + + Delta delta; + delta(doc, m_previousDoc); + m_previousDoc = doc; + } +} + +} // namespace Internal +} // namespace QmlJSInspector diff --git a/src/plugins/qmljsinspector/qmljslivetextpreview.h b/src/plugins/qmljsinspector/qmljslivetextpreview.h new file mode 100644 index 0000000000000000000000000000000000000000..019aa36dac20de57bb5462e53d85bb46d6d0a106 --- /dev/null +++ b/src/plugins/qmljsinspector/qmljslivetextpreview.h @@ -0,0 +1,68 @@ +#ifndef SCRIPTBINDINGREWRITER_H +#define SCRIPTBINDINGREWRITER_H + +#include <QObject> +#include <QWeakPointer> + +#include <private/qdeclarativedebug_p.h> +#include <qmljs/parser/qmljsastfwd_p.h> +#include <qmljs/qmljsdocument.h> + +QT_FORWARD_DECLARE_CLASS(QTextDocument) +QT_FORWARD_DECLARE_CLASS(QDeclarativeDebugObjectReference) + +namespace Core { + class IEditor; +} + +namespace QmlJS { + class ModelManagerInterface; +} + +namespace QmlJSEditor { +namespace Internal { + class QmlJSTextEditor; +} +} + +namespace QmlJSInspector { +namespace Internal { + +class QmlJSLiveTextPreview : public QObject +{ + Q_OBJECT +public: + explicit QmlJSLiveTextPreview(QObject *parent = 0); + static QmlJS::ModelManagerInterface *modelManager(); + void updateDocuments(); + + void setActiveObject(const QDeclarativeDebugObjectReference &object); + + void mapObjectToQml(const QDeclarativeDebugObjectReference &object); + +public slots: + void setCurrentEngineId(int id); + +signals: + void selectedItemsChanged(const QList<QDeclarativeDebugObjectReference> &objects); + +private slots: + void changeSelectedElement(int offset, const QString &wordAtCursor); + void documentChanged(QmlJS::Document::Ptr doc); + void setEditor(Core::IEditor *editor); + +private: + QVariant castToLiteral(const QString &expression, QmlJS::AST::UiScriptBinding *scriptBinding); + +private: + QmlJS::Document::Ptr m_previousDoc; + + QmlJS::Snapshot m_snapshot; + QWeakPointer<QmlJSEditor::Internal::QmlJSTextEditor> m_currentEditor; + +}; + +} // namespace Internal +} // namespace QmlJSInspector + +#endif // SCRIPTBINDINGREWRITER_H diff --git a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp index 7461ef73f47be2c1e91646cc206d24636bbf4842..c96a87eb9b9eec9c2f7533e91ec93c8a629a4de3 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp @@ -81,6 +81,12 @@ QmlRunControl::~QmlRunControl() void QmlRunControl::start() { + if (runMode() == ProjectExplorer::Constants::DEBUGMODE) { + if (!m_commandLineArguments.contains(QmlJSInspector::Constants::ARG_DESIGNMODE)) { + m_commandLineArguments.append(QmlJSInspector::Constants::ARG_DESIGNMODE); + } + } + m_applicationLauncher.start(ProjectExplorer::ApplicationLauncher::Gui, m_executable, m_commandLineArguments);