diff options
-rw-r--r-- | doc/images/qml-observer-bar-reload.png | bin | 708 -> 0 bytes | |||
-rw-r--r-- | doc/src/debugger/qtquick-debugging.qdoc | 11 | ||||
-rw-r--r-- | src/plugins/debugger/debugger.qbs | 1 | ||||
-rw-r--r-- | src/plugins/debugger/debuggeractions.cpp | 5 | ||||
-rw-r--r-- | src/plugins/debugger/debuggeractions.h | 3 | ||||
-rw-r--r-- | src/plugins/debugger/debuggerconstants.h | 1 | ||||
-rw-r--r-- | src/plugins/debugger/debuggerplugin.cpp | 8 | ||||
-rw-r--r-- | src/plugins/debugger/qml/qml.pri | 2 | ||||
-rw-r--r-- | src/plugins/debugger/qml/qmlengine.h | 1 | ||||
-rw-r--r-- | src/plugins/debugger/qml/qmlinspectoradapter.cpp | 193 | ||||
-rw-r--r-- | src/plugins/debugger/qml/qmlinspectoradapter.h | 20 | ||||
-rw-r--r-- | src/plugins/debugger/qml/qmllivetextpreview.cpp | 743 | ||||
-rw-r--r-- | src/plugins/debugger/qml/qmllivetextpreview.h | 121 |
13 files changed, 2 insertions, 1107 deletions
diff --git a/doc/images/qml-observer-bar-reload.png b/doc/images/qml-observer-bar-reload.png Binary files differdeleted file mode 100644 index 3c05180d01..0000000000 --- a/doc/images/qml-observer-bar-reload.png +++ /dev/null diff --git a/doc/src/debugger/qtquick-debugging.qdoc b/doc/src/debugger/qtquick-debugging.qdoc index fc7d7723be..70678cf1ac 100644 --- a/doc/src/debugger/qtquick-debugging.qdoc +++ b/doc/src/debugger/qtquick-debugging.qdoc @@ -168,17 +168,6 @@ \section1 Applying QML Changes at Runtime - \omit - // currently broken & disabled - - If you change property values or add properties in the code editor, the - debugger can update the properties in the running application when you save - the file. This is enabled by default. To disable it, click the - \inlineimage qml-observer-bar-reload.png "Apply Changes on Save button" - (\uicontrol {Apply Changes on Save}) button on the toolbar. - - \endomit - When you change property values in the \uicontrol {QML/JS Console} or in the \uicontrol {Locals and Expressions} view, they are immediately updated in the running application, but not in the source code. diff --git a/src/plugins/debugger/debugger.qbs b/src/plugins/debugger/debugger.qbs index f6a49138c0..bb4a37057b 100644 --- a/src/plugins/debugger/debugger.qbs +++ b/src/plugins/debugger/debugger.qbs @@ -153,7 +153,6 @@ QtcPlugin { "qmlengine.cpp", "qmlengine.h", "qmlinspectoradapter.cpp", "qmlinspectoradapter.h", "qmlinspectoragent.cpp", "qmlinspectoragent.h", - "qmllivetextpreview.cpp", "qmllivetextpreview.h", "qmlv8debuggerclient.cpp", "qmlv8debuggerclient.h", "qmlv8debuggerclientconstants.h", "qscriptdebuggerclient.cpp", "qscriptdebuggerclient.h" diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp index e58367e479..c766b28da6 100644 --- a/src/plugins/debugger/debuggeractions.cpp +++ b/src/plugins/debugger/debuggeractions.cpp @@ -655,11 +655,6 @@ DebuggerSettings::DebuggerSettings() item->setSettingsKey(qmlInspectorGroup, QLatin1String("QmlInspector.ShowAppOnTop")); item->setDefaultValue(false); insertItem(ShowAppOnTop, item); - - item = new SavedAction(this); - item->setSettingsKey(qmlInspectorGroup, QLatin1String("QmlInspector.FromQml")); - item->setDefaultValue(false); - insertItem(QmlUpdateOnSave, item); } DebuggerSettings::~DebuggerSettings() diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h index 2b3202fcd5..843d0dfadb 100644 --- a/src/plugins/debugger/debuggeractions.h +++ b/src/plugins/debugger/debuggeractions.h @@ -185,8 +185,7 @@ enum DebuggerActionCode // QML Tools ShowQmlObjectTree, - ShowAppOnTop, - QmlUpdateOnSave + ShowAppOnTop }; } // namespace Internal diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h index 0bfb5f749b..800e81bac1 100644 --- a/src/plugins/debugger/debuggerconstants.h +++ b/src/plugins/debugger/debuggerconstants.h @@ -63,7 +63,6 @@ const char RESET[] = "Debugger.Reset"; const char OPERATE_BY_INSTRUCTION[] = "Debugger.OperateByInstruction"; const char OPERATE_NATIVE_MIXED[] = "Debugger.OperateNativeMixed"; const char QML_SHOW_APP_ON_TOP[] = "Debugger.QmlShowAppOnTop"; -const char QML_UPDATE_ON_SAVE[] = "Debugger.QmlUpdateOnSave"; const char QML_SELECTTOOL[] = "Debugger.QmlSelectTool"; const char QML_ZOOMTOOL[] = "Debugger.QmlZoomTool"; diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 1a14e3f970..6796198153 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -958,9 +958,6 @@ public slots: bool parseArguments(const QStringList &args, QString *errorMessage); void parseCommandLineArguments(); - void updateQmlActions() { - action(QmlUpdateOnSave)->setEnabled(boolSetting(ShowQmlObjectTree)); - } public: DebuggerMainWindow *m_mainWindow; @@ -2957,11 +2954,6 @@ void DebuggerPluginPrivate::extensionsInitialized() connect(action(SettingsDialog), &QAction::triggered, [] { ICore::showOptionsDialog(DEBUGGER_COMMON_SETTINGS_ID); }); - // QML Actions - connect(action(ShowQmlObjectTree), &SavedAction::valueChanged, - this, &DebuggerPluginPrivate::updateQmlActions); - updateQmlActions(); - // Toolbar QWidget *toolbarContainer = new QWidget; diff --git a/src/plugins/debugger/qml/qml.pri b/src/plugins/debugger/qml/qml.pri index a8ec530a7c..3dd714070d 100644 --- a/src/plugins/debugger/qml/qml.pri +++ b/src/plugins/debugger/qml/qml.pri @@ -8,7 +8,6 @@ HEADERS += \ $$PWD/interactiveinterpreter.h \ $$PWD/qmlv8debuggerclientconstants.h \ $$PWD/qmlinspectoragent.h \ - $$PWD/qmllivetextpreview.h \ $$PWD/qmlinspectoradapter.h SOURCES += \ @@ -20,5 +19,4 @@ SOURCES += \ $$PWD/qmlv8debuggerclient.cpp \ $$PWD/interactiveinterpreter.cpp \ $$PWD/qmlinspectoragent.cpp \ - $$PWD/qmllivetextpreview.cpp \ $$PWD/qmlinspectoradapter.cpp diff --git a/src/plugins/debugger/qml/qmlengine.h b/src/plugins/debugger/qml/qmlengine.h index 5993399699..60fd23dd2c 100644 --- a/src/plugins/debugger/qml/qmlengine.h +++ b/src/plugins/debugger/qml/qmlengine.h @@ -40,6 +40,7 @@ #include <qmldebug/qdebugmessageclient.h> #include <qmldebug/qmloutputparser.h> #include <qmljs/iscriptevaluator.h> +#include <qmljs/qmljsdocument.h> QT_FORWARD_DECLARE_CLASS(QTextDocument) diff --git a/src/plugins/debugger/qml/qmlinspectoradapter.cpp b/src/plugins/debugger/qml/qmlinspectoradapter.cpp index 0eb3c88c91..cec5d2f1ea 100644 --- a/src/plugins/debugger/qml/qmlinspectoradapter.cpp +++ b/src/plugins/debugger/qml/qmlinspectoradapter.cpp @@ -32,7 +32,6 @@ #include "qmladapter.h" #include "qmlinspectoragent.h" -#include "qmllivetextpreview.h" #include <debugger/debuggeractions.h> #include <debugger/debuggercore.h> #include <debugger/debuggerstringutils.h> @@ -48,8 +47,6 @@ #include <qmldebug/declarativetoolsclient.h> #include <qmldebug/qmlenginedebugclient.h> #include <qmldebug/qmltoolsclient.h> -#include <qmljseditor/qmljseditorconstants.h> -#include <qmljs/qmljsmodelmanagerinterface.h> #include <utils/qtcassert.h> #include <utils/savedaction.h> @@ -75,13 +72,11 @@ QmlInspectorAdapter::QmlInspectorAdapter(QmlAdapter *debugAdapter, , m_targetToSync(NoTarget) , m_debugIdToSelect(-1) , m_currentSelectedDebugId(-1) - , m_listeningToEditorManager(false) , m_toolsClientConnected(false) , m_inspectorToolsContext("Debugger.QmlInspector") , m_selectAction(new QAction(this)) , m_zoomAction(new QAction(this)) , m_showAppOnTopAction(action(ShowAppOnTop)) - , m_updateOnSaveAction(action(QmlUpdateOnSave)) , m_engineClientConnected(false) { if (!m_engine->isMasterEngine()) @@ -143,11 +138,9 @@ QmlInspectorAdapter::QmlInspectorAdapter(QmlAdapter *debugAdapter, m_selectAction->setCheckable(true); m_zoomAction->setCheckable(true); m_showAppOnTopAction->setCheckable(true); - m_updateOnSaveAction->setCheckable(true); m_selectAction->setEnabled(false); m_zoomAction->setEnabled(false); m_showAppOnTopAction->setEnabled(false); - m_updateOnSaveAction->setEnabled(false); connect(m_selectAction, SIGNAL(triggered(bool)), SLOT(onSelectActionTriggered(bool))); @@ -155,8 +148,6 @@ QmlInspectorAdapter::QmlInspectorAdapter(QmlAdapter *debugAdapter, SLOT(onZoomActionTriggered(bool))); connect(m_showAppOnTopAction, SIGNAL(triggered(bool)), SLOT(onShowAppOnTopChanged(bool))); - connect(m_updateOnSaveAction, SIGNAL(triggered(bool)), - SLOT(onUpdateOnSaveChanged(bool))); } QmlInspectorAdapter::~QmlInspectorAdapter() @@ -225,9 +216,6 @@ void QmlInspectorAdapter::toolsClientStateChanged(QmlDebugClient::State state) Core::ActionManager::registerAction(m_showAppOnTopAction, Core::Id(Constants::QML_SHOW_APP_ON_TOP), m_inspectorToolsContext); - Core::ActionManager::registerAction(m_updateOnSaveAction, - Core::Id(Constants::QML_UPDATE_ON_SAVE), - m_inspectorToolsContext); Core::ICore::addAdditionalContext(m_inspectorToolsContext); @@ -246,8 +234,6 @@ void QmlInspectorAdapter::toolsClientStateChanged(QmlDebugClient::State state) Core::ActionManager::unregisterAction(m_zoomAction, Core::Id(Constants::QML_ZOOMTOOL)); Core::ActionManager::unregisterAction(m_showAppOnTopAction, Core::Id(Constants::QML_SHOW_APP_ON_TOP)); - Core::ActionManager::unregisterAction(m_updateOnSaveAction, - Core::Id(Constants::QML_UPDATE_ON_SAVE)); Core::ICore::removeAdditionalContext(m_inspectorToolsContext); @@ -256,7 +242,6 @@ void QmlInspectorAdapter::toolsClientStateChanged(QmlDebugClient::State state) m_selectAction->setCheckable(false); m_zoomAction->setCheckable(false); m_showAppOnTopAction->setCheckable(false); - m_updateOnSaveAction->setCheckable(false); } } @@ -271,7 +256,6 @@ void QmlInspectorAdapter::engineClientStateChanged(QmlDebugClient::State state) setActiveEngineClient(client); } else if (m_engineClientConnected && client == m_engineClient) { m_engineClientConnected = false; - deletePreviews(); } } @@ -293,85 +277,6 @@ void QmlInspectorAdapter::onObjectFetched(const ObjectReference &ref) } } -void QmlInspectorAdapter::createPreviewForEditor(Core::IEditor *newEditor) -{ - if (!m_engineClientConnected) - return; - - if (!newEditor || newEditor->document()->id() - != QmlJSEditor::Constants::C_QMLJSEDITOR_ID) - return; - - QString filename = newEditor->document()->filePath().toString(); - QmlJS::ModelManagerInterface *modelManager = - QmlJS::ModelManagerInterface::instance(); - if (modelManager) { - QmlJS::Document::Ptr doc = modelManager->snapshot().document(filename); - if (!doc) { - if (filename.endsWith(QLatin1String(".qml")) || filename.endsWith(QLatin1String(".js"))) { - // 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() && !filename.endsWith(QLatin1String(".js"))) - 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); - - preview->setApplyChangesToQmlInspector(action(QmlUpdateOnSave)->isChecked()); - connect(preview, SIGNAL(reloadRequest()), - this, SLOT(onReload())); - - m_textPreviews.insert(newEditor->document()->filePath().toString(), preview); - preview->associateEditor(newEditor); - preview->updateDebugIds(); - } - } -} - -void QmlInspectorAdapter::removePreviewForEditor(Core::IEditor *editor) -{ - if (QmlLiveTextPreview *preview - = m_textPreviews.value(editor->document()->filePath().toString())) { - preview->unassociateEditor(editor); - } -} - -void QmlInspectorAdapter::updatePendingPreviewDocuments(QmlJS::Document::Ptr doc) -{ - int idx = -1; - idx = m_pendingPreviewDocumentNames.indexOf(doc->fileName()); - - if (idx == -1) - return; - - QList<Core::IEditor *> editors - = Core::DocumentModel::editorsForFilePath(doc->fileName()); - - if (editors.isEmpty()) - return; - - m_pendingPreviewDocumentNames.removeAt(idx); - - Core::IEditor *editor = editors.takeFirst(); - createPreviewForEditor(editor); - QmlLiveTextPreview *preview - = m_textPreviews.value(editor->document()->filePath().toString()); - foreach (Core::IEditor *editor, editors) - preview->associateEditor(editor); -} - void QmlInspectorAdapter::onSelectActionTriggered(bool checked) { QTC_ASSERT(toolsClient(), return); @@ -402,16 +307,6 @@ void QmlInspectorAdapter::onShowAppOnTopChanged(bool checked) toolsClient()->showAppOnTop(checked); } -void QmlInspectorAdapter::onUpdateOnSaveChanged(bool checked) -{ - QTC_ASSERT(toolsClient(), return); - for (QHash<QString, QmlLiveTextPreview *>::const_iterator it - = m_textPreviews.constBegin(); - it != m_textPreviews.constEnd(); ++it) { - it.value()->setApplyChangesToQmlInspector(checked); - } -} - void QmlInspectorAdapter::setActiveEngineClient(BaseEngineDebugClient *client) { if (m_engineClient == client) @@ -420,54 +315,6 @@ void QmlInspectorAdapter::setActiveEngineClient(BaseEngineDebugClient *client) m_engineClient = client; m_agent->setEngineClient(m_engineClient); m_engineClientConnected = true; - - if (m_engineClient && - m_engineClient->state() == QmlDebugClient::Enabled) { - QmlJS::ModelManagerInterface *modelManager - = QmlJS::ModelManagerInterface::instance(); - if (modelManager) { - 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() -{ - QmlJS::ModelManagerInterface *modelManager - = QmlJS::ModelManagerInterface::instance(); - if (modelManager) { - m_loadedSnapshot = modelManager->snapshot(); - - if (!m_listeningToEditorManager) { - m_listeningToEditorManager = true; - QObject *em = Core::EditorManager::instance(); - 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::IDocument *document, Core::DocumentModel::openedDocuments()) { - QList<Core::IEditor *> editors = Core::DocumentModel::editorsForDocument(document); - createPreviewForEditor(editors.takeFirst()); - QmlLiveTextPreview *preview - = m_textPreviews.value(document->filePath().toString()); - foreach (Core::IEditor *editor, editors) - preview->associateEditor(editor); - } - } } void QmlInspectorAdapter::showConnectionStateMessage(const QString &message) @@ -500,60 +347,20 @@ void QmlInspectorAdapter::selectObject(const ObjectReference &obj, agent()->selectObjectInTree(obj.debugId()); } -void QmlInspectorAdapter::deletePreviews() -{ - qDeleteAll(m_textPreviews); - m_textPreviews.clear(); -} - void QmlInspectorAdapter::enableTools(const bool enable) { if (!m_toolsClientConnected) return; m_selectAction->setEnabled(enable); m_showAppOnTopAction->setEnabled(enable); - m_updateOnSaveAction->setEnabled(enable); // only enable zoom action for Qt 4.x/old client // (zooming is integrated into selection tool in Qt 5). if (!qobject_cast<QmlToolsClient*>(m_toolsClient)) m_zoomAction->setEnabled(enable); } -void QmlInspectorAdapter::onReload() -{ - QHash<QString, QByteArray> changesHash; - for (QHash<QString, QmlLiveTextPreview *>::const_iterator it - = m_textPreviews.constBegin(); - it != m_textPreviews.constEnd(); ++it) { - if (it.value()->hasUnsynchronizableChange()) { - QFileInfo info = QFileInfo(it.value()->fileName()); - QFile changedFile(it.value()->fileName()); - QByteArray fileContents; - if (changedFile.open(QFile::ReadOnly)) - fileContents = changedFile.readAll(); - changedFile.close(); - changesHash.insert(info.fileName(), - fileContents); - } - } - if (m_toolsClient) - m_toolsClient->reload(changesHash); -} - void QmlInspectorAdapter::onReloaded() { - QmlJS::ModelManagerInterface *modelManager = - QmlJS::ModelManagerInterface::instance(); - if (modelManager) { - QmlJS::Snapshot snapshot = modelManager->snapshot(); - m_loadedSnapshot = 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); - } - } m_agent->reloadEngines(); } diff --git a/src/plugins/debugger/qml/qmlinspectoradapter.h b/src/plugins/debugger/qml/qmlinspectoradapter.h index a39f196aba..9c487f439c 100644 --- a/src/plugins/debugger/qml/qmlinspectoradapter.h +++ b/src/plugins/debugger/qml/qmlinspectoradapter.h @@ -35,9 +35,6 @@ #include <coreplugin/icontext.h> #include <qmldebug/qmldebugclient.h> -#include <qmljs/qmljsdocument.h> - -namespace Core { class IEditor; } namespace QmlDebug { class BaseEngineDebugClient; @@ -50,10 +47,8 @@ namespace Debugger { namespace Internal { class DebuggerEngine; -class WatchTreeView; class QmlAdapter; class QmlInspectorAgent; -class QmlLiveTextPreview; class QmlInspectorAdapter : public QObject { @@ -84,15 +79,9 @@ private slots: void selectObjectsFromToolsClient(const QList<int> &debugIds); void onObjectFetched(const QmlDebug::ObjectReference &ref); - 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(bool checked); - void onUpdateOnSaveChanged(bool checked); - void onReload(); void onReloaded(); void onDestroyedObject(int); void jumpToObjectDefinitionInEditor(const QmlDebug::FileReference &objSource, int debugId = -1); @@ -100,14 +89,12 @@ private slots: private: void setActiveEngineClient(QmlDebug::BaseEngineDebugClient *client); - void initializePreviews(); void showConnectionStateMessage(const QString &message); enum SelectionTarget { NoTarget, ToolTarget, EditorTarget }; void selectObject( const QmlDebug::ObjectReference &objectReference, SelectionTarget target); - void deletePreviews(); void enableTools(const bool enable); @@ -124,19 +111,12 @@ private: 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; - // toolbar bool m_toolsClientConnected; Core::Context m_inspectorToolsContext; QAction *m_selectAction; QAction *m_zoomAction; QAction *m_showAppOnTopAction; - QAction *m_updateOnSaveAction; bool m_engineClientConnected; }; diff --git a/src/plugins/debugger/qml/qmllivetextpreview.cpp b/src/plugins/debugger/qml/qmllivetextpreview.cpp deleted file mode 100644 index fb6cf9540c..0000000000 --- a/src/plugins/debugger/qml/qmllivetextpreview.cpp +++ /dev/null @@ -1,743 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms and -** conditions see http://www.qt.io/terms-conditions. For further information -** use the contact form at http://www.qt.io/contact-us. -** -** 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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "qmllivetextpreview.h" - -#include "qmlinspectoradapter.h" -#include "qmlinspectoragent.h" - -#include <coreplugin/infobar.h> -#include <texteditor/textdocument.h> -#include <qmldebug/basetoolsclient.h> -#include <qmljseditor/qmljseditorconstants.h> -#include <qmljs/parser/qmljsast_p.h> -#include <qmljs/qmljsdelta.h> -#include <qmljs/qmljsmodelmanagerinterface.h> -#include <utils/qtcassert.h> - -using namespace QmlDebug; -using namespace QmlJS; -using namespace QmlJS::AST; - -namespace Debugger { -namespace Internal { - -const char INFO_OUT_OF_SYNC[] = "Debugger.Inspector.OutOfSyncWarning"; - -/*! - Associates the UiObjectMember* to their QDeclarativeDebugObjectReference. - */ -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); - - QHash<QPair<int, int>, DebugIdList> ids; - QString filename; - QHash<UiObjectMember *, DebugIdList> result; - QSet<UiObjectMember *> lookupObjects; - -private: - void process(UiObjectMember *ast); - void process(UiObjectBinding *ast); -private: - int activated; -}; - -class UpdateInspector : public Delta { -private: - static inline QString stripQuotes(const QString &str) - { - if ((str.startsWith(QLatin1Char('"')) && str.endsWith(QLatin1Char('"'))) - || (str.startsWith(QLatin1Char('\'')) - && str.endsWith(QLatin1Char('\'')))) - return str.mid(1, str.length() - 2); - - return str; - } - - static inline QString deEscape(const QString &value) - { - QString result = value; - - result.replace(QLatin1String("\\\\"), QLatin1String("\\")); - result.replace(QLatin1String("\\\""), QLatin1String("\"")); - result.replace(QLatin1String("\\\t"), QLatin1String("\t")); - result.replace(QLatin1String("\\\r"), QLatin1String("\\\r")); - result.replace(QLatin1String("\\\n"), QLatin1String("\n")); - - return result; - } - - static QString cleanExpression(const QString &expression, - UiScriptBinding *scriptBinding) - { - QString trimmedExpression = expression.trimmed(); - - if (ExpressionStatement *expStatement - = cast<ExpressionStatement*>(scriptBinding->statement)) { - if (expStatement->semicolonToken.isValid()) - trimmedExpression.chop(1); - } - - return deEscape(stripQuotes(trimmedExpression)); - } - - static bool isLiteralValue(ExpressionNode *expr) - { - if (cast<NumericLiteral*>(expr)) - return true; - else if (cast<StringLiteral*>(expr)) - return true; - else if (UnaryPlusExpression *plusExpr - = cast<UnaryPlusExpression*>(expr)) - return isLiteralValue(plusExpr->expression); - else if (UnaryMinusExpression *minusExpr - = cast<UnaryMinusExpression*>(expr)) - return isLiteralValue(minusExpr->expression); - else if (cast<TrueLiteral*>(expr)) - return true; - else if (cast<FalseLiteral*>(expr)) - return true; - else - return false; - } - - static inline bool isLiteralValue(UiScriptBinding *script) - { - if (!script || !script->statement) - return false; - - ExpressionStatement *exprStmt - = cast<ExpressionStatement *>(script->statement); - if (exprStmt) - return isLiteralValue(exprStmt->expression); - else - return false; - } - - static QVariant castToLiteral(const QString &expression, - UiScriptBinding *scriptBinding) - { - const QString cleanedValue = cleanExpression(expression, scriptBinding); - QVariant castedExpression; - - ExpressionStatement *expStatement - = cast<ExpressionStatement*>(scriptBinding->statement); - - switch (expStatement->expression->kind) { - case Node::Kind_NumericLiteral: - case Node::Kind_UnaryPlusExpression: - case Node::Kind_UnaryMinusExpression: - castedExpression = QVariant(cleanedValue).toReal(); - break; - case Node::Kind_StringLiteral: - castedExpression = QVariant(cleanedValue).toString(); - break; - case Node::Kind_TrueLiteral: - case Node::Kind_FalseLiteral: - castedExpression = QVariant(cleanedValue).toBool(); - break; - default: - castedExpression = cleanedValue; - break; - } - - return castedExpression; - } - -protected: - virtual void updateMethodBody(DebugId debugId, - UiObjectMember *parentDefinition, - UiScriptBinding *scriptBinding, - const QString &methodName, - const QString &methodBody) - { - Q_UNUSED(scriptBinding); - Q_UNUSED(parentDefinition); - appliedChangesToViewer = true; - if (m_inspectorAdapter->engineClient()) - m_inspectorAdapter->engineClient()->setMethodBody(debugId, - methodName, methodBody); - } - - virtual void updateScriptBinding(DebugId debugId, - UiObjectMember *parentDefinition, - UiScriptBinding *scriptBinding, - const QString &propertyName, - const QString &scriptCode) - { - if (unsyncronizableChanges - == QmlLiveTextPreview::NoUnsyncronizableChanges) { - if (propertyName == QLatin1String("id")) { - unsyncronizableElementName = propertyName; - unsyncronizableChanges - = QmlLiveTextPreview::AttributeChangeWarning; - unsyncronizableChangeLine - = parentDefinition->firstSourceLocation().startLine; - unsyncronizableChangeColumn - = parentDefinition->firstSourceLocation().startColumn; - } - } - - QVariant expr = scriptCode; - const bool isLiteral = isLiteralValue(scriptBinding); - if (isLiteral) - expr = castToLiteral(scriptCode, scriptBinding); - appliedChangesToViewer = true; - if (m_inspectorAdapter->engineClient()) - m_inspectorAdapter->engineClient()->setBindingForObject( - debugId, propertyName, expr, - isLiteral, document()->fileName(), - scriptBinding->firstSourceLocation().startLine); - } - - virtual void resetBindingForObject(int debugId, const QString &propertyName) - { - appliedChangesToViewer = true; - if (m_inspectorAdapter->engineClient()) - m_inspectorAdapter->engineClient()->resetBindingForObject(debugId, propertyName); - } - - virtual void removeObject(int debugId) - { - appliedChangesToViewer = true; - if (m_inspectorAdapter->toolsClient()) - m_inspectorAdapter->toolsClient()->destroyQmlObject(debugId); - } - - virtual void createObject(const QString &qmlText, DebugId ref, - const QStringList &importList, - const QString &filename, - int order) - { - appliedChangesToViewer = true; - referenceRefreshRequired = true; - if (m_inspectorAdapter->toolsClient()) - m_inspectorAdapter->toolsClient()->createQmlObject(qmlText, ref, importList, filename, order); - } - - virtual void reparentObject(int debugId, int newParent) - { - appliedChangesToViewer = true; - if (m_inspectorAdapter->toolsClient()) - m_inspectorAdapter->toolsClient()->reparentQmlObject(debugId, newParent); - } - - void notifyUnsyncronizableElementChange(UiObjectMember *parent) - { - if (unsyncronizableChanges == QmlLiveTextPreview::NoUnsyncronizableChanges) { - UiObjectDefinition *parentDefinition = cast<UiObjectDefinition *>(parent); - if (parentDefinition && parentDefinition->qualifiedTypeNameId - && !parentDefinition->qualifiedTypeNameId->name.isEmpty()) - { - unsyncronizableElementName - = parentDefinition->qualifiedTypeNameId->name.toString(); - unsyncronizableChanges - = QmlLiveTextPreview::ElementChangeWarning; - unsyncronizableChangeLine - = parentDefinition->firstSourceLocation().startLine; - unsyncronizableChangeColumn - = parentDefinition->firstSourceLocation().startColumn; - } - } - } - -public: - UpdateInspector(QmlInspectorAdapter *inspectorAdapter) - : appliedChangesToViewer(false) - , referenceRefreshRequired(false) - , unsyncronizableChanges(QmlLiveTextPreview::NoUnsyncronizableChanges) - , m_inspectorAdapter(inspectorAdapter) - { - } - - bool appliedChangesToViewer; - bool referenceRefreshRequired; - QString unsyncronizableElementName; - QmlLiveTextPreview::UnsyncronizableChangeType unsyncronizableChanges; - unsigned unsyncronizableChangeLine; - unsigned unsyncronizableChangeColumn; - QmlInspectorAdapter *m_inspectorAdapter; - -}; - -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 Document::Ptr &doc, - const 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) - , m_changesUnsynchronizable(false) - , m_contentsChanged(false) -{ - QTC_CHECK(doc->fileName() == initDoc->fileName()); - - ModelManagerInterface *modelManager - = ModelManagerInterface::instance(); - if (modelManager) { - connect(modelManager, SIGNAL(documentChangedOnDisk(QmlJS::Document::Ptr)), - SLOT(documentChanged(QmlJS::Document::Ptr))); - } - connect(m_inspectorAdapter->agent(), SIGNAL(objectTreeUpdated()), - SLOT(updateDebugIds())); - connect(this, - SIGNAL(fetchObjectsForLocation(QString,int,int)), - m_inspectorAdapter->agent(), - SLOT(fetchContextObjectsForLocation(QString,int,int))); - connect(m_inspectorAdapter->agent(), SIGNAL(automaticUpdateFailed()), - SLOT(onAutomaticUpdateFailed())); -} - -QmlLiveTextPreview::~QmlLiveTextPreview() -{ - removeOutofSyncInfo(); -} - -void QmlLiveTextPreview::associateEditor(Core::IEditor *editor) -{ - QTC_ASSERT(editor, return); - using namespace TextEditor; - if (editor->document()->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) { - QTC_ASSERT(QLatin1String(editor->widget()->metaObject()->className()) == - QLatin1String("QmlJSEditor::Internal::QmlJSEditorWidget"), - return); - - TextEditorWidget *editWidget - = qobject_cast<TextEditorWidget*>(editor->widget()); - QTC_ASSERT(editWidget, return); - - if (!m_editors.contains(editWidget)) { - m_editors << editWidget; - if (m_inspectorAdapter) { - connect(editWidget, SIGNAL(textChanged()), SLOT(editorContentsChanged())); - connect(editWidget, - SIGNAL(selectedElementsChanged(QList<QmlJS::AST::UiObjectMember*>,QString)), - SLOT(changeSelectedElements(QList<QmlJS::AST::UiObjectMember*>,QString))); - } - } - } -} - -void QmlLiveTextPreview::unassociateEditor(Core::IEditor *oldEditor) -{ - using namespace TextEditor; - if (oldEditor && oldEditor->document()->id() - == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) { - TextEditorWidget *editWidget - = qobject_cast<TextEditorWidget*>(oldEditor->widget()); - QTC_ASSERT(editWidget, return); - - if (m_editors.contains(editWidget)) { - m_editors.removeOne(editWidget); - disconnect(editWidget, 0, this, 0); - } - } -} - -void QmlLiveTextPreview::resetInitialDoc(const Document::Ptr &doc) -{ - m_initialDoc = doc; - m_previousDoc = doc; - m_createdObjects.clear(); - m_debugIds.clear(); - m_docWithUnappliedChanges.clear(); - m_changesUnsynchronizable = false; - removeOutofSyncInfo(); -} - -const QString QmlLiveTextPreview::fileName() -{ - return m_previousDoc->fileName(); -} - -void QmlLiveTextPreview::setApplyChangesToQmlInspector(bool applyChanges) -{ - if (applyChanges && !m_applyChangesToQmlInspector) { - if (m_docWithUnappliedChanges) { - m_applyChangesToQmlInspector = true; - documentChanged(m_docWithUnappliedChanges); - } - } - - m_applyChangesToQmlInspector = applyChanges; -} - -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 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 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; - QHashIterator<int,QString> rIds(m_inspectorAdapter->agent()->rootObjectIds()); - QList<int> r; - while (rIds.hasNext()) { - rIds.next(); - if (rIds.value() == doc->componentName()) - r += rIds.key(); - } - 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 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(const QList<UiObjectMember*> offsetObjects, - const QString &wordAtCursor) -{ - if (m_editors.isEmpty() || !m_previousDoc) - return; - - QList<int> offsets; - foreach (UiObjectMember *member, offsetObjects) - offsets << member->firstSourceLocation().offset; - - if (!changeSelectedElements(offsets, wordAtCursor) && m_initialDoc && offsetObjects.count()) { - m_updateNodeForOffset = true; - emit fetchObjectsForLocation(m_initialDoc->fileName(), - offsetObjects.first()->firstSourceLocation().startLine, - offsetObjects.first()->firstSourceLocation().startColumn); - } -} - -bool QmlLiveTextPreview::changeSelectedElements(const QList<int> offsets, - const QString &wordAtCursor) -{ - m_updateNodeForOffset = false; - m_lastOffsets = offsets; - ObjectReference objectRefUnderCursor; - objectRefUnderCursor - = m_inspectorAdapter->agent()->objectForName(wordAtCursor); - - QList<int> selectedReferences; - bool containsReferenceUnderCursor = false; - - foreach (int offset, offsets) { - if (offset >= 0) { - QList<int> list = objectReferencesForOffset(offset); - - if (!containsReferenceUnderCursor - && objectRefUnderCursor.isValid()) { - 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.isValid()) { - selectedReferences << objectRefUnderCursor.debugId(); - } - - if (selectedReferences.isEmpty()) - return false; - emit selectedItemsChanged(selectedReferences); - return true; -} - -void QmlLiveTextPreview::documentChanged(Document::Ptr doc) -{ - if (doc->fileName() != m_previousDoc->fileName()) - return; - - // Changes to be applied when changes were made from the editor. - // m_contentsChanged ensures that the changes were made by the user in - // the editor before starting with the comparisons. - if (!m_contentsChanged) - return; - - if (m_applyChangesToQmlInspector) { - m_docWithUnappliedChanges.clear(); - - if (doc && m_previousDoc && doc->fileName() == m_previousDoc->fileName()) { - if (doc->fileName().endsWith(QLatin1String(".js"))) { - showSyncWarning(JSChangeWarning, QString(), 0, 0); - m_previousDoc = doc; - return; - } - if (doc->qmlProgram() && m_previousDoc->qmlProgram()) { - UpdateInspector delta(m_inspectorAdapter); - m_debugIds = delta(m_previousDoc, doc, m_debugIds); - - if (delta.referenceRefreshRequired) - m_inspectorAdapter->agent()->queryEngineContext(); - - - if (delta.unsyncronizableChanges != NoUnsyncronizableChanges) { - showSyncWarning(delta.unsyncronizableChanges, - delta.unsyncronizableElementName, - delta.unsyncronizableChangeLine, - delta.unsyncronizableChangeColumn); - m_previousDoc = doc; - return; - } - m_previousDoc = doc; - if (!delta.newObjects.isEmpty()) - m_createdObjects[doc] += delta.newObjects; - if (m_inspectorAdapter->toolsClient()) - m_inspectorAdapter->toolsClient()->clearComponentCache(); - } - } - } else { - m_docWithUnappliedChanges = doc; - } - m_contentsChanged = false; -} - -void QmlLiveTextPreview::editorContentsChanged() -{ - m_contentsChanged = true; -} - -void QmlLiveTextPreview::onAutomaticUpdateFailed() -{ - showSyncWarning(AutomaticUpdateFailed, QString(), UINT_MAX, UINT_MAX); -} - -QList<int> QmlLiveTextPreview::objectReferencesForOffset(quint32 offset) -{ - QList<int> result; - QHashIterator<UiObjectMember*, QList<int> > iter(m_debugIds); - UiObjectMember *possibleNode = 0; - while (iter.hasNext()) { - iter.next(); - 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 QmlLiveTextPreview::showSyncWarning( - UnsyncronizableChangeType unsyncronizableChangeType, - const QString &elementName, unsigned line, unsigned column) -{ - QString errorMessage; - switch (unsyncronizableChangeType) { - case AttributeChangeWarning: - errorMessage = tr("The %1 attribute at line %2, column %3 cannot be " - "changed without reloading the QML application. ") - .arg(elementName, QString::number(line), QString::number(column)); - break; - case ElementChangeWarning: - errorMessage = tr("The %1 element at line %2, column %3 cannot be " - "changed without reloading the QML application. ") - .arg(elementName, QString::number(line), QString::number(column)); - break; - case JSChangeWarning: - errorMessage = tr("The changes in JavaScript cannot be applied " - "without reloading the QML application. "); - break; - case AutomaticUpdateFailed: - errorMessage = tr("The changes made cannot be applied without " - "reloading the QML application. "); - break; - case QmlLiveTextPreview::NoUnsyncronizableChanges: - default: - return; - } - - m_changesUnsynchronizable = true; - errorMessage.append(tr("You can continue debugging, but behavior can be unexpected.")); - - // Clear infobars if present before showing the same. Otherwise multiple infobars - // will be shown in case the user changes and saves the file multiple times. - removeOutofSyncInfo(); - - foreach (TextEditor::TextEditorWidget *editor, m_editors) { - if (editor) { - Core::InfoBar *infoBar = editor->textDocument()->infoBar(); - Core::InfoBarEntry info(Core::Id(INFO_OUT_OF_SYNC), errorMessage); - BaseToolsClient *toolsClient = m_inspectorAdapter->toolsClient(); - if (toolsClient && toolsClient->supportReload()) - info.setCustomButtonInfo(tr("Reload QML"), [this]() { - removeOutofSyncInfo(); - emit reloadRequest(); - }); - infoBar->addInfo(info); - } - } -} - -void QmlLiveTextPreview::removeOutofSyncInfo() -{ - foreach (TextEditor::TextEditorWidget *editor, m_editors) { - if (editor) { - Core::InfoBar *infoBar = editor->textDocument()->infoBar(); - infoBar->removeInfo(Core::Id(INFO_OUT_OF_SYNC)); - } - } -} - -} // namespace Internal -} // namespace Debugger diff --git a/src/plugins/debugger/qml/qmllivetextpreview.h b/src/plugins/debugger/qml/qmllivetextpreview.h deleted file mode 100644 index 4102d79ac4..0000000000 --- a/src/plugins/debugger/qml/qmllivetextpreview.h +++ /dev/null @@ -1,121 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms and -** conditions see http://www.qt.io/terms-conditions. For further information -** use the contact form at http://www.qt.io/contact-us. -** -** 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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef QMLLIVETEXTPREVIEW_H -#define QMLLIVETEXTPREVIEW_H - -#include <texteditor/texteditor.h> -#include <qmljs/qmljsdocument.h> - -namespace Core { class IEditor; } - -namespace QmlJS { class ModelManagerInterface; } - -namespace Debugger { -namespace Internal { - -class UpdateInspector; -class QmlInspectorAdapter; - -class QmlLiveTextPreview : public QObject -{ - Q_OBJECT - -public: - QmlLiveTextPreview(const QmlJS::Document::Ptr &doc, - const QmlJS::Document::Ptr &initDoc, - QmlInspectorAdapter *inspectorAdapter, - QObject *parent = 0); - ~QmlLiveTextPreview(); - - void associateEditor(Core::IEditor *editor); - void unassociateEditor(Core::IEditor *editor); - void resetInitialDoc(const QmlJS::Document::Ptr &doc); - const QString fileName(); - bool hasUnsynchronizableChange() { return m_changesUnsynchronizable; } - -signals: - void selectedItemsChanged(const QList<int> &debugIds); - void fetchObjectsForLocation(const QString &file, - int lineNumber, int columnNumber); - void reloadRequest(); - -public slots: - void setApplyChangesToQmlInspector(bool applyChanges); - void updateDebugIds(); - -private slots: - void changeSelectedElements(const QList<QmlJS::AST::UiObjectMember *> offsets, - const QString &wordAtCursor); - void documentChanged(QmlJS::Document::Ptr doc); - void editorContentsChanged(); - void onAutomaticUpdateFailed(); - -private: - enum UnsyncronizableChangeType { - NoUnsyncronizableChanges, - AttributeChangeWarning, - ElementChangeWarning, - JSChangeWarning, - AutomaticUpdateFailed - }; - - bool changeSelectedElements(const QList<int> offsets, const QString &wordAtCursor); - QList<int> objectReferencesForOffset(quint32 offset); - void showSyncWarning(UnsyncronizableChangeType unsyncronizableChangeType, - const QString &elementName, - unsigned line, unsigned column); - void removeOutofSyncInfo(); - -private: - QHash<QmlJS::AST::UiObjectMember*, QList<int> > m_debugIds; - QHash<QmlJS::Document::Ptr, QSet<QmlJS::AST::UiObjectMember *> > m_createdObjects; - - QmlJS::Document::Ptr m_previousDoc; - QmlJS::Document::Ptr m_initialDoc; //the document that was loaded by the server - - QList<QPointer<TextEditor::TextEditorWidget> > m_editors; - - bool m_applyChangesToQmlInspector; - QmlJS::Document::Ptr m_docWithUnappliedChanges; - QmlInspectorAdapter *m_inspectorAdapter; - QList<int> m_lastOffsets; - QmlJS::AST::UiObjectMember *m_nodeForOffset; - bool m_updateNodeForOffset; - bool m_changesUnsynchronizable; - bool m_contentsChanged; - - friend class UpdateInspector; -}; - -} // namespace Internal -} // namespace Debugger - -#endif // QMLLIVETEXTPREVIEW_H |