Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
Q
qt-creator
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Tobias Hunger
qt-creator
Commits
de59fe3f
"git@git.qt.io:tohunger/qt-creator.git" did not exist on "f8db7aca18fda294eae40df4ff5ba407a942f94e"
Commit
de59fe3f
authored
14 years ago
by
hjk
Browse files
Options
Downloads
Patches
Plain Diff
debugger: work on the qmlengine
parent
d0c2e11a
No related branches found
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
src/plugins/debugger/qml/qmlengine.cpp
+989
-16
989 additions, 16 deletions
src/plugins/debugger/qml/qmlengine.cpp
src/plugins/debugger/qml/qmlengine.h
+85
-1
85 additions, 1 deletion
src/plugins/debugger/qml/qmlengine.h
with
1074 additions
and
17 deletions
src/plugins/debugger/qml/qmlengine.cpp
+
989
−
16
View file @
de59fe3f
...
...
@@ -161,10 +161,27 @@ QmlEngine::QmlEngine(const DebuggerStartParameters &startParameters)
{
m_conn
=
0
;
m_client
=
0
;
m_engineQuery
=
0
;
m_contextQuery
=
0
;
m_engineDebugInterface
=
0
;
m_frameRate
=
0
;
/*
m_watchTableModel = new Internal::WatchTableModel(0, this);
m_objectTreeWidget = new Internal::ObjectTree;
m_propertiesWidget = new Internal::ObjectPropertiesView(m_watchTableModel);
m_watchTableView = new Internal::WatchTableView(m_watchTableModel);
m_expressionWidget = new Internal::ExpressionQueryWidget(Internal::ExpressionQueryWidget::SeparateEntryMode);
// m_frameRateWidget = new Internal::CanvasFrameRate;
// m_frameRateWidget->setObjectName(QLatin1String("QmlDebugFrameRate"));
connect(Debugger::DebuggerPlugin::instance(),
SIGNAL(stateChanged(int)), this, SLOT(debuggerStateChanged(int)));
m_editablePropertyTypes = QStringList() << "qreal" << "bool" << "QString"
<< "int" << "QVariant" << "QUrl" << "QColor";
connect(m_connectionTimer, SIGNAL(timeout()), SLOT(pollInspector()));
*/
}
QmlEngine
::~
QmlEngine
()
...
...
@@ -189,6 +206,10 @@ void QmlEngine::executeDebuggerCommand(const QString &command)
void
QmlEngine
::
shutdown
()
{
exitDebugger
();
//m_objectTreeWidget->saveSettings(m_settings);
//m_propertiesWidget->saveSettings(m_settings);
//m_settings.saveSettings(Core::ICore::instance()->settings());
}
void
QmlEngine
::
exitDebugger
()
...
...
@@ -254,14 +275,16 @@ void QmlEngine::setupConnection()
m_client
=
new
QmlDebuggerClient
(
m_conn
,
this
);
(
void
)
new
QmlFrameRateClient
(
m_conn
,
this
);
//m_objectTreeWidget->setEngineDebug(m_client);
//m_propertiesWidget->setEngineDebug(m_client);
//m_watchTableModel->setEngineDebug(m_client);
//m_expressionWidget->setEngineDebug(m_client);
// resetViews();
// m_frameRateWidget->reset(m_conn);
// reloadEngines();
QTC_ASSERT
(
m_engineDebugInterface
==
0
,
/**/
);
m_engineDebugInterface
=
new
QDeclarativeEngineDebug
(
m_conn
,
this
);
//m_objectTreeWidget->setEngineDebug(m_engineDebugInterface);
//m_propertiesWidget->setEngineDebug(m_engineDebugInterface);
//m_watchTableModel->setEngineDebug(m_engineDebugInterface);
//m_expressionWidget->setEngineDebug(m_engineDebugInterface);
//resetViews();
//m_frameRateWidget->reset(m_conn);
QHostAddress
ha
(
QHostAddress
::
LocalHost
);
...
...
@@ -278,6 +301,8 @@ void QmlEngine::setupConnection()
qDebug
()
<<
"CONNECTION SUCCESSFUL"
;
setState
(
InferiorRunning
);
startSuccessful
();
reloadEngines
();
}
void
QmlEngine
::
continueInferior
()
...
...
@@ -462,10 +487,12 @@ void QmlEngine::assignValueInDebugger(const QString &expression,
void
QmlEngine
::
updateLocals
()
{
qDebug
()
<<
"UPDATE LOCALS"
;
}
void
QmlEngine
::
updateWatchData
(
const
WatchData
&
data
)
{
qDebug
()
<<
"UPDATE WATCH DATA"
<<
data
.
toString
();
//watchHandler()->rebuildModel();
showStatusMessage
(
tr
(
"Stopped."
),
5000
);
...
...
@@ -624,6 +651,14 @@ void QmlEngine::messageReceived(const QByteArray &message)
watchHandler
()
->
endCycle
();
foreach
(
QDeclarativeDebugWatch
*
watch
,
m_watches
)
{
qDebug
()
<<
"WATCH"
<<
watch
->
objectName
()
<<
watch
->
queryId
()
<<
watch
->
state
()
<<
watch
->
objectDebugId
();
}
}
else
if
(
command
==
"RESULT"
)
{
WatchData
data
;
QVariant
variant
;
...
...
@@ -710,12 +745,6 @@ void QmlEngine::connectionStateChanged()
case
QAbstractSocket
::
UnconnectedState
:
{
showStatusMessage
(
tr
(
"[QmlEngine] disconnected.
\n\n
"
));
delete
m_engineQuery
;
m_engineQuery
=
0
;
delete
m_contextQuery
;
m_contextQuery
=
0
;
// resetViews();
// updateMenuActions();
...
...
@@ -762,6 +791,950 @@ void QmlEngine::connectionConnected()
}
#if 0
class EngineComboBox : public QComboBox
{
Q_OBJECT
public:
struct EngineInfo
{
QString name;
int id;
};
EngineComboBox(QWidget *parent = 0);
void addEngine(int engine, const QString &name);
void clearEngines();
protected:
private:
QList<EngineInfo> m_engines;
};
EngineComboBox::EngineComboBox(QWidget *parent)
: QComboBox(parent)
{
setEnabled(false);
setEditable(false);
}
void EngineComboBox::addEngine(int engine, const QString &name)
{
EngineInfo info;
info.id = engine;
if (name.isEmpty())
info.name = tr("Engine %1", "engine number").arg(engine);
else
info.name = name;
m_engines << info;
addItem(info.name);
}
void EngineComboBox::clearEngines()
{
m_engines.clear();
clear();
}
} // Internal
bool QmlEngine::setDebugConfigurationDataFromProject(ProjectExplorer::Project *projectToDebug)
{
if (!projectToDebug) {
emit statusMessage(tr("Invalid project, debugging canceled."));
return false;
}
QmlProjectManager::QmlProjectRunConfiguration* config =
qobject_cast<QmlProjectManager::QmlProjectRunConfiguration*>(projectToDebug->activeTarget()->activeRunConfiguration());
if (!config) {
emit statusMessage(tr("Cannot find project run configuration, debugging canceled."));
return false;
}
m_runConfigurationDebugData.serverAddress = config->debugServerAddress();
m_runConfigurationDebugData.serverPort = config->debugServerPort();
m_connectionTimer->setInterval(ConnectionAttemptDefaultInterval);
return true;
}
void QmlEngine::startQmlProjectDebugger()
{
m_simultaneousCppAndQmlDebugMode = false;
m_connectionTimer->start();
}
bool QmlEngine::connectToViewer()
{
if (m_conn && m_conn->state() != QAbstractSocket::UnconnectedState)
return false;
delete m_engineDebugInterface; m_engineDebugInterface = 0;
if (m_conn) {
m_conn->disconnectFromHost();
delete m_conn;
m_conn = 0;
}
QString host = m_runConfigurationDebugData.serverAddress;
quint16 port = quint16(m_runConfigurationDebugData.serverPort);
m_conn = new QDeclarativeDebugConnection(this);
connect(m_conn, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
SLOT(connectionStateChanged()));
connect(m_conn, SIGNAL(error(QAbstractSocket::SocketError)),
SLOT(connectionError()));
emit statusMessage(tr("[Inspector] set to connect to debug server %1:%2").arg(host).arg(port));
m_conn->connectToHost(host, port);
// blocks until connected; if no connection is available, will fail immediately
if (!m_conn->waitForConnected())
return false;
QTC_ASSERT(m_debuggerRunControl, return false);
QmlEngine *engine = qobject_cast<QmlEngine *>(m_debuggerRunControl->engine());
QTC_ASSERT(engine, return false);
(void) new DebuggerClient(m_conn, engine);
return true;
}
void QmlEngine::disconnectFromViewer()
{
m_conn->disconnectFromHost();
updateMenuActions();
}
void QmlEngine::connectionStateChanged()
{
switch (m_conn->state()) {
case QAbstractSocket::UnconnectedState:
{
emit statusMessage(tr("[Inspector] disconnected.\n\n"));
resetViews();
updateMenuActions();
break;
}
case QAbstractSocket::HostLookupState:
emit statusMessage(tr("[Inspector] resolving host..."));
break;
case QAbstractSocket::ConnectingState:
emit statusMessage(tr("[Inspector] connecting to debug server..."));
break;
case QAbstractSocket::ConnectedState:
{
emit statusMessage(tr("[Inspector] connected.\n"));
resetViews();
// m_frameRateWidget->reset(m_conn);
break;
}
case QAbstractSocket::ClosingState:
emit statusMessage(tr("[Inspector] closing..."));
break;
case QAbstractSocket::BoundState:
case QAbstractSocket::ListeningState:
break;
}
}
void QmlEngine::resetViews()
{
m_objectTreeWidget->cleanup();
m_propertiesWidget->clear();
m_expressionWidget->clear();
m_watchTableModel->removeAllWatches();
}
void QmlEngine::createDockWidgets()
{
m_engineComboBox = new Internal::EngineComboBox;
m_engineComboBox->setEnabled(false);
connect(m_engineComboBox, SIGNAL(currentIndexChanged(int)),
SLOT(queryEngineContext(int)));
// FancyMainWindow uses widgets' window titles for tab labels
// m_frameRateWidget->setWindowTitle(tr("Frame rate"));
Utils::StyledBar *treeOptionBar = new Utils::StyledBar;
QHBoxLayout *treeOptionBarLayout = new QHBoxLayout(treeOptionBar);
treeOptionBarLayout->setContentsMargins(5, 0, 5, 0);
treeOptionBarLayout->setSpacing(5);
treeOptionBarLayout->addWidget(new QLabel(tr("QML engine:")));
treeOptionBarLayout->addWidget(m_engineComboBox);
QWidget *treeWindow = new QWidget;
treeWindow->setObjectName(QLatin1String("QmlDebugTree"));
treeWindow->setWindowTitle(tr("Object Tree"));
QVBoxLayout *treeWindowLayout = new QVBoxLayout(treeWindow);
treeWindowLayout->setMargin(0);
treeWindowLayout->setSpacing(0);
treeWindowLayout->setContentsMargins(0,0,0,0);
treeWindowLayout->addWidget(treeOptionBar);
treeWindowLayout->addWidget(m_objectTreeWidget);
m_watchTableView->setModel(m_watchTableModel);
Internal::WatchTableHeaderView *header = new Internal::WatchTableHeaderView(m_watchTableModel);
m_watchTableView->setHorizontalHeader(header);
connect(m_objectTreeWidget, SIGNAL(activated(QDeclarativeDebugObjectReference)),
this, SLOT(treeObjectActivated(QDeclarativeDebugObjectReference)));
connect(m_objectTreeWidget, SIGNAL(currentObjectChanged(QDeclarativeDebugObjectReference)),
m_propertiesWidget, SLOT(reload(QDeclarativeDebugObjectReference)));
connect(m_objectTreeWidget, SIGNAL(expressionWatchRequested(QDeclarativeDebugObjectReference,QString)),
m_watchTableModel, SLOT(expressionWatchRequested(QDeclarativeDebugObjectReference,QString)));
connect(m_propertiesWidget, SIGNAL(watchToggleRequested(QDeclarativeDebugObjectReference,QDeclarativeDebugPropertyReference)),
m_watchTableModel, SLOT(togglePropertyWatch(QDeclarativeDebugObjectReference,QDeclarativeDebugPropertyReference)));
connect(m_watchTableModel, SIGNAL(watchCreated(QDeclarativeDebugWatch*)),
m_propertiesWidget, SLOT(watchCreated(QDeclarativeDebugWatch*)));
connect(m_watchTableModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
m_watchTableView, SLOT(scrollToBottom()));
connect(m_watchTableView, SIGNAL(objectActivated(int)),
m_objectTreeWidget, SLOT(setCurrentObject(int)));
connect(m_objectTreeWidget, SIGNAL(currentObjectChanged(QDeclarativeDebugObjectReference)),
m_expressionWidget, SLOT(setCurrentObject(QDeclarativeDebugObjectReference)));
Core::MiniSplitter *propSplitter = new Core::MiniSplitter(Qt::Horizontal);
Core::MiniSplitter *propWatcherSplitter = new Core::MiniSplitter(Qt::Vertical);
propWatcherSplitter->addWidget(m_propertiesWidget);
propWatcherSplitter->addWidget(m_watchTableView);
propWatcherSplitter->setStretchFactor(0, 2);
propWatcherSplitter->setStretchFactor(1, 1);
propWatcherSplitter->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding);
propSplitter->setWindowTitle(tr("Properties and Watchers"));
propSplitter->setObjectName(QLatin1String("QmlDebugProperties"));
propSplitter->addWidget(m_objectTreeWidget);
propSplitter->addWidget(propWatcherSplitter);
propSplitter->setStretchFactor(0, 1);
propSplitter->setStretchFactor(1, 3);
InspectorOutputWidget *inspectorOutput = new InspectorOutputWidget();
inspectorOutput->setObjectName(QLatin1String("QmlDebugInspectorOutput"));
connect(this, SIGNAL(statusMessage(QString)),
inspectorOutput, SLOT(addInspectorStatus(QString)));
Debugger::DebuggerUISwitcher *uiSwitcher = Debugger::DebuggerUISwitcher::instance();
m_watchTableView->hide();
// m_objectTreeDock = uiSwitcher->createDockWidget(Qml::Constants::LANG_QML,
// treeWindow, Qt::BottomDockWidgetArea);
// m_frameRateDock = uiSwitcher->createDockWidget(Qml::Constants::LANG_QML,
// m_frameRateWidget, Qt::BottomDockWidgetArea);
m_propertyWatcherDock = uiSwitcher->createDockWidget(Qml::Constants::LANG_QML,
propSplitter, Qt::BottomDockWidgetArea);
m_inspectorOutputDock = uiSwitcher->createDockWidget(Qml::Constants::LANG_QML,
inspectorOutput, Qt::BottomDockWidgetArea);
m_expressionWidget->setWindowTitle(tr("Script Console"));
m_expressionQueryDock = uiSwitcher->createDockWidget(Qml::Constants::LANG_QML,
m_expressionWidget, Qt::BottomDockWidgetArea);
m_inspectorOutputDock->setToolTip(tr("Output of the QML inspector, such as information on connecting to the server."));
m_dockWidgets << /*m_objectTreeDock << *//*m_frameRateDock << */ m_propertyWatcherDock
<< m_inspectorOutputDock << m_expressionQueryDock;
m_context = new Internal::InspectorContext(m_objectTreeWidget);
m_propWatcherContext = new Internal::InspectorContext(m_propertyWatcherDock);
Core::ICore *core = Core::ICore::instance();
core->addContextObject(m_propWatcherContext);
core->addContextObject(m_context);
m_simultaneousDebugAction = new QAction(this);
m_simultaneousDebugAction->setText(tr("Start Debugging C++ and QML Simultaneously..."));
connect(m_simultaneousDebugAction, SIGNAL(triggered()),
this, SLOT(simultaneouslyDebugQmlCppApplication()));
Core::ActionManager *am = core->actionManager();
Core::ActionContainer *mstart = am->actionContainer(ProjectExplorer::Constants::M_DEBUG_STARTDEBUGGING);
Core::Command *cmd = am->registerAction(m_simultaneousDebugAction, Constants::M_DEBUG_SIMULTANEOUSLY,
m_context->context());
cmd->setAttribute(Core::Command::CA_Hide);
mstart->addAction(cmd, Core::Constants::G_DEFAULT_ONE);
m_settings.readSettings(core->settings());
m_objectTreeWidget->readSettings(m_settings);
m_propertiesWidget->readSettings(m_settings);
connect(m_objectTreeWidget, SIGNAL(contextHelpIdChanged(QString)), m_context,
SLOT(setContextHelpId(QString)));
connect(m_watchTableView, SIGNAL(contextHelpIdChanged(QString)), m_propWatcherContext,
SLOT(setContextHelpId(QString)));
connect(m_propertiesWidget, SIGNAL(contextHelpIdChanged(QString)), m_propWatcherContext,
SLOT(setContextHelpId(QString)));
connect(m_expressionWidget, SIGNAL(contextHelpIdChanged(QString)), m_propWatcherContext,
SLOT(setContextHelpId(QString)));
}
void QmlEngine::simultaneouslyDebugQmlCppApplication()
{
QString errorMessage;
ProjectExplorer::ProjectExplorerPlugin *pex = ProjectExplorer::ProjectExplorerPlugin::instance();
ProjectExplorer::Project *project = pex->startupProject();
if (!project)
errorMessage = QString(tr("No project was found."));
else {
if (project->id() == "QmlProjectManager.QmlProject")
errorMessage = attachToQmlViewerAsExternalApp(project);
else {
errorMessage = attachToExternalCppAppWithQml(project);
}
}
if (!errorMessage.isEmpty())
QMessageBox::warning(Core::ICore::instance()->mainWindow(), "Failed to debug C++ and QML", errorMessage);
}
QString QmlEngine::attachToQmlViewerAsExternalApp(ProjectExplorer::Project *project)
{
m_debugMode = QmlProjectWithCppPlugins;
QmlProjectManager::QmlProjectRunConfiguration* runConfig =
qobject_cast<QmlProjectManager::QmlProjectRunConfiguration*>(project->activeTarget()->activeRunConfiguration());
if (!runConfig)
return QString(tr("No run configurations were found for the project '%1'.").arg(project->displayName()));
Internal::StartExternalQmlDialog dlg(Debugger::DebuggerUISwitcher::instance()->mainWindow());
QString importPathArgument = "-I";
QString execArgs;
if (runConfig->viewerArguments().contains(importPathArgument))
execArgs = runConfig->viewerArguments().join(" ");
else {
QFileInfo qmlFileInfo(runConfig->viewerArguments().last());
importPathArgument.append(" " + qmlFileInfo.absolutePath() + " ");
execArgs = importPathArgument + runConfig->viewerArguments().join(" ");
}
dlg.setPort(runConfig->debugServerPort());
dlg.setDebuggerUrl(runConfig->debugServerAddress());
dlg.setProjectDisplayName(project->displayName());
dlg.setDebugMode(Internal::StartExternalQmlDialog::QmlProjectWithCppPlugins);
dlg.setQmlViewerArguments(execArgs);
dlg.setQmlViewerPath(runConfig->viewerPath());
if (dlg.exec() != QDialog::Accepted)
return QString();
m_runConfigurationDebugData.serverAddress = dlg.debuggerUrl();
m_runConfigurationDebugData.serverPort = dlg.port();
m_settings.setExternalPort(dlg.port());
m_settings.setExternalUrl(dlg.debuggerUrl());
ProjectExplorer::Environment customEnv = ProjectExplorer::Environment::systemEnvironment(); // empty env by default
customEnv.set(QmlProjectManager::Constants::E_QML_DEBUG_SERVER_PORT, QString::number(m_settings.externalPort()));
Debugger::DebuggerRunControl *debuggableRunControl =
createDebuggerRunControl(runConfig, dlg.qmlViewerPath(), dlg.qmlViewerArguments());
return executeDebuggerRunControl(debuggableRunControl, &customEnv);
}
QString QmlEngine::attachToExternalCppAppWithQml(ProjectExplorer::Project *project)
{
m_debugMode = CppProjectWithQmlEngines;
ProjectExplorer::LocalApplicationRunConfiguration* runConfig =
qobject_cast<ProjectExplorer::LocalApplicationRunConfiguration*>(project->activeTarget()->activeRunConfiguration());
if (!project->activeTarget() || !project->activeTarget()->activeRunConfiguration())
return QString(tr("No run configurations were found for the project '%1'.").arg(project->displayName()));
else if (!runConfig)
return QString(tr("No valid run configuration was found for the project %1. "
"Only locally runnable configurations are supported.\n"
"Please check your project settings.").arg(project->displayName()));
Internal::StartExternalQmlDialog dlg(Debugger::DebuggerUISwitcher::instance()->mainWindow());
dlg.setPort(m_settings.externalPort());
dlg.setDebuggerUrl(m_settings.externalUrl());
dlg.setProjectDisplayName(project->displayName());
dlg.setDebugMode(Internal::StartExternalQmlDialog::CppProjectWithQmlEngine);
if (dlg.exec() != QDialog::Accepted)
return QString();
m_runConfigurationDebugData.serverAddress = dlg.debuggerUrl();
m_runConfigurationDebugData.serverPort = dlg.port();
m_settings.setExternalPort(dlg.port());
m_settings.setExternalUrl(dlg.debuggerUrl());
ProjectExplorer::Environment customEnv = runConfig->environment();
customEnv.set(QmlProjectManager::Constants::E_QML_DEBUG_SERVER_PORT, QString::number(m_settings.externalPort()));
Debugger::DebuggerRunControl *debuggableRunControl = createDebuggerRunControl(runConfig);
return executeDebuggerRunControl(debuggableRunControl, &customEnv);
}
QString QmlEngine::executeDebuggerRunControl(Debugger::DebuggerRunControl *debuggableRunControl, ProjectExplorer::Environment *environment)
{
ProjectExplorer::ProjectExplorerPlugin *pex = ProjectExplorer::ProjectExplorerPlugin::instance();
// to make sure we have a valid, debuggable run control, find the correct factory for it
if (debuggableRunControl) {
// modify the env
debuggableRunControl->setCustomEnvironment(*environment);
pex->startRunControl(debuggableRunControl, ProjectExplorer::Constants::DEBUGMODE);
m_simultaneousCppAndQmlDebugMode = true;
return QString();
}
return QString(tr("A valid run control was not registered in Qt Creator for this project run configuration."));;
}
Debugger::DebuggerRunControl *QmlEngine::createDebuggerRunControl(ProjectExplorer::RunConfiguration *runConfig,
const QString &executableFile, const QString &executableArguments)
{
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
const QList<Debugger::DebuggerRunControlFactory *> factories = pm->getObjects<Debugger::DebuggerRunControlFactory>();
ProjectExplorer::RunControl *runControl = 0;
if (m_debugMode == QmlProjectWithCppPlugins) {
Debugger::DebuggerStartParameters sp;
sp.startMode = Debugger::StartExternal;
sp.executable = executableFile;
sp.processArgs = executableArguments.split(QLatin1Char(' '));
runControl = factories.first()->create(sp);
return qobject_cast<Debugger::DebuggerRunControl *>(runControl);
}
if (m_debugMode == CppProjectWithQmlEngines) {
if (factories.length() && factories.first()->canRun(runConfig, ProjectExplorer::Constants::DEBUGMODE)) {
runControl = factories.first()->create(runConfig, ProjectExplorer::Constants::DEBUGMODE);
return qobject_cast<Debugger::DebuggerRunControl *>(runControl);
}
}
return 0;
}
void QmlEngine::updateMenuActions()
{
bool enabled = true;
if (m_simultaneousCppAndQmlDebugMode)
enabled = (m_cppDebuggerState == Debugger::DebuggerNotReady && (!m_conn || m_conn->state() == QAbstractSocket::UnconnectedState));
else
enabled = (!m_conn || m_conn->state() == QAbstractSocket::UnconnectedState);
m_simultaneousDebugAction->setEnabled(enabled);
}
void QmlEngine::debuggerStateChanged(int newState)
{
if (m_simultaneousCppAndQmlDebugMode) {
switch(newState) {
case Debugger::EngineStarting:
{
m_connectionInitialized = false;
break;
}
case Debugger::AdapterStartFailed:
case Debugger::InferiorStartFailed:
emit statusMessage(QString(tr("Debugging failed: could not start C++ debugger.")));
break;
case Debugger::InferiorRunningRequested:
{
if (m_cppDebuggerState == Debugger::InferiorStopped) {
// re-enable UI again
m_objectTreeWidget->setEnabled(true);
m_propertiesWidget->setEnabled(true);
m_expressionWidget->setEnabled(true);
}
break;
}
case Debugger::InferiorRunning:
{
if (!m_connectionInitialized) {
m_connectionInitialized = true;
m_connectionTimer->setInterval(ConnectionAttemptSimultaneousInterval);
m_connectionTimer->start();
}
break;
}
case Debugger::InferiorStopped:
{
m_objectTreeWidget->setEnabled(false);
m_propertiesWidget->setEnabled(false);
m_expressionWidget->setEnabled(false);
break;
}
case Debugger::EngineShuttingDown:
{
m_connectionInitialized = false;
// here it's safe to enable the debugger windows again -
// disabled ones look ugly.
m_objectTreeWidget->setEnabled(true);
m_propertiesWidget->setEnabled(true);
m_expressionWidget->setEnabled(true);
m_simultaneousCppAndQmlDebugMode = false;
break;
}
default:
break;
}
}
m_cppDebuggerState = newState;
updateMenuActions();
}
void QmlEngine::setSimpleDockWidgetArrangement()
{
Utils::FancyMainWindow *mainWindow = Debugger::DebuggerUISwitcher::instance()->mainWindow();
mainWindow->setTrackingEnabled(false);
QList<QDockWidget *> dockWidgets = mainWindow->dockWidgets();
foreach (QDockWidget *dockWidget, dockWidgets) {
if (m_dockWidgets.contains(dockWidget)) {
dockWidget->setFloating(false);
mainWindow->removeDockWidget(dockWidget);
}
}
foreach (QDockWidget *dockWidget, dockWidgets) {
if (m_dockWidgets.contains(dockWidget)) {
mainWindow->addDockWidget(Qt::BottomDockWidgetArea, dockWidget);
dockWidget->show();
}
}
mainWindow->splitDockWidget(mainWindow->toolBarDockWidget(), m_propertyWatcherDock, Qt::Vertical);
//mainWindow->tabifyDockWidget(m_frameRateDock, m_propertyWatcherDock);
mainWindow->tabifyDockWidget(m_propertyWatcherDock, m_expressionQueryDock);
mainWindow->tabifyDockWidget(m_propertyWatcherDock, m_inspectorOutputDock);
m_propertyWatcherDock->raise();
m_inspectorOutputDock->setVisible(false);
mainWindow->setTrackingEnabled(true);
}
#endif
void
QmlEngine
::
reloadEngines
()
{
//m_engineComboBox->setEnabled(false);
QDeclarativeDebugEnginesQuery
*
query
=
m_engineDebugInterface
->
queryAvailableEngines
(
this
);
if
(
!
query
->
isWaiting
())
enginesChanged
(
query
);
else
QObject
::
connect
(
query
,
SIGNAL
(
stateChanged
(
QDeclarativeDebugQuery
::
State
)),
this
,
SLOT
(
enginesChanged
()));
}
void
QmlEngine
::
enginesChanged
()
{
enginesChanged
(
qobject_cast
<
QDeclarativeDebugEnginesQuery
*>
(
sender
()));
}
void
QmlEngine
::
enginesChanged
(
QDeclarativeDebugEnginesQuery
*
query
)
{
//m_engineComboBox->clearEngines();
QList
<
QDeclarativeDebugEngineReference
>
engines
=
query
->
engines
();
if
(
engines
.
isEmpty
())
qWarning
(
"qmldebugger: no engines found!"
);
//m_engineComboBox->setEnabled(true);
for
(
int
i
=
0
;
i
<
engines
.
count
();
++
i
)
qDebug
()
<<
"ENGINE: "
<<
engines
.
at
(
i
).
debugId
()
<<
engines
.
at
(
i
).
name
();
// m_engineComboBox->addEngine(engines.at(i).debugId(), engines.at(i).name());
if
(
engines
.
count
()
>
0
)
{
// m_engineComboBox->setCurrentIndex(engines.at(0).debugId());
queryEngineContext
(
engines
.
at
(
0
));
}
}
void
QmlEngine
::
queryEngineContext
(
const
QDeclarativeDebugEngineReference
&
engine
)
{
QDeclarativeDebugRootContextQuery
*
query
=
m_engineDebugInterface
->
queryRootContexts
(
engine
,
this
);
if
(
!
query
->
isWaiting
())
contextChanged
();
else
QObject
::
connect
(
query
,
SIGNAL
(
stateChanged
(
QDeclarativeDebugQuery
::
State
)),
this
,
SLOT
(
contextChanged
()));
}
void
QmlEngine
::
contextChanged
()
{
contextChanged
(
qobject_cast
<
QDeclarativeDebugRootContextQuery
*>
(
sender
()));
}
void
QmlEngine
::
contextChanged
(
QDeclarativeDebugRootContextQuery
*
query
)
{
QTC_ASSERT
(
query
,
return
);
//dump(query->rootContext(), 0);
foreach
(
const
QDeclarativeDebugObjectReference
&
object
,
query
->
rootContext
().
objects
())
reloadObject
(
object
);
}
void
QmlEngine
::
reloadObject
(
const
QDeclarativeDebugObjectReference
&
object
)
{
qDebug
()
<<
"RELOAD OBJECT: "
<<
object
.
debugId
()
<<
object
.
idString
()
<<
object
.
className
();
QDeclarativeDebugObjectQuery
*
query
=
m_engineDebugInterface
->
queryObjectRecursive
(
object
,
this
);
if
(
!
query
->
isWaiting
())
objectFetched
(
query
,
QDeclarativeDebugQuery
::
Completed
);
else
QObject
::
connect
(
query
,
SIGNAL
(
stateChanged
(
QDeclarativeDebugQuery
::
State
)),
this
,
SLOT
(
objectFetched
(
QDeclarativeDebugQuery
::
State
)));
}
void
QmlEngine
::
objectFetched
(
QDeclarativeDebugQuery
::
State
state
)
{
objectFetched
(
qobject_cast
<
QDeclarativeDebugObjectQuery
*>
(
sender
()),
state
);
}
void
QmlEngine
::
objectFetched
(
QDeclarativeDebugObjectQuery
*
query
,
QDeclarativeDebugQuery
::
State
state
)
{
QTC_ASSERT
(
query
,
return
);
QTC_ASSERT
(
state
==
QDeclarativeDebugQuery
::
Completed
,
return
);
//dump(m_query->object(), 0);
m_watches
.
clear
();
buildTree
(
query
->
object
(),
"local"
);
qDebug
()
<<
"WATCHES CREATED: "
<<
m_watches
.
size
();
//watchHandler()->beginCycle();
//watchHandler()->insertBulkData(list);
//watchHandler()->endCycle();
//setCurrentItem(topLevelItem(0));
// this ugly hack is needed if user wants to see internal structs
// on startup - debugger does not load them until towards the end,
// so essentially loading twice gives us the full list as everything
// is already loaded.
//if (m_showUninspectableItems && !m_showUninspectableOnInitDone) {
// m_showUninspectableOnInitDone = true;
// reloadObject(m_currentObjectDebugId);
//}
}
void
QmlEngine
::
buildTree
(
const
QDeclarativeDebugObjectReference
&
obj
,
const
QByteArray
&
iname
)
{
//QTC_ASSERT(obj.contextDebugId() >= 0, return);
WatchData
data
;
data
.
iname
=
iname
;
if
(
obj
.
idString
().
isEmpty
())
data
.
name
=
QString
(
"<%1>"
).
arg
(
obj
.
className
());
else
data
.
name
=
obj
.
idString
();
data
.
value
=
"?"
;
data
.
type
=
"?"
;
data
.
setHasChildren
(
!
obj
.
children
().
isEmpty
());
data
.
setAllUnneeded
();
qDebug
()
<<
"CREATED ITEM "
<<
data
.
iname
<<
data
.
name
;
m_watches
.
append
(
m_engineDebugInterface
->
addWatch
(
obj
,
data
.
name
,
0
));
//QDeclarativeDebugPropertyWatch *QDeclarativeEngineDebug::addWatch(const QDeclarativeDebugPropertyReference &property, QObject *parent)
//data.userRole = qVariantFromValue(obj);
/*
if (parent && obj.contextDebugId() >= 0
&& obj.contextDebugId() != parent->data(0, Qt::UserRole
).value<QDeclarativeDebugObjectReference>().contextDebugId())
{
QDeclarativeDebugFileReference source = obj.source();
if (!source.url().isEmpty()) {
QString toolTipString = QLatin1String("URL: ") + source.url().toString();
item->setToolTip(0, toolTipString);
}
} else {
item->setExpanded(true);
}
if (obj.contextDebugId() < 0)
item->setHasValidDebugId(false);
*/
for
(
int
i
=
0
;
i
<
obj
.
children
().
size
();
++
i
)
buildTree
(
obj
.
children
().
at
(
i
),
iname
+
'.'
+
QByteArray
::
number
(
i
));
}
#if 0
void QmlEngine::treeObjectActivated(const QDeclarativeDebugObjectReference &obj)
{
QDeclarativeDebugFileReference source = obj.source();
QString fileName = source.url().toLocalFile();
if (source.lineNumber() < 0 || !QFile::exists(fileName))
return;
Core::EditorManager *editorManager = Core::EditorManager::instance();
Core::IEditor *editor = editorManager->openEditor(fileName, QString(), Core::EditorManager::NoModeSwitch);
TextEditor::ITextEditor *textEditor = qobject_cast<TextEditor::ITextEditor*>(editor);
if (textEditor) {
editorManager->addCurrentPositionToNavigationHistory();
textEditor->gotoLine(source.lineNumber());
textEditor->widget()->setFocus();
}
}
bool QmlEngine::canEditProperty(const QString &propertyType)
{
return m_editablePropertyTypes.contains(propertyType);
}
QDeclarativeDebugExpressionQuery *QmlEngine::executeExpression(int objectDebugId, const QString &objectId,
const QString &propertyName, const QVariant &value)
{
//qDebug() << entity.property << entity.title << entity.objectId;
if (objectId.length()) {
QString quoteWrappedValue = value.toString();
if (addQuotesForData(value))
quoteWrappedValue = QString("'%1'").arg(quoteWrappedValue);
QString constructedExpression = objectId + "." + propertyName + "=" + quoteWrappedValue;
//qDebug() << "EXPRESSION:" << constructedExpression;
return m_client->queryExpressionResult(objectDebugId, constructedExpression, this);
}
return 0;
}
bool QmlEngine::addQuotesForData(const QVariant &value) const
{
switch (value.type()) {
case QVariant::String:
case QVariant::Color:
case QVariant::Date:
return true;
default:
break;
}
return false;
}
ObjectTree::ObjectTree(QDeclarativeEngineDebug *client, QWidget *parent)
: QTreeWidget(parent),
m_client(client),
m_query(0), m_clickedItem(0), m_showUninspectableItems(false),
m_currentObjectDebugId(0), m_showUninspectableOnInitDone(false)
{
setAttribute(Qt::WA_MacShowFocusRect, false);
setFrameStyle(QFrame::NoFrame);
setHeaderHidden(true);
setExpandsOnDoubleClick(false);
m_addWatchAction = new QAction(tr("Add watch expression..."), this);
m_toggleUninspectableItemsAction = new QAction(tr("Show uninspectable items"), this);
m_toggleUninspectableItemsAction->setCheckable(true);
m_goToFileAction = new QAction(tr("Go to file"), this);
connect(m_toggleUninspectableItemsAction, SIGNAL(triggered()), SLOT(toggleUninspectableItems()));
connect(m_addWatchAction, SIGNAL(triggered()), SLOT(addWatch()));
connect(m_goToFileAction, SIGNAL(triggered()), SLOT(goToFile()));
connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
SLOT(currentItemChanged(QTreeWidgetItem *)));
connect(this, SIGNAL(itemActivated(QTreeWidgetItem *, int)),
SLOT(activated(QTreeWidgetItem *)));
connect(this, SIGNAL(itemSelectionChanged()), SLOT(selectionChanged()));
}
void ObjectTree::readSettings(const InspectorSettings &settings)
{
if (settings.showUninspectableItems() != m_showUninspectableItems)
toggleUninspectableItems();
}
void ObjectTree::saveSettings(InspectorSettings &settings)
{
settings.setShowUninspectableItems(m_showUninspectableItems);
}
void ObjectTree::setEngineDebug(QDeclarativeEngineDebug *client)
{
m_client = client;
}
void ObjectTree::toggleUninspectableItems()
{
m_showUninspectableItems = !m_showUninspectableItems;
m_toggleUninspectableItemsAction->setChecked(m_showUninspectableItems);
reload(m_currentObjectDebugId);
}
void ObjectTree::selectionChanged()
{
if (selectedItems().isEmpty())
return;
QTreeWidgetItem *item = selectedItems().first();
if (item)
emit contextHelpIdChanged(InspectorContext::contextHelpIdForItem(item->text(0)));
}
void ObjectTree::setCurrentObject(int debugId)
{
QTreeWidgetItem *item = findItemByObjectId(debugId);
if (item) {
setCurrentItem(item);
scrollToItem(item);
item->setExpanded(true);
}
}
{
if (!item)
return;
QDeclarativeDebugObjectReference obj = item->data(0, Qt::UserRole).value<QDeclarativeDebugObjectReference>();
if (obj.debugId() >= 0)
emit currentObjectChanged(obj);
}
void ObjectTree::activated(QTreeWidgetItem *item)
{
if (!item)
return;
QDeclarativeDebugObjectReference obj = item->data(0, Qt::UserRole).value<QDeclarativeDebugObjectReference>();
if (obj.debugId() >= 0)
emit activated(obj);
}
void ObjectTree::cleanup()
{
m_showUninspectableOnInitDone = false;
clear();
}
void ObjectTree::dump(const QDeclarativeDebugContextReference &ctxt, int ind)
{
QByteArray indent(ind * 4, ' ');
qWarning().nospace() << indent.constData() << ctxt.debugId() << " "
<< qPrintable(ctxt.name());
for (int ii = 0; ii < ctxt.contexts().count(); ++ii)
dump(ctxt.contexts().at(ii), ind + 1);
for (int ii = 0; ii < ctxt.objects().count(); ++ii)
dump(ctxt.objects().at(ii), ind);
}
void ObjectTree::dump(const QDeclarativeDebugObjectReference &obj, int ind)
{
QByteArray indent(ind * 4, ' ');
qWarning().nospace() << indent.constData() << qPrintable(obj.className())
<< " " << qPrintable(obj.idString()) << " "
<< obj.debugId();
for (int ii = 0; ii < obj.children().count(); ++ii)
dump(obj.children().at(ii), ind + 1);
}
QTreeWidgetItem *ObjectTree::findItemByObjectId(int debugId) const
{
for (int i=0; i<topLevelItemCount(); ++i) {
QTreeWidgetItem *item = findItem(topLevelItem(i), debugId);
if (item)
return item;
}
return 0;
}
QTreeWidgetItem *ObjectTree::findItem(QTreeWidgetItem *item, int debugId) const
{
if (item->data(0, Qt::UserRole).value<QDeclarativeDebugObjectReference>().debugId() == debugId)
return item;
QTreeWidgetItem *child;
for (int i=0; i<item->childCount(); ++i) {
child = findItem(item->child(i), debugId);
if (child)
return child;
}
return 0;
}
void ObjectTree::addWatch()
{
QDeclarativeDebugObjectReference obj =
currentItem()->data(0, Qt::UserRole).value<QDeclarativeDebugObjectReference>();
bool ok = false;
QString watch = QInputDialog::getText(this, tr("Watch expression"),
tr("Expression:"), QLineEdit::Normal, QString(), &ok);
if (ok && !watch.isEmpty())
emit expressionWatchRequested(obj, watch);
}
void ObjectTree::goToFile()
{
QDeclarativeDebugObjectReference obj =
currentItem()->data(0, Qt::UserRole).value<QDeclarativeDebugObjectReference>();
if (obj.debugId() >= 0)
emit activated(obj);
}
void ObjectTree::contextMenuEvent(QContextMenuEvent *event)
{
m_clickedItem = itemAt(QPoint(event->pos().x(),
event->pos().y() ));
if (!m_clickedItem)
return;
QMenu menu;
menu.addAction(m_addWatchAction);
menu.addAction(m_goToFileAction);
if (m_currentObjectDebugId) {
menu.addSeparator();
menu.addAction(m_toggleUninspectableItemsAction);
}
menu.exec(event->globalPos());
}
} // Internal
} // Qml
#endif
}
// namespace Internal
}
// namespace Debugger
...
...
This diff is collapsed.
Click to expand it.
src/plugins/debugger/qml/qmlengine.h
+
85
−
1
View file @
de59fe3f
...
...
@@ -32,6 +32,10 @@
#include
"debuggerengine.h"
#include
"private/qdeclarativedebug_p.h"
#include
"private/qdeclarativedebugclient_p.h"
#include
"private/qdeclarativeenginedebug_p.h"
#include
<QtCore/QByteArray>
#include
<QtCore/QHash>
#include
<QtCore/QObject>
...
...
@@ -44,6 +48,7 @@
#include
<QtNetwork/QAbstractSocket>
#include
<QtNetwork/QTcpSocket>
QT_BEGIN_NAMESPACE
class
QTcpSocket
;
class
QDeclarativeDebugConnection
;
...
...
@@ -74,6 +79,7 @@ public:
private:
// DebuggerEngine implementation
bool
isSynchroneous
()
const
{
return
true
;
}
void
executeStep
();
void
executeStepOut
();
void
executeNext
();
...
...
@@ -130,15 +136,93 @@ private slots:
void
connectionConnected
();
void
connectionStateChanged
();
void
reloadEngines
();
void
enginesChanged
();
void
queryEngineContext
(
const
QDeclarativeDebugEngineReference
&
engine
);
void
contextChanged
();
void
reloadObject
(
const
QDeclarativeDebugObjectReference
&
object
);
void
objectFetched
(
QDeclarativeDebugQuery
::
State
state
);
private
:
void
objectFetched
(
QDeclarativeDebugObjectQuery
*
query
,
QDeclarativeDebugQuery
::
State
state
);
void
contextChanged
(
QDeclarativeDebugRootContextQuery
*
query
);
void
enginesChanged
(
QDeclarativeDebugEnginesQuery
*
query
);
void
buildTree
(
const
QDeclarativeDebugObjectReference
&
obj
,
const
QByteArray
&
iname
);
QString
errorMessage
(
QProcess
::
ProcessError
error
);
QProcess
m_proc
;
QDeclarativeDebugConnection
*
m_conn
;
QDeclarativeEngineDebug
*
m_engineDebugInterface
;
QmlDebuggerClient
*
m_client
;
CanvasFrameRate
*
m_frameRate
;
enum
DebugMode
{
StandaloneMode
,
CppProjectWithQmlEngines
,
QmlProjectWithCppPlugins
};
QList
<
QDeclarativeDebugWatch
*>
m_watches
;
#if 0
void createDockWidgets();
bool connectToViewer(); // using host, port from widgets
// returns false if project is not debuggable.
bool setDebugConfigurationDataFromProject(ProjectExplorer::Project *projectToDebug);
void startQmlProjectDebugger();
bool canEditProperty(const QString &propertyType);
QDeclarativeDebugExpressionQuery *executeExpression(int objectDebugId,
const QString &objectId, const QString &propertyName, const QVariant &value);
public slots:
void disconnectFromViewer();
void setSimpleDockWidgetArrangement();
private slots:
void treeObjectActivated(const QDeclarativeDebugObjectReference &obj);
void simultaneouslyDebugQmlCppApplication();
private:
void updateMenuActions();
QString attachToQmlViewerAsExternalApp(ProjectExplorer::Project *project);
QString attachToExternalCppAppWithQml(ProjectExplorer::Project *project);
bool addQuotesForData(const QVariant &value) const;
void resetViews();
QDeclarativeDebugEnginesQuery *m_engineQuery;
QDeclarativeDebugRootContextQuery *m_contextQuery;
CanvasFrameRate
*
m_frameRate
;
Internal::ObjectTree *m_objectTreeWidget;
Internal::ObjectPropertiesView *m_propertiesWidget;
Internal::WatchTableModel *m_watchTableModel;
Internal::WatchTableView *m_watchTableView;
Internal::CanvasFrameRate *m_frameRateWidget;
Internal::ExpressionQueryWidget *m_expressionWidget;
Internal::EngineComboBox *m_engineComboBox;
QDockWidget *m_objectTreeDock;
QDockWidget *m_frameRateDock;
QDockWidget *m_expressionQueryDock;
QDockWidget *m_propertyWatcherDock;
QDockWidget *m_inspectorOutputDock;
Internal::InspectorSettings m_settings;
QmlProjectManager::QmlProjectRunConfigurationDebugData m_runConfigurationDebugData;
QStringList m_editablePropertyTypes;
// simultaneous debug mode stuff
int m_cppDebuggerState;
bool m_connectionInitialized;
bool m_simultaneousCppAndQmlDebugMode;
#endif
};
}
// namespace Internal
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment