Commit 2c15b30a authored by Lasse Holmstedt's avatar Lasse Holmstedt
Browse files

Qml JS Live Preview: Show warnings when running Live Preview

Two kinds of warnings are now shown: one for warning about the Live
Preview itself, as it is experimental, and another when user changes
id's of objects during runtime, as this is not supported at the moment.

More warnings will be added later for other unsupported changes.
parent 07ac6bca
......@@ -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);
......
......@@ -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);
......
......@@ -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);
}
......@@ -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
......
......@@ -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";
......
......@@ -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()));
......
......@@ -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) {
......
......@@ -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;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment