diff --git a/src/plugins/qmljsinspector/qmlinspectortoolbar.cpp b/src/plugins/qmljsinspector/qmlinspectortoolbar.cpp index 0b7870eef0f87be725ccf9d60cdd3f5fefe1d366..98d4dd3adabb90050b82165a34efba0afe9d5fd6 100644 --- a/src/plugins/qmljsinspector/qmlinspectortoolbar.cpp +++ b/src/plugins/qmljsinspector/qmlinspectortoolbar.cpp @@ -166,7 +166,7 @@ void QmlInspectorToolbar::createActions(const Core::Context &context) m_selectMarqueeAction = new QAction(QIcon(":/qml/images/select-marquee-small.png"), tr("Select (Marquee)"), this); m_zoomAction = new QAction(QIcon(":/qml/images/zoom-small.png"), tr("Zoom"), this); m_colorPickerAction = new QAction(QIcon(":/qml/images/color-picker-small.png"), tr("Color Picker"), this); - m_toQmlAction = new QAction(QIcon(":/qml/images/to-qml-small.png"), tr("Apply Changes to QML Viewer"), this); + m_toQmlAction = new QAction(QIcon(":/qml/images/to-qml-small.png"), tr("Live Preview Changes in QML Viewer"), this); m_designmodeAction->setCheckable(true); m_designmodeAction->setChecked(false); @@ -401,6 +401,11 @@ void QmlInspectorToolbar::activateZoomOnClick() } } +void QmlInspectorToolbar::setLivePreviewChecked(bool value) +{ + m_fromQmlAction->setChecked(value); +} + void QmlInspectorToolbar::setSelectedColor(const QColor &color) { m_colorBox->setColor(color); diff --git a/src/plugins/qmljsinspector/qmlinspectortoolbar.h b/src/plugins/qmljsinspector/qmlinspectortoolbar.h index efed26f50f6cfdff4ea4151ccd52dcea6fe3951f..21d3c9d71961ca61bbd9f7ea0025bf8bb08b9b39 100644 --- a/src/plugins/qmljsinspector/qmlinspectortoolbar.h +++ b/src/plugins/qmljsinspector/qmlinspectortoolbar.h @@ -46,6 +46,8 @@ public slots: void setDesignModeBehavior(bool inDesignMode); void setSelectedColor(const QColor &color); + void setLivePreviewChecked(bool value); + signals: void animationSpeedChanged(qreal slowdownFactor = 1.0f); diff --git a/src/plugins/qmljsinspector/qmljsinspector.cpp b/src/plugins/qmljsinspector/qmljsinspector.cpp index eb477773f7c1424929012cb0f8af7fc74daed573..0201deaddfde9121204e3923ea13bc5af538a0c5 100644 --- a/src/plugins/qmljsinspector/qmljsinspector.cpp +++ b/src/plugins/qmljsinspector/qmljsinspector.cpp @@ -116,6 +116,8 @@ enum { ConnectionAttemptSimultaneousInterval = 500 }; +bool Inspector::m_showExperimentalWarning = true; + Inspector::Inspector(QObject *parent) : QObject(parent), m_connectionTimer(new QTimer(this)), @@ -275,6 +277,9 @@ void Inspector::createPreviewForEditor(Core::IEditor *newEditor) connect(preview, SIGNAL(selectedItemsChanged(QList<QDeclarativeDebugObjectReference>)), SLOT(changeSelectedItems(QList<QDeclarativeDebugObjectReference>))); + connect(preview, SIGNAL(reloadQmlViewerRequested()), m_clientProxy, SLOT(reloadQmlViewer())); + connect(preview, SIGNAL(disableLivePreviewRequested()), SLOT(disableLivePreview())); + m_textPreviews.insert(newEditor->file()->fileName(), preview); preview->associateEditor(newEditor); preview->updateDebugIds(m_clientProxy->rootObjectReference()); @@ -640,6 +645,7 @@ bool Inspector::addQuotesForData(const QVariant &value) const void Inspector::setApplyChangesToQmlObserver(bool applyChanges) { + emit livePreviewActivated(applyChanges); QHashIterator<QString, QmlJSLiveTextPreview *> iter(m_textPreviews); while(iter.hasNext()) { iter.next(); @@ -647,3 +653,17 @@ void Inspector::setApplyChangesToQmlObserver(bool applyChanges) } } +bool Inspector::showExperimentalWarning() +{ + return m_showExperimentalWarning; +} + +void Inspector::setShowExperimentalWarning(bool value) +{ + m_showExperimentalWarning = value; +} + +void Inspector::disableLivePreview() +{ + setApplyChangesToQmlObserver(false); +} diff --git a/src/plugins/qmljsinspector/qmljsinspector.h b/src/plugins/qmljsinspector/qmljsinspector.h index 81dc606aa0fc09b4f440cc4c91280449faedbf2c..fb83678b3cf2cdd4f95cdc06c1af85200763b264 100644 --- a/src/plugins/qmljsinspector/qmljsinspector.h +++ b/src/plugins/qmljsinspector/qmljsinspector.h @@ -79,6 +79,7 @@ public: Inspector(QObject *parent = 0); virtual ~Inspector(); + bool connectToViewer(); // using host, port from widgets void shutdown(); @@ -92,8 +93,13 @@ public: QDeclarativeDebugExpressionQuery *setBindingForObject(int objectDebugId, const QString &objectId, const QString &propertyName, const QVariant &value, bool isLiteralValue); + static bool showExperimentalWarning(); + static void setShowExperimentalWarning(bool value); + + signals: void statusMessage(const QString &text); + void livePreviewActivated(bool isActivated); public slots: void setSimpleDockWidgetArrangement(); @@ -122,6 +128,8 @@ private slots: void removePreviewForEditor(Core::IEditor *newEditor); void createPreviewForEditor(Core::IEditor *newEditor); + void disableLivePreview(); + private: Debugger::DebuggerRunControl *createDebuggerRunControl(ProjectExplorer::RunConfiguration *runConfig, const QString &executableFile = QString(), @@ -136,6 +144,7 @@ private: bool addQuotesForData(const QVariant &value) const; void resetViews(); + QmlJS::ModelManagerInterface *modelManager(); void initializeDocuments(); @@ -151,6 +160,8 @@ private: DebugMode m_debugMode; ClientProxy *m_clientProxy; + static bool m_showExperimentalWarning; + // Qml/JS integration QHash<QString, QmlJSLiveTextPreview *> m_textPreviews; QmlJS::Snapshot m_loadedSnapshot; //the snapshot loaded by the viewer diff --git a/src/plugins/qmljsinspector/qmljsinspectorconstants.h b/src/plugins/qmljsinspector/qmljsinspectorconstants.h index 5915d1bb2b993174087b9f6db41285594f820877..b8ffb798b93e2cd1951b9d5ecf5e027250a813e0 100644 --- a/src/plugins/qmljsinspector/qmljsinspectorconstants.h +++ b/src/plugins/qmljsinspector/qmljsinspectorconstants.h @@ -40,6 +40,9 @@ const char * const COMPLETE_THIS = "QmlInspector.CompleteThis"; const char * const M_DEBUG_SIMULTANEOUSLY = "QmlInspector.Menu.SimultaneousDebug"; +const char * const INFO_EXPERIMENTAL = "QmlInspector.Experimental"; +const char * const INFO_OUT_OF_SYNC = "QmlInspector.OutOfSyncWarning"; + const char * const LANG_QML = "QML"; const char * const DESIGNMODE_ACTION = "QmlInspector.DesignMode"; diff --git a/src/plugins/qmljsinspector/qmljsinspectorplugin.cpp b/src/plugins/qmljsinspector/qmljsinspectorplugin.cpp index f69fb16967ff60b24aaf8bfe5b200f817ee200c1..8a5a0dc962969c3713a7e627836328a5dbf54c11 100644 --- a/src/plugins/qmljsinspector/qmljsinspectorplugin.cpp +++ b/src/plugins/qmljsinspector/qmljsinspectorplugin.cpp @@ -168,6 +168,7 @@ void InspectorPlugin::extensionsInitialized() connect(m_toolbar, SIGNAL(marqueeSelectToolSelected()), _clientProxy, SLOT(changeToSelectMarqueeTool())); connect(m_toolbar, SIGNAL(applyChangesFromQmlFileTriggered(bool)), _inspector, SLOT(setApplyChangesToQmlObserver(bool))); + connect(_inspector, SIGNAL(livePreviewActivated(bool)), m_toolbar, SLOT(setLivePreviewChecked(bool))); connect(_clientProxy, SIGNAL(colorPickerActivated()), m_toolbar, SLOT(activateColorPicker())); connect(_clientProxy, SIGNAL(selectToolActivated()), m_toolbar, SLOT(activateSelectTool())); connect(_clientProxy, SIGNAL(selectMarqueeToolActivated()), m_toolbar, SLOT(activateMarqueeSelectTool())); diff --git a/src/plugins/qmljsinspector/qmljslivetextpreview.cpp b/src/plugins/qmljsinspector/qmljslivetextpreview.cpp index 2793d9ee6fd1a390166b4648d5d0166ecc839758..4c1707254a02f94602c9a92d1d2964a88d415bdb 100644 --- a/src/plugins/qmljsinspector/qmljslivetextpreview.cpp +++ b/src/plugins/qmljsinspector/qmljslivetextpreview.cpp @@ -29,10 +29,12 @@ #include <typeinfo> +#include "qmljsinspector.h" #include "qmljsclientproxy.h" #include "qmljslivetextpreview.h" #include "qmljsprivateapi.h" +#include "qmljsinspectorconstants.h" #include <qmljseditor/qmljseditorconstants.h> #include <qmljseditor/qmljseditor.h> #include <qmljs/qmljsdelta.h> @@ -430,6 +432,12 @@ protected: virtual void updateScriptBinding(DebugId debugId, UiScriptBinding* scriptBinding, const QString& propertyName, const QString& scriptCode) { + if (propertyName == QLatin1String("id") && !hasUnsyncronizableChanges) { + hasUnsyncronizableChanges = true; + unsyncronizableChangeLine = scriptBinding->firstSourceLocation().startLine; + unsyncronizableChangeColumn = scriptBinding->firstSourceLocation().startColumn; + } + QVariant expr = scriptCode; const bool isLiteral = isLiteralValue(scriptBinding); if (isLiteral) @@ -455,8 +463,12 @@ virtual void updateScriptBinding(DebugId debugId, UiScriptBinding* scriptBinding } public: - UpdateObserver() : referenceRefreshRequired(false) {} + UpdateObserver() : referenceRefreshRequired(false), hasUnsyncronizableChanges(false) {} bool referenceRefreshRequired; + bool hasUnsyncronizableChanges; + unsigned unsyncronizableChangeLine; + unsigned unsyncronizableChangeColumn; + }; void QmlJSLiveTextPreview::documentChanged(QmlJS::Document::Ptr doc) @@ -470,9 +482,17 @@ void QmlJSLiveTextPreview::documentChanged(QmlJS::Document::Ptr doc) if (!core->hasContext(dbgcontext)) return; + bool experimentalWarningShown = false; + if (m_applyChangesToQmlObserver) { m_docWithUnappliedChanges.clear(); + if (Inspector::showExperimentalWarning()) { + showExperimentalWarning(); + experimentalWarningShown = true; + Inspector::setShowExperimentalWarning(false); + } + if (doc && m_previousDoc && doc->fileName() == m_previousDoc->fileName() && doc->qmlProgram() && m_previousDoc->qmlProgram()) { @@ -482,6 +502,9 @@ void QmlJSLiveTextPreview::documentChanged(QmlJS::Document::Ptr doc) if (delta.referenceRefreshRequired) ClientProxy::instance()->refreshObjectTree(); + if (delta.hasUnsyncronizableChanges && !experimentalWarningShown) + showSyncWarning(delta.unsyncronizableChangeLine, delta.unsyncronizableChangeColumn); + m_previousDoc = doc; if (!delta.newObjects.isEmpty()) m_createdObjects[doc] += delta.newObjects; @@ -491,6 +514,37 @@ void QmlJSLiveTextPreview::documentChanged(QmlJS::Document::Ptr doc) } } +void QmlJSLiveTextPreview::showExperimentalWarning() +{ + Core::EditorManager *em = Core::EditorManager::instance(); + em->showEditorInfoBar(Constants::INFO_EXPERIMENTAL, + tr("You changed a QML file in in Live Preview mode, and the changes were applied to the running QML application. " + "This feature is experimental, and behavior can be unexpected."), + tr("Disable Live Preview"), this, SLOT(disableLivePreview())); +} + +void QmlJSLiveTextPreview::showSyncWarning(unsigned line, unsigned column) +{ + Core::EditorManager *em = Core::EditorManager::instance(); + em->showEditorInfoBar(Constants::INFO_OUT_OF_SYNC, + tr("The change at line %1, column %2 cannot be applied without reloading the QML application. " + "You can continue debugging, but behavior can be unexpected."). + arg(QString::number(line), QString::number(column)), + tr("Reload"), this, SLOT(reloadQmlViewer())); +} + +void QmlJSLiveTextPreview::reloadQmlViewer() +{ + Core::EditorManager::instance()->hideEditorInfoBar(Constants::INFO_OUT_OF_SYNC); + emit reloadQmlViewerRequested(); +} + +void QmlJSLiveTextPreview::disableLivePreview() +{ + Core::EditorManager::instance()->hideEditorInfoBar(Constants::INFO_EXPERIMENTAL); + emit disableLivePreviewRequested(); +} + void QmlJSLiveTextPreview::setApplyChangesToQmlObserver(bool applyChanges) { if (applyChanges && !m_applyChangesToQmlObserver) { diff --git a/src/plugins/qmljsinspector/qmljslivetextpreview.h b/src/plugins/qmljsinspector/qmljslivetextpreview.h index 83faa2b04eac1fc6ba0b265ab8fb29bff4c0e82f..6173e5c0150c6f2eb722573b7d05ebd72ad0b9da 100644 --- a/src/plugins/qmljsinspector/qmljslivetextpreview.h +++ b/src/plugins/qmljsinspector/qmljslivetextpreview.h @@ -73,6 +73,8 @@ public: signals: void selectedItemsChanged(const QList<QDeclarativeDebugObjectReference> &objects); + void reloadQmlViewerRequested(); + void disableLivePreviewRequested(); public slots: void setApplyChangesToQmlObserver(bool applyChanges); @@ -81,11 +83,14 @@ public slots: private slots: void changeSelectedElements(QList<int> offsets, const QString &wordAtCursor); void documentChanged(QmlJS::Document::Ptr doc); - + void disableLivePreview(); + void reloadQmlViewer(); private: QList<int> objectReferencesForOffset(quint32 offset) const; QVariant castToLiteral(const QString &expression, QmlJS::AST::UiScriptBinding *scriptBinding); + void showSyncWarning(unsigned line, unsigned column); + void showExperimentalWarning(); private: QHash<QmlJS::AST::UiObjectMember*, QList<int> > m_debugIds;