diff options
Diffstat (limited to 'src/plugins/debugger')
63 files changed, 723 insertions, 410 deletions
diff --git a/src/plugins/debugger/Debugger.pluginspec.in b/src/plugins/debugger/Debugger.pluginspec.in index 1b4327cc0a..77d13834f8 100644 --- a/src/plugins/debugger/Debugger.pluginspec.in +++ b/src/plugins/debugger/Debugger.pluginspec.in @@ -17,6 +17,7 @@ Alternatively, this plugin may be used under the terms of the GNU Lesser General <dependency name=\"ProjectExplorer\" version=\"$$QTCREATOR_VERSION\"/> <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/> <dependency name=\"Find\" version=\"$$QTCREATOR_VERSION\"/> + <dependency name=\"CppTools\" version=\"$$QTCREATOR_VERSION\"/> <!-- Debugger plugin adds items to the editor\'s context menu --> <dependency name=\"CppEditor\" version=\"$$QTCREATOR_VERSION\" type=\"optional\"/> </dependencyList> diff --git a/src/plugins/debugger/basewindow.cpp b/src/plugins/debugger/basewindow.cpp index 133dc86be0..92fdcd0d91 100644 --- a/src/plugins/debugger/basewindow.cpp +++ b/src/plugins/debugger/basewindow.cpp @@ -35,116 +35,44 @@ #include "debuggeractions.h" #include "debuggercore.h" +#include <aggregation/aggregate.h> +#include <coreplugin/findplaceholder.h> +#include <find/treeviewfind.h> #include <utils/savedaction.h> -#include <QDebug> -#include <QContextMenuEvent> -#include <QHeaderView> #include <QMenu> +#include <QVBoxLayout> namespace Debugger { namespace Internal { -BaseWindow::BaseWindow(QWidget *parent) - : QTreeView(parent) +BaseTreeView::BaseTreeView(QWidget *parent) + : Utils::BaseTreeView(parent) { QAction *act = debuggerCore()->action(UseAlternatingRowColors); - - setAttribute(Qt::WA_MacShowFocusRect, false); - setFrameStyle(QFrame::NoFrame); setAlternatingRowColors(act->isChecked()); - setRootIsDecorated(false); - setIconSize(QSize(10, 10)); - setSelectionMode(QAbstractItemView::ExtendedSelection); - setUniformRowHeights(true); - - header()->setDefaultAlignment(Qt::AlignLeft); - header()->setClickable(true); - connect(act, SIGNAL(toggled(bool)), - SLOT(setAlternatingRowColorsHelper(bool))); - connect(this, SIGNAL(activated(QModelIndex)), - SLOT(rowActivatedHelper(QModelIndex))); - connect(header(), SIGNAL(sectionClicked(int)), - SLOT(headerSectionClicked(int))); - - m_adjustColumnsAction = new QAction(tr("Adjust Column Widths to Contents"), 0); - m_alwaysAdjustColumnsAction = 0; -} - -void BaseWindow::setAlwaysAdjustColumnsAction(QAction *action) -{ - m_alwaysAdjustColumnsAction = action; - connect(action, SIGNAL(toggled(bool)), - SLOT(setAlwaysResizeColumnsToContents(bool))); + SLOT(setAlternatingRowColorsHelper(bool))); } -void BaseWindow::addBaseContextActions(QMenu *menu) +void BaseTreeView::addBaseContextActions(QMenu *menu) { - menu->addSeparator(); - if (m_alwaysAdjustColumnsAction) - menu->addAction(m_alwaysAdjustColumnsAction); - menu->addAction(m_adjustColumnsAction); - menu->addSeparator(); + Utils::BaseTreeView::addBaseContextActions(menu); menu->addAction(debuggerCore()->action(SettingsDialog)); } -bool BaseWindow::handleBaseContextAction(QAction *act) -{ - if (act == 0) - return true; - if (act == m_adjustColumnsAction) { - resizeColumnsToContents(); - return true; - } - if (act == m_alwaysAdjustColumnsAction) { - if (act->isChecked()) - resizeColumnsToContents(); - // Action triggered automatically. - return true; - } - return false; -} - -void BaseWindow::setModel(QAbstractItemModel *model) -{ - QTreeView::setModel(model); - if (header() && m_alwaysAdjustColumnsAction) - setAlwaysResizeColumnsToContents(m_alwaysAdjustColumnsAction->isChecked()); -} - -void BaseWindow::mousePressEvent(QMouseEvent *ev) -{ - QTreeView::mousePressEvent(ev); - if (!indexAt(ev->pos()).isValid()) - resizeColumnsToContents(); -} - -void BaseWindow::resizeColumnsToContents() -{ - const int columnCount = model()->columnCount(); - for (int c = 0 ; c != columnCount; ++c) - resizeColumnToContents(c); -} - -void BaseWindow::setAlwaysResizeColumnsToContents(bool on) -{ - QHeaderView::ResizeMode mode = on - ? QHeaderView::ResizeToContents : QHeaderView::Interactive; - header()->setResizeMode(0, mode); -} - -void BaseWindow::headerSectionClicked(int logicalIndex) -{ - resizeColumnToContents(logicalIndex); -} - -void BaseWindow::reset() +BaseWindow::BaseWindow(QTreeView *treeView, QWidget *parent) + : QWidget(parent), m_treeView(treeView) { - QTreeView::reset(); - if (header() && m_alwaysAdjustColumnsAction - && m_alwaysAdjustColumnsAction->isChecked()) - resizeColumnsToContents(); + QVBoxLayout *vbox = new QVBoxLayout(this); + vbox->setMargin(0); + vbox->setSpacing(0); + vbox->addWidget(m_treeView); + vbox->addWidget(new Core::FindToolBarPlaceHolder(this)); + + Aggregation::Aggregate *agg = new Aggregation::Aggregate; + agg->add(m_treeView); + agg->add(new Find::TreeViewFind(m_treeView)); } } // namespace Internal diff --git a/src/plugins/debugger/basewindow.h b/src/plugins/debugger/basewindow.h index 1592df4202..4a0b95d8b8 100644 --- a/src/plugins/debugger/basewindow.h +++ b/src/plugins/debugger/basewindow.h @@ -33,39 +33,30 @@ #ifndef DEBUGGER_BASEWINDOW_H #define DEBUGGER_BASEWINDOW_H -#include <QTreeView> +#include <utils/basetreeview.h> namespace Debugger { namespace Internal { -class BaseWindow : public QTreeView +class BaseTreeView : public Utils::BaseTreeView { Q_OBJECT public: - BaseWindow(QWidget *parent = 0); - - void setAlwaysAdjustColumnsAction(QAction *action); + explicit BaseTreeView(QWidget *parent = 0); void addBaseContextActions(QMenu *menu); - bool handleBaseContextAction(QAction *action); - - void setModel(QAbstractItemModel *model); - virtual void rowActivated(const QModelIndex &) {} - void mousePressEvent(QMouseEvent *ev); - -public slots: - void resizeColumnsToContents(); - void setAlwaysResizeColumnsToContents(bool on); +}; -private slots: - void setAlternatingRowColorsHelper(bool on) { setAlternatingRowColors(on); } - void rowActivatedHelper(const QModelIndex &index) { rowActivated(index); } - void headerSectionClicked(int logicalIndex); - void reset(); +class BaseWindow : public QWidget +{ +public: + explicit BaseWindow(QTreeView *treeView, QWidget *parent = 0); + void setModel(QAbstractItemModel *model) { m_treeView->setModel(model); } + QHeaderView *header() const { return m_treeView->header(); } + QAbstractItemModel *model() const { return m_treeView->model(); } private: - QAction *m_alwaysAdjustColumnsAction; - QAction *m_adjustColumnsAction; + QTreeView *m_treeView; }; } // namespace Internal diff --git a/src/plugins/debugger/breakwindow.cpp b/src/plugins/debugger/breakwindow.cpp index 699025a18e..63856af81f 100644 --- a/src/plugins/debugger/breakwindow.cpp +++ b/src/plugins/debugger/breakwindow.cpp @@ -486,11 +486,9 @@ MultiBreakPointsDialog::MultiBreakPointsDialog(QWidget *parent) : // /////////////////////////////////////////////////////////////////////// -BreakWindow::BreakWindow(QWidget *parent) - : BaseWindow(parent) +BreakTreeView::BreakTreeView(QWidget *parent) + : BaseTreeView(parent) { - setWindowTitle(tr("Breakpoints")); - setObjectName(QLatin1String("ThreadsWindow")); setWindowIcon(QIcon(QLatin1String(":/debugger/images/debugger_breakpoints.png"))); setSelectionMode(QAbstractItemView::ExtendedSelection); setAlwaysAdjustColumnsAction(debuggerCore()->action(AlwaysAdjustBreakpointsColumnWidths)); @@ -498,12 +496,12 @@ BreakWindow::BreakWindow(QWidget *parent) SIGNAL(toggled(bool)), SLOT(showAddressColumn(bool))); } -void BreakWindow::showAddressColumn(bool on) +void BreakTreeView::showAddressColumn(bool on) { setColumnHidden(7, !on); } -void BreakWindow::keyPressEvent(QKeyEvent *ev) +void BreakTreeView::keyPressEvent(QKeyEvent *ev) { if (ev->key() == Qt::Key_Delete) { QItemSelectionModel *sm = selectionModel(); @@ -519,7 +517,7 @@ void BreakWindow::keyPressEvent(QKeyEvent *ev) QTreeView::keyPressEvent(ev); } -void BreakWindow::mouseDoubleClickEvent(QMouseEvent *ev) +void BreakTreeView::mouseDoubleClickEvent(QMouseEvent *ev) { QModelIndex indexUnderMouse = indexAt(ev->pos()); if (indexUnderMouse.isValid() && indexUnderMouse.column() >= 4) { @@ -529,16 +527,16 @@ void BreakWindow::mouseDoubleClickEvent(QMouseEvent *ev) QTreeView::mouseDoubleClickEvent(ev); } -void BreakWindow::setModel(QAbstractItemModel *model) +void BreakTreeView::setModel(QAbstractItemModel *model) { - BaseWindow::setModel(model); + BaseTreeView::setModel(model); resizeColumnToContents(0); // Number resizeColumnToContents(3); // Line resizeColumnToContents(6); // Ignore count connect(model, SIGNAL(layoutChanged()), this, SLOT(expandAll())); } -void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) +void BreakTreeView::contextMenuEvent(QContextMenuEvent *ev) { QMenu menu; QItemSelectionModel *sm = selectionModel(); @@ -654,21 +652,21 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) handleBaseContextAction(act); } -void BreakWindow::setBreakpointsEnabled(const BreakpointModelIds &ids, bool enabled) +void BreakTreeView::setBreakpointsEnabled(const BreakpointModelIds &ids, bool enabled) { BreakHandler *handler = breakHandler(); foreach (const BreakpointModelId id, ids) handler->setEnabled(id, enabled); } -void BreakWindow::deleteBreakpoints(const BreakpointModelIds &ids) +void BreakTreeView::deleteBreakpoints(const BreakpointModelIds &ids) { BreakHandler *handler = breakHandler(); foreach (const BreakpointModelId id, ids) handler->removeBreakpoint(id); } -void BreakWindow::editBreakpoint(BreakpointModelId id, QWidget *parent) +void BreakTreeView::editBreakpoint(BreakpointModelId id, QWidget *parent) { BreakpointParameters data = breakHandler()->breakpointData(id); BreakpointParts parts = NoParts; @@ -677,7 +675,7 @@ void BreakWindow::editBreakpoint(BreakpointModelId id, QWidget *parent) breakHandler()->changeBreakpointData(id, data, parts); } -void BreakWindow::addBreakpoint() +void BreakTreeView::addBreakpoint() { BreakpointParameters data(BreakpointByFileAndLine); BreakpointParts parts = NoParts; @@ -687,7 +685,7 @@ void BreakWindow::addBreakpoint() breakHandler()->appendBreakpoint(data); } -void BreakWindow::editBreakpoints(const BreakpointModelIds &ids) +void BreakTreeView::editBreakpoints(const BreakpointModelIds &ids) { QTC_ASSERT(!ids.isEmpty(), return); @@ -726,18 +724,24 @@ void BreakWindow::editBreakpoints(const BreakpointModelIds &ids) } } -void BreakWindow::associateBreakpoint(const BreakpointModelIds &ids, int threadId) +void BreakTreeView::associateBreakpoint(const BreakpointModelIds &ids, int threadId) { BreakHandler *handler = breakHandler(); foreach (const BreakpointModelId id, ids) handler->setThreadSpec(id, threadId); } -void BreakWindow::rowActivated(const QModelIndex &index) +void BreakTreeView::rowActivated(const QModelIndex &index) { breakHandler()->gotoLocation(breakHandler()->findBreakpointByIndex(index)); } +BreakWindow::BreakWindow() + : BaseWindow(new BreakTreeView) +{ + setWindowTitle(tr("Breakpoints")); +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/breakwindow.h b/src/plugins/debugger/breakwindow.h index 877f3dfcaa..b06055ad10 100644 --- a/src/plugins/debugger/breakwindow.h +++ b/src/plugins/debugger/breakwindow.h @@ -39,12 +39,12 @@ namespace Debugger { namespace Internal { -class BreakWindow : public BaseWindow +class BreakTreeView : public BaseTreeView { Q_OBJECT public: - explicit BreakWindow(QWidget *parent = 0); + explicit BreakTreeView(QWidget *parent = 0); static void editBreakpoint(BreakpointModelId id, QWidget *parent); void setModel(QAbstractItemModel *model); @@ -65,6 +65,12 @@ private: void setBreakpointsEnabled(const BreakpointModelIds &ids, bool enabled); }; +class BreakWindow : public BaseWindow +{ +public: + BreakWindow(); +}; + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index eac6068952..bce3ac1910 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -75,7 +75,7 @@ #include <cplusplus/findcdbbreakpoint.h> #include <cplusplus/CppDocument.h> -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <QCoreApplication> #include <QFileInfo> diff --git a/src/plugins/debugger/commonoptionspage.cpp b/src/plugins/debugger/commonoptionspage.cpp index 4718a1cc9f..98806c9784 100644 --- a/src/plugins/debugger/commonoptionspage.cpp +++ b/src/plugins/debugger/commonoptionspage.cpp @@ -72,6 +72,8 @@ CommonOptionsPageWidget::CommonOptionsPageWidget m_ui.checkBoxCloseBuffersOnExit); m_group->insert(dc->action(SwitchModeOnExit), m_ui.checkBoxSwitchModeOnExit); + m_group->insert(dc->action(RaiseOnInterrupt), + m_ui.checkBoxBringToForegroundOnInterrrupt); m_group->insert(dc->action(FontSizeFollowsEditor), m_ui.checkBoxFontSizeFollowsEditor); m_group->insert(dc->action(AutoDerefPointers), 0); @@ -120,6 +122,7 @@ QString CommonOptionsPageWidget::searchKeyWords() const << sep << m_ui.checkBoxCloseBuffersOnExit->text() << sep << m_ui.checkBoxSwitchModeOnExit->text() << sep << m_ui.labelMaximalStackDepth->text() + << sep << m_ui.checkBoxBringToForegroundOnInterrrupt->text() ; rc.remove(QLatin1Char('&')); return rc; diff --git a/src/plugins/debugger/commonoptionspage.ui b/src/plugins/debugger/commonoptionspage.ui index 8cf9ae4f0e..b44f2f36cb 100644 --- a/src/plugins/debugger/commonoptionspage.ui +++ b/src/plugins/debugger/commonoptionspage.ui @@ -65,16 +65,6 @@ </property> </widget> </item> - <item row="3" column="0"> - <widget class="QCheckBox" name="checkBoxRegisterForPostMortem"> - <property name="toolTip"> - <string>Register Qt Creator for debugging crashed applications.</string> - </property> - <property name="text"> - <string>Use Qt Creator for post-mortem debugging</string> - </property> - </widget> - </item> <item row="4" column="0"> <layout class="QHBoxLayout" name="horizontalLayout"> <item> @@ -130,6 +120,23 @@ </item> </layout> </item> + <item row="3" column="1"> + <widget class="QCheckBox" name="checkBoxRegisterForPostMortem"> + <property name="toolTip"> + <string>Register Qt Creator for debugging crashed applications.</string> + </property> + <property name="text"> + <string>Use Qt Creator for post-mortem debugging</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QCheckBox" name="checkBoxBringToForegroundOnInterrrupt"> + <property name="text"> + <string>Bring Qt Creator to foreground when application interrupts</string> + </property> + </widget> + </item> </layout> </widget> </item> diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp index 0712a37124..ffb0d1842d 100644 --- a/src/plugins/debugger/debuggeractions.cpp +++ b/src/plugins/debugger/debuggeractions.cpp @@ -398,6 +398,12 @@ DebuggerSettings::DebuggerSettings(QSettings *settings) insertItem(SwitchModeOnExit, item); item = new SavedAction(this); + item->setSettingsKey(debugModeGroup, QLatin1String("RaiseOnInterrupt")); + item->setCheckable(true); + item->setDefaultValue(true); + insertItem(RaiseOnInterrupt, item); + + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("AutoQuit")); item->setText(tr("Automatically Quit Debugger")); item->setCheckable(true); diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h index 1bdc34c496..9da4ab1b05 100644 --- a/src/plugins/debugger/debuggeractions.h +++ b/src/plugins/debugger/debuggeractions.h @@ -100,6 +100,7 @@ enum DebuggerActionCode OperateByInstruction, CloseBuffersOnExit, SwitchModeOnExit, + RaiseOnInterrupt, UseDebuggingHelpers, diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h index 1367cbeb5b..5925f2df17 100644 --- a/src/plugins/debugger/debuggerconstants.h +++ b/src/plugins/debugger/debuggerconstants.h @@ -134,6 +134,12 @@ enum DebuggerStartMode StartRemoteEngine // Start ipc guest engine on other machine }; +enum DebuggerCloseMode +{ + KillAtClose, + DetachAtClose +}; + enum DebuggerCapabilities { ReverseSteppingCapability = 0x1, diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index ab623dee5b..1a53d207c6 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -61,8 +61,8 @@ #include <texteditor/itexteditor.h> #include <texteditor/basetextmark.h> +#include <projectexplorer/projectexplorer.h> #include <projectexplorer/taskhub.h> -#include <extensionsystem/pluginmanager.h> #include <utils/savedaction.h> #include <utils/qtcassert.h> @@ -269,6 +269,8 @@ public slots: m_disassemblerAgent.resetLocation(); } + TaskHub *taskHub(); + public: DebuggerState state() const { return m_state; } RemoteSetupState remoteSetupState() const { return m_remoteSetupState; } @@ -1038,6 +1040,8 @@ void DebuggerEngine::notifyInferiorSpontaneousStop() QTC_ASSERT(state() == InferiorRunOk, qDebug() << this << state()); showStatusMessage(tr("Stopped.")); setState(InferiorStopOk); + if (debuggerCore()->boolSetting(RaiseOnInterrupt)) + emit raiseWindow(); } void DebuggerEngine::notifyInferiorStopFailed() @@ -1394,6 +1398,8 @@ void DebuggerEngine::quitDebugger() break; case EngineRunFailed: case DebuggerFinished: + case InferiorExitOk: + case InferiorShutdownOk: break; case InferiorSetupRequested: notifyInferiorSetupFailed(); @@ -1518,6 +1524,7 @@ void DebuggerEngine::updateAll() void DebuggerEngine::attemptBreakpointSynchronization() { + showMessage(_("ATTEMPT BREAKPOINT SYNCHRONIZATION")); if (!stateAcceptsBreakpointChanges()) { showMessage(_("BREAKPOINT SYNCHRONIZATION NOT POSSIBLE IN CURRENT STATE")); return; @@ -1527,8 +1534,14 @@ void DebuggerEngine::attemptBreakpointSynchronization() foreach (BreakpointModelId id, handler->unclaimedBreakpointIds()) { // Take ownership of the breakpoint. Requests insertion. - if (acceptsBreakpoint(id)) + if (acceptsBreakpoint(id)) { + showMessage(_("TAKING OWNERSHIP OF BREAKPOINT %1 IN STATE %2") + .arg(id.toString()).arg(handler->state(id))); handler->setEngine(id, this); + } else { + showMessage(_("BREAKPOINT %1 IN STATE %2 IS NOT ACCEPTABLE") + .arg(id.toString()).arg(handler->state(id))); + } } bool done = true; @@ -1568,8 +1581,12 @@ void DebuggerEngine::attemptBreakpointSynchronization() QTC_ASSERT(false, qDebug() << "UNKNOWN STATE" << id << state()); } - if (done) + if (done) { + showMessage(_("BREAKPOINTS ARE SYNCHRONIZED")); d->m_disassemblerAgent.updateBreakpointMarkers(); + } else { + showMessage(_("BREAKPOINTS ARE NOT FULLY SYNCHRONIZED")); + } } void DebuggerEngine::insertBreakpoint(BreakpointModelId id) @@ -1951,15 +1968,23 @@ void DebuggerEnginePrivate::reportTestError(const QString &msg, int line) { m_engine->showMessage(_("### Line %1: %2").arg(line).arg(msg)); m_foundError = true; + Task task(Task::Error, msg, Utils::FileName::fromUserInput(m_testFileName), line + 1, Core::Id("DebuggerTest")); + taskHub()->addTask(task); +} +TaskHub *DebuggerEnginePrivate::taskHub() +{ if (!m_taskHub) { - ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); - m_taskHub = pm->getObject<TaskHub>(); + m_taskHub = ProjectExplorerPlugin::instance()->taskHub(); + m_taskHub->addCategory(Core::Id("Debuginfo"), tr("Debug Information")); m_taskHub->addCategory(Core::Id("DebuggerTest"), tr("Debugger Test")); } + return m_taskHub; +} - Task task(Task::Error, msg, Utils::FileName::fromUserInput(m_testFileName), line + 1, Core::Id("DebuggerTest")); - m_taskHub->addTask(task); +TaskHub *DebuggerEngine::taskHub() +{ + return d->taskHub(); } } // namespace Debugger diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h index f2f133dff1..8665edd954 100644 --- a/src/plugins/debugger/debuggerengine.h +++ b/src/plugins/debugger/debuggerengine.h @@ -47,13 +47,9 @@ class QMessageBox; class QAbstractItemModel; QT_END_NAMESPACE -namespace TextEditor { -class ITextEditor; -} - -namespace Core { -class IOptionsPage; -} +namespace TextEditor { class ITextEditor; } +namespace Core { class IOptionsPage; } +namespace ProjectExplorer { class TaskHub; } namespace Debugger { @@ -201,6 +197,7 @@ public: virtual void createSnapshot(); virtual void updateAll(); + ProjectExplorer::TaskHub *taskHub(); typedef Internal::BreakpointModelId BreakpointModelId; virtual bool stateAcceptsBreakpointChanges() const { return true; } @@ -289,10 +286,9 @@ public: QString toFileInProject(const QUrl &fileUrl); signals: - void stateChanged(const Debugger::DebuggerState &state); + void stateChanged(Debugger::DebuggerState state); // A new stack frame is on display including locals. void stackFrameCompleted(); - void updateViewsRequested(); /* * For "external" clients of a debugger run control that needs to do * further setup before the debugger is started (e.g. Maemo). @@ -302,6 +298,7 @@ signals: * a server start script should be used, but none is given. */ void requestRemoteSetup(); + void raiseWindow(); protected: // The base notify*() function implementation should be sufficient diff --git a/src/plugins/debugger/debuggermainwindow.cpp b/src/plugins/debugger/debuggermainwindow.cpp index d5c1102b9e..bce0213b5f 100644 --- a/src/plugins/debugger/debuggermainwindow.cpp +++ b/src/plugins/debugger/debuggermainwindow.cpp @@ -32,7 +32,9 @@ #include "debuggermainwindow.h" #include "debuggercore.h" +#include "debuggerengine.h" +#include <utils/appmainwindow.h> #include <utils/styledbar.h> #include <utils/qtcassert.h> #include <utils/fancymainwindow.h> @@ -124,7 +126,8 @@ public: DebuggerLanguages m_supportedLanguages; - QStackedWidget *m_toolBarStack; + QWidget *m_debugToolBar; + QHBoxLayout *m_debugToolBarLayout; QHash<DebuggerLanguage, Context> m_contextsForLanguage; @@ -141,13 +144,16 @@ public: Project *m_previousProject; Target *m_previousTarget; RunConfiguration *m_previousRunConfiguration; + + DebuggerEngine *m_engine; }; DebuggerMainWindowPrivate::DebuggerMainWindowPrivate(DebuggerMainWindow *mw) : q(mw) , m_resizeEventFilter(this) , m_supportedLanguages(AnyLanguage) - , m_toolBarStack(new QStackedWidget) + , m_debugToolBar(new QWidget) + , m_debugToolBarLayout(new QHBoxLayout(m_debugToolBar)) , m_inDebugMode(false) , m_changingUI(false) , m_previousDebugLanguages(AnyLanguage) @@ -157,8 +163,12 @@ DebuggerMainWindowPrivate::DebuggerMainWindowPrivate(DebuggerMainWindow *mw) , m_previousProject(0) , m_previousTarget(0) , m_previousRunConfiguration(0) + , m_engine(0) { + m_debugToolBarLayout->setMargin(0); + m_debugToolBarLayout->setSpacing(0); createViewsMenuItems(); + addLanguage(AnyLanguage, Context()); addLanguage(CppLanguage, Context(C_CPPDEBUGGER)); addLanguage(QmlLanguage, Context(C_QMLDEBUGGER)); } @@ -271,6 +281,15 @@ DebuggerMainWindow::~DebuggerMainWindow() delete d; } +void DebuggerMainWindow::setCurrentEngine(DebuggerEngine *engine) +{ + if (d->m_engine) + disconnect(d->m_engine, SIGNAL(raiseWindow()), this, SLOT(raiseDebuggerWindow())); + d->m_engine = engine; + if (d->m_engine) + connect(d->m_engine, SIGNAL(raiseWindow()), this, SLOT(raiseDebuggerWindow())); +} + DebuggerLanguages DebuggerMainWindow::activeDebugLanguages() const { return d->m_activeDebugLanguages; @@ -353,8 +372,10 @@ void DebuggerMainWindowPrivate::activateQmlCppLayout() { Context qmlCppContext = m_contextsForLanguage.value(QmlLanguage); qmlCppContext.add(m_contextsForLanguage.value(CppLanguage)); - if (m_toolBars.value(QmlLanguage)) - m_toolBarStack->setCurrentWidget(m_toolBars.value(QmlLanguage)); + if (m_toolBars.value(QmlLanguage)) { + m_toolBars.value(QmlLanguage)->show(); + m_debugToolBarLayout->insertWidget(1, m_toolBars.value(QmlLanguage)); + } if (m_previousDebugLanguages & QmlLanguage) { m_dockWidgetActiveStateQmlCpp = q->saveSettings(); @@ -373,7 +394,10 @@ void DebuggerMainWindowPrivate::activateCppLayout() { Context qmlCppContext = m_contextsForLanguage.value(QmlLanguage); qmlCppContext.add(m_contextsForLanguage.value(CppLanguage)); - m_toolBarStack->setCurrentWidget(m_toolBars.value(CppLanguage)); + if (m_toolBars.value(QmlLanguage)) { + m_toolBars.value(QmlLanguage)->hide(); + m_debugToolBarLayout->removeWidget(m_toolBars.value(QmlLanguage)); + } if (m_previousDebugLanguages & QmlLanguage) { m_dockWidgetActiveStateQmlCpp = q->saveSettings(); @@ -394,7 +418,12 @@ void DebuggerMainWindow::setToolBar(DebuggerLanguage language, QWidget *widget) { Q_ASSERT(d->m_toolBars.contains(language)); d->m_toolBars[language] = widget; - d->m_toolBarStack->addWidget(widget); + if (language == CppLanguage) + d->m_debugToolBarLayout->addWidget(widget); + + //Add widget at the end + if (language == AnyLanguage) + d->m_debugToolBarLayout->insertWidget(-1, widget, 10); } QDockWidget *DebuggerMainWindow::dockWidget(const QString &objectName) const @@ -493,7 +522,7 @@ QWidget *DebuggerMainWindow::createContents(IMode *mode) QHBoxLayout *debugToolBarLayout = new QHBoxLayout(debugToolBar); debugToolBarLayout->setMargin(0); debugToolBarLayout->setSpacing(0); - debugToolBarLayout->addWidget(d->m_toolBarStack); + debugToolBarLayout->addWidget(d->m_debugToolBar); debugToolBarLayout->addWidget(new Utils::StyledSeparator); QDockWidget *dock = new QDockWidget(DebuggerMainWindowPrivate::tr("Debugger Toolbar")); @@ -559,6 +588,14 @@ void DebuggerMainWindow::writeSettings() const settings->endGroup(); } +void DebuggerMainWindow::raiseDebuggerWindow() +{ + Core::ICore *core = Core::ICore::instance(); + Utils::AppMainWindow *appMainWindow = qobject_cast<Utils::AppMainWindow*>(core->mainWindow()); + QTC_ASSERT(appMainWindow, return) + appMainWindow->raiseWindow(); +} + void DebuggerMainWindow::readSettings() { QSettings *settings = ICore::settings(); diff --git a/src/plugins/debugger/debuggermainwindow.h b/src/plugins/debugger/debuggermainwindow.h index a43ee833c5..ed82cbdd72 100644 --- a/src/plugins/debugger/debuggermainwindow.h +++ b/src/plugins/debugger/debuggermainwindow.h @@ -45,6 +45,8 @@ class IMode; namespace Debugger { +class DebuggerEngine; + namespace Internal { class DebuggerMainWindowPrivate; } @@ -57,6 +59,8 @@ public: DebuggerMainWindow(); ~DebuggerMainWindow(); + void setCurrentEngine(DebuggerEngine *engine); + // Debugger toolbars are registered with this function. void setToolBar(DebuggerLanguage language, QWidget *widget); @@ -81,6 +85,9 @@ public: void readSettings(); void writeSettings() const; +private slots: + void raiseDebuggerWindow(); + signals: void activeDebugLanguagesChanged(Debugger::DebuggerLanguages); diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 844497c42e..f568d9346c 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -84,7 +84,7 @@ #include <coreplugin/modemanager.h> #include <cppeditor/cppeditorconstants.h> -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <extensionsystem/pluginmanager.h> #include <extensionsystem/invoker.h> @@ -1001,7 +1001,7 @@ public slots: QTC_ASSERT(act, return); const BreakpointModelId id = act->data().value<BreakpointModelId>(); QTC_ASSERT(id > 0, return); - BreakWindow::editBreakpoint(id, mainWindow()); + BreakTreeView::editBreakpoint(id, mainWindow()); } void slotRunToLine() @@ -1169,18 +1169,18 @@ public: Utils::StatusLabel *m_statusLabel; QComboBox *m_threadBox; - BreakWindow *m_breakWindow; + BaseWindow *m_breakWindow; BreakHandler *m_breakHandler; QtMessageLogWindow *m_qtMessageLogWindow; - QTreeView *m_returnWindow; - QTreeView *m_localsWindow; - QTreeView *m_watchersWindow; - QAbstractItemView *m_registerWindow; - QAbstractItemView *m_modulesWindow; - QAbstractItemView *m_snapshotWindow; - SourceFilesWindow *m_sourceFilesWindow; - QAbstractItemView *m_stackWindow; - QAbstractItemView *m_threadsWindow; + WatchWindow *m_returnWindow; + WatchWindow *m_localsWindow; + WatchWindow *m_watchersWindow; + BaseWindow *m_registerWindow; + BaseWindow *m_modulesWindow; + BaseWindow *m_snapshotWindow; + BaseWindow *m_sourceFilesWindow; + BaseWindow *m_stackWindow; + BaseWindow *m_threadsWindow; LogWindow *m_logWindow; bool m_busy; @@ -1339,6 +1339,7 @@ bool DebuggerPluginPrivate::parseArgument(QStringList::const_iterator &it, qulonglong pid = it->toULongLong(); if (pid) { sp.startMode = AttachExternal; + sp.closeMode = DetachAtClose; sp.attachPID = pid; sp.displayName = tr("Process %1").arg(sp.attachPID); sp.startMessage = tr("Attaching to local process %1.").arg(sp.attachPID); @@ -1560,6 +1561,7 @@ void DebuggerPluginPrivate::attachExternalApplication() sp.displayName = tr("Process %1").arg(dlg.attachPID()); sp.executable = dlg.executable(); sp.startMode = AttachExternal; + sp.closeMode = DetachAtClose; sp.toolChainAbi = dlg.abi(); sp.debuggerCommand = dlg.debuggerCommand(); if (DebuggerRunControl *rc = createDebugger(sp)) @@ -1572,6 +1574,7 @@ void DebuggerPluginPrivate::attachExternalApplication(RunControl *rc) sp.attachPID = rc->applicationProcessHandle().pid(); sp.displayName = tr("Debugger attached to %1").arg(rc->displayName()); sp.startMode = AttachExternal; + sp.closeMode = DetachAtClose; sp.toolChainAbi = rc->abi(); if (DebuggerRunControl *rc = createDebugger(sp)) startDebugger(rc); @@ -1617,6 +1620,7 @@ void DebuggerPluginPrivate::attachToRemoteServer(const QString &spec) sp.remoteArchitecture = spec.section(QLatin1Char('@'), 2, 2); sp.displayName = tr("Remote: \"%1\"").arg(sp.remoteChannel); sp.startMode = AttachToRemoteServer; + sp.closeMode = KillAtClose; sp.toolChainAbi = anyAbiOfBinary(sp.executable); if (DebuggerRunControl *rc = createDebugger(sp)) startDebugger(rc); @@ -1630,6 +1634,7 @@ void DebuggerPluginPrivate::startRemoteCdbSession() sp.toolChainAbi = Abi(hostAbi.architecture(), Abi::WindowsOS, Abi::WindowsMsvc2010Flavor, Abi::PEFormat, hostAbi.wordWidth()); sp.startMode = AttachToRemoteServer; + sp.closeMode = KillAtClose; StartRemoteCdbDialog dlg(mainWindow()); QString previousConnection = configValue(connectionKey).toString(); if (previousConnection.isEmpty()) @@ -1666,6 +1671,7 @@ void DebuggerPluginPrivate::attachToRemoteServer() DebuggerStartParameters sp; if (StartRemoteDialog::run(mainWindow(), m_coreSettings, false, &sp)) { sp.startMode = AttachToRemoteServer; + sp.closeMode = KillAtClose; sp.useServerStartScript = false; sp.serverStartScript.clear(); if (RunControl *rc = createDebugger(sp)) @@ -1742,6 +1748,7 @@ void DebuggerPluginPrivate::attachedToProcess(const QString &channel, sp.sysroot = sysroot; sp.executable = localExecutable; sp.startMode = AttachToRemoteServer; + sp.closeMode = KillAtClose; sp.overrideStartScript.clear(); sp.useServerStartScript = false; sp.serverStartScript.clear(); @@ -1785,6 +1792,7 @@ void DebuggerPluginPrivate::attachToQmlPort() sp.sysroot = dlg.sysroot(); sp.startMode = AttachToRemoteServer; + sp.closeMode = KillAtClose; sp.languages = QmlLanguage; // @@ -2114,6 +2122,7 @@ void DebuggerPluginPrivate::connectEngine(DebuggerEngine *engine) engine->watchHandler()->rebuildModel(); mainWindow()->setEngineDebugLanguages(engine->languages()); + mainWindow()->setCurrentEngine(engine); } static void changeFontSize(QWidget *widget, qreal size) @@ -2332,6 +2341,8 @@ void DebuggerPluginPrivate::updateState(DebuggerEngine *engine) m_attachToRemoteServerAction->setEnabled(true); m_attachToRemoteProcessAction->setEnabled(true); + m_threadBox->setEnabled(state == InferiorStopOk); + const bool isCore = engine->startParameters().startMode == AttachCore; const bool stopped = state == InferiorStopOk; const bool detachable = stopped && !isCore; @@ -2897,11 +2908,11 @@ void DebuggerPluginPrivate::extensionsInitialized() m_sourceFilesWindow->setObjectName(QLatin1String(DOCKWIDGET_SOURCE_FILES)); m_threadsWindow = new ThreadsWindow; m_threadsWindow->setObjectName(QLatin1String(DOCKWIDGET_THREADS)); - m_returnWindow = new WatchWindow(WatchWindow::ReturnType); + m_returnWindow = new WatchWindow(WatchTreeView::ReturnType); m_returnWindow->setObjectName(QLatin1String("CppDebugReturn")); - m_localsWindow = new WatchWindow(WatchWindow::LocalsType); + m_localsWindow = new WatchWindow(WatchTreeView::LocalsType); m_localsWindow->setObjectName(QLatin1String("CppDebugLocals")); - m_watchersWindow = new WatchWindow(WatchWindow::WatchersType); + m_watchersWindow = new WatchWindow(WatchTreeView::WatchersType); m_watchersWindow->setObjectName(QLatin1String("CppDebugWatchers")); // Snapshot @@ -3446,9 +3457,9 @@ void DebuggerPluginPrivate::extensionsInitialized() hbox->addWidget(m_threadBox); hbox->addSpacerItem(new QSpacerItem(4, 0)); - hbox->addWidget(m_statusLabel, 10); m_mainWindow->setToolBar(CppLanguage, toolbarContainer); + m_mainWindow->setToolBar(AnyLanguage, m_statusLabel); connect(action(EnableReverseDebugging), SIGNAL(valueChanged(QVariant)), diff --git a/src/plugins/debugger/debuggerplugin.h b/src/plugins/debugger/debuggerplugin.h index c18f93bbe9..4850459572 100644 --- a/src/plugins/debugger/debuggerplugin.h +++ b/src/plugins/debugger/debuggerplugin.h @@ -53,6 +53,7 @@ class DebuggerStartParameters; class DEBUGGER_EXPORT DebuggerPlugin : public ExtensionSystem::IPlugin { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Debugger.json") public: DebuggerPlugin(); diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index fcb8fc788e..f4296747e4 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -167,9 +167,10 @@ public: QString displayName() const { return tr("Debugger Settings"); } private slots: - void useCppDebuggerToggled(bool toggled); - void useQmlDebuggerToggled(bool toggled); + void useCppDebuggerToggled(bool on); + void useQmlDebuggerToggled(bool on); void qmlDebugServerPortChanged(int port); + void useMultiProcessToggled(bool on); public: DebuggerRunConfigurationAspect *m_aspect; // not owned @@ -179,6 +180,7 @@ public: QSpinBox *m_debugServerPort; QLabel *m_debugServerPortLabel; QLabel *m_qmlDebuggerInfoLabel; + QCheckBox *m_useMultiProcess; }; DebuggerRunConfigWidget::DebuggerRunConfigWidget(RunConfiguration *runConfiguration) @@ -204,6 +206,12 @@ DebuggerRunConfigWidget::DebuggerRunConfigWidget(RunConfiguration *runConfigurat m_debugServerPort->setValue(m_aspect->qmlDebugServerPort()); + static const QByteArray env = qgetenv("QTC_DEBUGGER_MULTIPROCESS"); + m_useMultiProcess = + new QCheckBox(tr("Enable Debugging of Subprocesses"), this); + m_useMultiProcess->setChecked(m_aspect->useMultiProcess()); + m_useMultiProcess->setVisible(env.toInt()); + connect(m_qmlDebuggerInfoLabel, SIGNAL(linkActivated(QString)), Core::HelpManager::instance(), SLOT(handleHelpRequest(QString))); connect(m_useQmlDebugger, SIGNAL(toggled(bool)), @@ -212,6 +220,8 @@ DebuggerRunConfigWidget::DebuggerRunConfigWidget(RunConfiguration *runConfigurat SLOT(useCppDebuggerToggled(bool))); connect(m_debugServerPort, SIGNAL(valueChanged(int)), SLOT(qmlDebugServerPortChanged(int))); + connect(m_useMultiProcess, SIGNAL(toggled(bool)), + SLOT(useMultiProcessToggled(bool))); if (m_aspect->isDisplaySuppressed()) hide(); @@ -242,6 +252,7 @@ DebuggerRunConfigWidget::DebuggerRunConfigWidget(RunConfiguration *runConfigurat layout->setMargin(0); layout->addWidget(m_useCppDebugger); layout->addLayout(qmlLayout); + layout->addWidget(m_useMultiProcess); setLayout(layout); } @@ -250,25 +261,30 @@ void DebuggerRunConfigWidget::qmlDebugServerPortChanged(int port) m_aspect->m_qmlDebugServerPort = port; } -void DebuggerRunConfigWidget::useCppDebuggerToggled(bool toggled) +void DebuggerRunConfigWidget::useCppDebuggerToggled(bool on) { - m_aspect->m_useCppDebugger = toggled; - if (!toggled && !m_useQmlDebugger->isChecked()) + m_aspect->m_useCppDebugger = on; + if (!on && !m_useQmlDebugger->isChecked()) m_useQmlDebugger->setChecked(true); } -void DebuggerRunConfigWidget::useQmlDebuggerToggled(bool toggled) +void DebuggerRunConfigWidget::useQmlDebuggerToggled(bool on) { - m_debugServerPort->setEnabled(toggled); - m_debugServerPortLabel->setEnabled(toggled); + m_debugServerPort->setEnabled(on); + m_debugServerPortLabel->setEnabled(on); - m_aspect->m_useQmlDebugger = toggled + m_aspect->m_useQmlDebugger = on ? DebuggerRunConfigurationAspect::EnableQmlDebugger : DebuggerRunConfigurationAspect::DisableQmlDebugger; - if (!toggled && !m_useCppDebugger->isChecked()) + if (!on && !m_useCppDebugger->isChecked()) m_useCppDebugger->setChecked(true); } +void DebuggerRunConfigWidget::useMultiProcessToggled(bool on) +{ + m_aspect->m_useMultiProcess = on; +} + //////////////////////////////////////////////////////////////////////// // // DebuggerRunControlPrivate @@ -900,12 +916,15 @@ static DebuggerStartParameters localStartParameters(RunConfiguration *runConfigu } } - if (runConfiguration->debuggerAspect()->useCppDebugger()) + DebuggerRunConfigurationAspect *aspect = runConfiguration->debuggerAspect(); + sp.multiProcess = aspect->useMultiProcess(); + + if (aspect->useCppDebugger()) sp.languages |= CppLanguage; - if (runConfiguration->debuggerAspect()->useQmlDebugger()) { + if (aspect->useQmlDebugger()) { sp.qmlServerAddress = _("127.0.0.1"); - sp.qmlServerPort = runConfiguration->debuggerAspect()->qmlDebugServerPort(); + sp.qmlServerPort = aspect->qmlDebugServerPort(); sp.languages |= QmlLanguage; // Makes sure that all bindings go through the JavaScript engine, so that diff --git a/src/plugins/debugger/debuggerstartparameters.h b/src/plugins/debugger/debuggerstartparameters.h index 6c556d222e..513bdea8e1 100644 --- a/src/plugins/debugger/debuggerstartparameters.h +++ b/src/plugins/debugger/debuggerstartparameters.h @@ -61,13 +61,14 @@ public: attachPID(-1), useTerminal(false), breakOnMain(false), + multiProcess(false), languages(AnyLanguage), qmlServerAddress(QLatin1String("127.0.0.1")), qmlServerPort(ProjectExplorer::Constants::QML_DEFAULT_DEBUG_SERVER_PORT), useServerStartScript(false), - connParams(Utils::SshConnectionParameters::NoProxy), requestRemoteSetup(false), startMode(NoStartMode), + closeMode(KillAtClose), executableUid(0), communicationChannel(CommunicationChannelTcpIp), serverPort(0), @@ -88,6 +89,7 @@ public: qint64 attachPID; bool useTerminal; bool breakOnMain; + bool multiProcess; DebuggerLanguages languages; // Used by AttachCrashedExternal. @@ -126,6 +128,7 @@ public: QString dumperLibrary; QStringList dumperLibraryLocations; DebuggerStartMode startMode; + DebuggerCloseMode closeMode; // For Symbian debugging. quint32 executableUid; diff --git a/src/plugins/debugger/gdb/abstractgdbadapter.h b/src/plugins/debugger/gdb/abstractgdbadapter.h index 05410a9d61..51ed0bf5c5 100644 --- a/src/plugins/debugger/gdb/abstractgdbadapter.h +++ b/src/plugins/debugger/gdb/abstractgdbadapter.h @@ -75,7 +75,6 @@ public: virtual void setupInferior() = 0; virtual void runEngine() = 0; virtual void interruptInferior() = 0; - virtual void shutdownInferior() = 0; virtual void shutdownAdapter() = 0; virtual AbstractGdbProcess *gdbProc() = 0; diff --git a/src/plugins/debugger/gdb/attachgdbadapter.cpp b/src/plugins/debugger/gdb/attachgdbadapter.cpp index 6e1f91f175..28c722a4e0 100644 --- a/src/plugins/debugger/gdb/attachgdbadapter.cpp +++ b/src/plugins/debugger/gdb/attachgdbadapter.cpp @@ -116,11 +116,6 @@ void AttachGdbAdapter::interruptInferior() interruptLocalInferior(startParameters().attachPID); } -void AttachGdbAdapter::shutdownInferior() -{ - m_engine->defaultInferiorShutdown("detach"); -} - void AttachGdbAdapter::shutdownAdapter() { m_engine->notifyAdapterShutdownOk(); diff --git a/src/plugins/debugger/gdb/attachgdbadapter.h b/src/plugins/debugger/gdb/attachgdbadapter.h index 01a6feb9fc..e9a41ac49d 100644 --- a/src/plugins/debugger/gdb/attachgdbadapter.h +++ b/src/plugins/debugger/gdb/attachgdbadapter.h @@ -59,7 +59,6 @@ private: void setupInferior(); void runEngine(); void interruptInferior(); - void shutdownInferior(); void shutdownAdapter(); AbstractGdbProcess *gdbProc() { return &m_gdbProc; } diff --git a/src/plugins/debugger/gdb/codagdbadapter.cpp b/src/plugins/debugger/gdb/codagdbadapter.cpp index 1cc5135f5e..1049e4a2f5 100644 --- a/src/plugins/debugger/gdb/codagdbadapter.cpp +++ b/src/plugins/debugger/gdb/codagdbadapter.cpp @@ -1237,11 +1237,6 @@ void CodaGdbAdapter::cleanup() } } -void CodaGdbAdapter::shutdownInferior() -{ - m_engine->defaultInferiorShutdown("kill"); -} - void CodaGdbAdapter::shutdownAdapter() { if (m_gdbProc.state() == QProcess::Running) { diff --git a/src/plugins/debugger/gdb/codagdbadapter.h b/src/plugins/debugger/gdb/codagdbadapter.h index d517cdedaf..56efb451a8 100644 --- a/src/plugins/debugger/gdb/codagdbadapter.h +++ b/src/plugins/debugger/gdb/codagdbadapter.h @@ -114,7 +114,6 @@ private: void setupInferior(); void runEngine(); void interruptInferior(); - void shutdownInferior(); void shutdownAdapter(); void sendRunControlTerminateCommand(); void handleRunControlTerminate(const Coda::CodaCommandResult &); diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 6af9fe4049..0b31cef073 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -72,14 +72,18 @@ #include <coreplugin/icore.h> #include <coreplugin/idocument.h> +#include <extensionsystem/pluginmanager.h> #include <projectexplorer/abi.h> #include <projectexplorer/projectexplorerconstants.h> +#include <projectexplorer/taskhub.h> +#include <projectexplorer/itaskhandler.h> #include <texteditor/itexteditor.h> #include <utils/qtcassert.h> #include <QCoreApplication> #include <QDebug> #include <QDir> +#include <QDirIterator> #include <QFileInfo> #include <QMetaObject> #include <QTime> @@ -180,6 +184,52 @@ static QByteArray parsePlainConsoleStream(const GdbResponse &response) /////////////////////////////////////////////////////////////////////// // +// Debuginfo Taskhandler +// +/////////////////////////////////////////////////////////////////////// + +class DebugInfoTask +{ +public: + QString command; +}; + +class DebugInfoTaskHandler : public ProjectExplorer::ITaskHandler +{ +public: + DebugInfoTaskHandler(GdbEngine *engine) + : ITaskHandler(_("Debuginfo")), m_engine(engine) + {} + + bool canHandle(const Task &task) + { + return m_debugInfoTasks.contains(task.taskId); + } + + void handle(const Task &task) + { + m_engine->requestDebugInformation(m_debugInfoTasks.value(task.taskId)); + } + + void addTask(unsigned id, const DebugInfoTask &task) + { + m_debugInfoTasks[id] = task; + } + + QAction *createAction(QObject *parent = 0) + { + QAction *action = new QAction(tr("Install &Debug Information"), parent); + action->setToolTip(tr("This tries to install missing debug information.")); + return action; + } + +private: + GdbEngine *m_engine; + QHash<unsigned, DebugInfoTask> m_debugInfoTasks; +}; + +/////////////////////////////////////////////////////////////////////// +// // GdbEngine // /////////////////////////////////////////////////////////////////////// @@ -217,6 +267,9 @@ GdbEngine::GdbEngine(const DebuggerStartParameters &startParameters, m_gdbAdapter = createAdapter(); + m_debugInfoTaskHandler = new DebugInfoTaskHandler(this); + ExtensionSystem::PluginManager::instance()->addObject(m_debugInfoTaskHandler); + m_commandTimer.setSingleShot(true); connect(&m_commandTimer, SIGNAL(timeout()), SLOT(commandTimeout())); @@ -238,6 +291,10 @@ AbstractGdbProcess *GdbEngine::gdbProc() const GdbEngine::~GdbEngine() { + ExtensionSystem::PluginManager::instance()->removeObject(m_debugInfoTaskHandler); + delete m_debugInfoTaskHandler; + m_debugInfoTaskHandler = 0; + // Prevent sending error messages afterwards. if (m_gdbAdapter) disconnect(gdbProc(), 0, this, 0); @@ -422,6 +479,7 @@ void GdbEngine::handleResponse(const QByteArray &buff) } if (pid) notifyInferiorPid(pid); + handleThreadGroupCreated(result); } else if (asyncClass == "thread-created") { //"{id="1",group-id="28902"}" QByteArray id = result.findChild("id").data(); @@ -430,6 +488,7 @@ void GdbEngine::handleResponse(const QByteArray &buff) // Archer has "{id="28902"}" QByteArray id = result.findChild("id").data(); showStatusMessage(tr("Thread group %1 exited").arg(_(id)), 1000); + handleThreadGroupExited(result); } else if (asyncClass == "thread-exited") { //"{id="1",group-id="28902"}" QByteArray id = result.findChild("id").data(); @@ -607,6 +666,34 @@ void GdbEngine::handleResponse(const QByteArray &buff) // version and/or OS version used. if (data.startsWith("warning:")) showMessage(_(data.mid(9)), AppStuff); // Cut "warning: " + + // Messages when the target exits (gdbserver) + if (data.trimmed() == "Remote connection closed" + || data.trimmed() == "Remote communication error. " + "Target disconnected.: No error." + || data.trimmed() == "Quit") { + notifyInferiorExited(); + } + + // From SuSE's gdb: >&"Missing separate debuginfo for ...\n" + // ">&"Try: zypper install -C \"debuginfo(build-id)=c084ee5876ed1ac12730181c9f07c3e027d8e943\"\n" + if (data.startsWith("Missing separate debuginfo for ")) { + m_lastMissingDebugInfo = QString::fromLocal8Bit(data.mid(32)); + } else if (data.startsWith("Try: zypper")) { + QString cmd = QString::fromLocal8Bit(data.mid(4)); + + Task task(Task::Warning, + tr("Missing debug information for %1\nTry: %2") + .arg(m_lastMissingDebugInfo).arg(cmd), + Utils::FileName(), 0, Core::Id("Debuginfo")); + + taskHub()->addTask(task); + + DebugInfoTask dit; + dit.command = cmd; + m_debugInfoTaskHandler->addTask(task.taskId, dit); + } + break; } @@ -1025,10 +1112,6 @@ void GdbEngine::handleResultRecord(GdbResponse *response) QTC_CHECK(state() == InferiorRunOk); notifyInferiorSpontaneousStop(); notifyEngineIll(); - } else if (msg.startsWith("Remote connection closed") - || msg.startsWith("Quit")) { - // Can happen when the target exits (gdbserver) - notifyInferiorExited(); } else { // Windows: Some DLL or some function not found. Report // the exception now in a box. @@ -1171,7 +1254,6 @@ void GdbEngine::updateAll() void GdbEngine::handleQuerySources(const GdbResponse &response) { m_sourcesListUpdating = false; - m_sourcesListOutdated = false; if (response.resultClass == GdbResultDone) { QMap<QString, QString> oldShortToFull = m_shortToFullName; m_shortToFullName.clear(); @@ -1180,16 +1262,17 @@ void GdbEngine::handleQuerySources(const GdbResponse &response) // fullname="/data5/dev/ide/main/bin/dumper/dumper.cpp"}, GdbMi files = response.data.findChild("files"); foreach (const GdbMi &item, files.children()) { - GdbMi fullName = item.findChild("fullname"); GdbMi fileName = item.findChild("file"); + if (fileName.data().endsWith("<built-in>")) + continue; + GdbMi fullName = item.findChild("fullname"); QString file = QString::fromLocal8Bit(fileName.data()); + QString full; if (fullName.isValid()) { - QString full = cleanupFullName(QString::fromLocal8Bit(fullName.data())); - m_shortToFullName[file] = full; + full = cleanupFullName(QString::fromLocal8Bit(fullName.data())); m_fullToShortName[full] = file; - } else if (fileName.isValid()) { - m_shortToFullName[file] = tr("<unknown>"); } + m_shortToFullName[file] = full; } if (m_shortToFullName != oldShortToFull) sourceFilesHandler()->setSourceFiles(m_shortToFullName); @@ -1722,6 +1805,11 @@ void GdbEngine::handleShowVersion(const GdbResponse &response) postCommand("set target-async on", ConsoleCommand); else postCommand("set target-async off", ConsoleCommand); + + if (startParameters().multiProcess) + postCommand("set detach-on-fork off", ConsoleCommand); + + postCommand("set build-id-verbose 2", ConsoleCommand); } } @@ -1846,6 +1934,43 @@ QString GdbEngine::cleanupFullName(const QString &fileName) cleanFilePath.replace(0, startParameters().remoteMountPoint.length(), startParameters().localMountDir); } + + if (!debuggerCore()->boolSetting(AutoEnrichParameters)) + return cleanFilePath; + + const QString sysroot = startParameters().sysroot; + if (QFileInfo(cleanFilePath).isReadable()) + return cleanFilePath; + if (!sysroot.isEmpty() && fileName.startsWith(QLatin1Char('/'))) { + cleanFilePath = sysroot + fileName; + if (QFileInfo(cleanFilePath).isReadable()) + return cleanFilePath; + } + if (m_baseNameToFullName.isEmpty()) { + QString debugSource = sysroot + QLatin1String("/usr/src/debug"); + if (QFileInfo(debugSource).isDir()) { + QDirIterator it(debugSource, QDirIterator::Subdirectories); + while (it.hasNext()) { + it.next(); + QString name = it.fileName(); + if (!name.startsWith(QLatin1Char('.'))) { + QString path = it.filePath(); + m_baseNameToFullName.insert(name, path); + } + } + } + } + + cleanFilePath.clear(); + const QString base = QFileInfo(fileName).fileName(); + + QMap<QString, QString>::const_iterator jt = m_baseNameToFullName.find(base); + while (jt != m_baseNameToFullName.end() && jt.key() == base) { + // FIXME: Use some heuristics to find the "best" match. + return jt.value(); + //++jt; + } + return cleanFilePath; } @@ -1853,13 +1978,15 @@ void GdbEngine::shutdownInferior() { QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state()); m_commandsToRunOnTemporaryBreak.clear(); - m_gdbAdapter->shutdownInferior(); -} - -void GdbEngine::defaultInferiorShutdown(const char *cmd) -{ - QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state()); - postCommand(cmd, NeedsStop | LosesChild, CB(handleInferiorShutdown)); + switch (startParameters().closeMode) { + case KillAtClose: + postCommand("kill", NeedsStop | LosesChild, CB(handleInferiorShutdown)); + return; + case DetachAtClose: + postCommand("detach", NeedsStop | LosesChild, CB(handleInferiorShutdown)); + return; + } + QTC_ASSERT(false, notifyInferiorShutdownFailed()); } void GdbEngine::handleInferiorShutdown(const GdbResponse &response) @@ -1946,6 +2073,18 @@ void GdbEngine::handleDetach(const GdbResponse &response) notifyInferiorExited(); } +void GdbEngine::handleThreadGroupCreated(const GdbMi &result) +{ + QByteArray id = result.findChild("id").data(); + QByteArray pid = result.findChild("pid").data(); + Q_UNUSED(pid); +} + +void GdbEngine::handleThreadGroupExited(const GdbMi &result) +{ + QByteArray id = result.findChild("id").data(); +} + int GdbEngine::currentFrame() const { return stackHandler()->currentIndex(); @@ -3372,7 +3511,6 @@ void GdbEngine::examineModules() void GdbEngine::invalidateSourcesList() { m_modulesListOutdated = true; - m_sourcesListOutdated = true; m_breakListOutdated = true; } @@ -5173,6 +5311,11 @@ void GdbEngine::scheduleTestResponse(int testCase, const QByteArray &response) m_scheduledTestResponses[token] = response; } +void GdbEngine::requestDebugInformation(const DebugInfoTask &task) +{ + QProcess::startDetached(task.command); +} + // // Factory // diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index 08d4e0b17a..48551cd682 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -57,6 +57,8 @@ namespace Internal { class AbstractGdbAdapter; class AbstractGdbProcess; +class DebugInfoTask; +class DebugInfoTaskHandler; class GdbResponse; class GdbMi; class GdbToolTipContext; @@ -264,7 +266,6 @@ private: ////////// Gdb Process Management ////////// void handleNamespaceExtraction(const GdbResponse &response); void handleAdapterStarted(); - void defaultInferiorShutdown(const char *cmd); void loadInitScript(); void loadPythonDumpers(); void pythonDumpersFailed(); @@ -584,9 +585,9 @@ private: ////////// View & Data Stuff ////////// // awful hack to keep track of used files QMap<QString, QString> m_shortToFullName; QMap<QString, QString> m_fullToShortName; + QMultiMap<QString, QString> m_baseNameToFullName; void invalidateSourcesList(); - bool m_sourcesListOutdated; bool m_sourcesListUpdating; bool m_breakListOutdated; @@ -656,6 +657,9 @@ private: ////////// View & Data Stuff ////////// void handleDebuggingHelperVersionCheckClassic(const GdbResponse &response); void handleDetach(const GdbResponse &response); + void handleThreadGroupCreated(const GdbMi &result); + void handleThreadGroupExited(const GdbMi &result); + Q_SLOT void createFullBacktrace(); void handleCreateFullBacktrace(const GdbResponse &response); @@ -729,6 +733,7 @@ private: ////////// View & Data Stuff ////////// // HACK: QByteArray m_currentThread; QString m_lastWinException; + QString m_lastMissingDebugInfo; BreakpointResponseId m_qFatalBreakpointResponseId; bool m_actingOnExpectedStop; @@ -736,6 +741,11 @@ private: ////////// View & Data Stuff ////////// QHash<int, QByteArray> m_scheduledTestResponses; QSet<int> m_testCases; + + // Debug information + friend class DebugInfoTaskHandler; + void requestDebugInformation(const DebugInfoTask &task); + DebugInfoTaskHandler *m_debugInfoTaskHandler; }; } // namespace Internal diff --git a/src/plugins/debugger/gdb/localplaingdbadapter.cpp b/src/plugins/debugger/gdb/localplaingdbadapter.cpp index 0b0060ffa6..1e0ad9ff24 100644 --- a/src/plugins/debugger/gdb/localplaingdbadapter.cpp +++ b/src/plugins/debugger/gdb/localplaingdbadapter.cpp @@ -114,11 +114,6 @@ void LocalPlainGdbAdapter::runEngine() AbstractPlainGdbAdapter::runEngine(); } -void LocalPlainGdbAdapter::shutdownInferior() -{ - m_engine->defaultInferiorShutdown("kill"); -} - void LocalPlainGdbAdapter::shutdownAdapter() { showMessage(_("PLAIN ADAPTER SHUTDOWN %1").arg(state())); diff --git a/src/plugins/debugger/gdb/localplaingdbadapter.h b/src/plugins/debugger/gdb/localplaingdbadapter.h index ced097faac..39181bac7e 100644 --- a/src/plugins/debugger/gdb/localplaingdbadapter.h +++ b/src/plugins/debugger/gdb/localplaingdbadapter.h @@ -58,7 +58,6 @@ private: void setupInferior(); void runEngine(); void interruptInferior(); - void shutdownInferior(); void shutdownAdapter(); DumperHandling dumperHandling() const; diff --git a/src/plugins/debugger/gdb/remotegdbserveradapter.cpp b/src/plugins/debugger/gdb/remotegdbserveradapter.cpp index 9cd71bd3a9..174fbb9069 100644 --- a/src/plugins/debugger/gdb/remotegdbserveradapter.cpp +++ b/src/plugins/debugger/gdb/remotegdbserveradapter.cpp @@ -233,9 +233,16 @@ void RemoteGdbServerAdapter::handleFileExecAndSymbols(const GdbResponse &respons if (response.resultClass == GdbResultDone) { callTargetRemote(); } else { + QByteArray reason = response.data.findChild("msg").data(); QString msg = tr("Reading debug information failed:\n"); - msg += QString::fromLocal8Bit(response.data.findChild("msg").data()); - m_engine->notifyInferiorSetupFailed(msg); + msg += QString::fromLocal8Bit(reason); + if (reason.endsWith("No such file or directory.")) { + showMessage(_("INFERIOR STARTUP: BINARY NOT FOUND")); + showMessage(msg, StatusBar); + callTargetRemote(); // Proceed nevertheless. + } else { + m_engine->notifyInferiorSetupFailed(msg); + } } } @@ -247,14 +254,24 @@ void RemoteGdbServerAdapter::callTargetRemote() // (1) connects to the gdb server // (2) starts the remote application // (3) stops the remote application (early, e.g. in the dynamic linker) - QString channel = startParameters().remoteChannel; - if (m_engine->m_isQnxGdb) { - m_engine->postCommand("target qnx " + channel.toLatin1(), - CB(handleTargetQnx)); - } else { - m_engine->postCommand("target remote " + channel.toLatin1(), - CB(handleTargetRemote)); + QByteArray channel = startParameters().remoteChannel.toLatin1(); + + // Don't touch channels with explicitly set protocols. + if (!channel.startsWith("tcp:") && !channel.startsWith("udp:") + && !channel.startsWith("file:") && channel.contains(':')) + { + // "Fix" the IPv6 case with host names without '['...']' + if (!channel.startsWith('[') && channel.count(':') >= 2) { + channel.insert(0, '['); + channel.insert(channel.lastIndexOf(':'), ']'); + } + channel = "tcp:" + channel; } + + if (m_engine->m_isQnxGdb) + m_engine->postCommand("target qnx " + channel, CB(handleTargetQnx)); + else + m_engine->postCommand("target remote " + channel, CB(handleTargetRemote)); } void RemoteGdbServerAdapter::handleTargetRemote(const GdbResponse &record) @@ -355,14 +372,6 @@ void RemoteGdbServerAdapter::handleInterruptInferior(const GdbResponse &response } } -void RemoteGdbServerAdapter::shutdownInferior() -{ - if (m_engine->startParameters().startMode == AttachToRemoteServer) - m_engine->defaultInferiorShutdown("detach"); - else - m_engine->defaultInferiorShutdown("kill"); -} - void RemoteGdbServerAdapter::shutdownAdapter() { m_engine->notifyAdapterShutdownOk(); diff --git a/src/plugins/debugger/gdb/remotegdbserveradapter.h b/src/plugins/debugger/gdb/remotegdbserveradapter.h index 9261797d6d..7a3f88d642 100644 --- a/src/plugins/debugger/gdb/remotegdbserveradapter.h +++ b/src/plugins/debugger/gdb/remotegdbserveradapter.h @@ -59,7 +59,6 @@ private: void setupInferior(); void runEngine(); void interruptInferior(); - void shutdownInferior(); void shutdownAdapter(); AbstractGdbProcess *gdbProc() { return &m_gdbProc; } diff --git a/src/plugins/debugger/gdb/remoteplaingdbadapter.cpp b/src/plugins/debugger/gdb/remoteplaingdbadapter.cpp index 5913ade032..a3a7263b14 100644 --- a/src/plugins/debugger/gdb/remoteplaingdbadapter.cpp +++ b/src/plugins/debugger/gdb/remoteplaingdbadapter.cpp @@ -98,11 +98,6 @@ void RemotePlainGdbAdapter::handleApplicationOutput(const QByteArray &output) showMessage(QString::fromUtf8(output), AppOutput); } -void RemotePlainGdbAdapter::shutdownInferior() -{ - m_engine->defaultInferiorShutdown("kill"); -} - void RemotePlainGdbAdapter::shutdownAdapter() { m_engine->notifyAdapterShutdownOk(); diff --git a/src/plugins/debugger/gdb/remoteplaingdbadapter.h b/src/plugins/debugger/gdb/remoteplaingdbadapter.h index b1e7644574..7c19e10df8 100644 --- a/src/plugins/debugger/gdb/remoteplaingdbadapter.h +++ b/src/plugins/debugger/gdb/remoteplaingdbadapter.h @@ -55,7 +55,6 @@ private: void startAdapter(); void setupInferior(); void interruptInferior(); - void shutdownInferior(); void shutdownAdapter(); void handleRemoteSetupDone(int gdbServerPort, int qmlPort); void handleRemoteSetupFailed(const QString &reason); diff --git a/src/plugins/debugger/gdb/termgdbadapter.cpp b/src/plugins/debugger/gdb/termgdbadapter.cpp index 8acff6ede4..135630e875 100644 --- a/src/plugins/debugger/gdb/termgdbadapter.cpp +++ b/src/plugins/debugger/gdb/termgdbadapter.cpp @@ -210,11 +210,6 @@ void TermGdbAdapter::stubExited() m_engine->notifyEngineIll(); } -void TermGdbAdapter::shutdownInferior() -{ - m_engine->defaultInferiorShutdown("kill"); -} - void TermGdbAdapter::shutdownAdapter() { m_engine->notifyAdapterShutdownOk(); diff --git a/src/plugins/debugger/gdb/termgdbadapter.h b/src/plugins/debugger/gdb/termgdbadapter.h index d9ecee078d..b56d969cd2 100644 --- a/src/plugins/debugger/gdb/termgdbadapter.h +++ b/src/plugins/debugger/gdb/termgdbadapter.h @@ -62,7 +62,6 @@ private: void setupInferior(); void runEngine(); void interruptInferior(); - void shutdownInferior(); void shutdownAdapter(); AbstractGdbProcess *gdbProc() { return &m_gdbProc; } diff --git a/src/plugins/debugger/lldb/ipcenginehost.cpp b/src/plugins/debugger/lldb/ipcenginehost.cpp index 1c6765f4fc..73a01839de 100644 --- a/src/plugins/debugger/lldb/ipcenginehost.cpp +++ b/src/plugins/debugger/lldb/ipcenginehost.cpp @@ -591,7 +591,7 @@ void IPCEngineHost::rpcCallback(quint64 f, QByteArray payload) } } -void IPCEngineHost::m_stateChanged(const Debugger::DebuggerState &state) +void IPCEngineHost::m_stateChanged(Debugger::DebuggerState state) { QByteArray p; { diff --git a/src/plugins/debugger/lldb/ipcenginehost.h b/src/plugins/debugger/lldb/ipcenginehost.h index b75e1ceeaa..71756c02f2 100644 --- a/src/plugins/debugger/lldb/ipcenginehost.h +++ b/src/plugins/debugger/lldb/ipcenginehost.h @@ -124,7 +124,7 @@ protected: public slots: void rpcCallback(quint64 f, QByteArray payload = QByteArray()); private slots: - void m_stateChanged(const Debugger::DebuggerState &state); + void m_stateChanged(Debugger::DebuggerState state); void readyRead(); private: IPCEngineGuest *m_localGuest; diff --git a/src/plugins/debugger/moduleswindow.cpp b/src/plugins/debugger/moduleswindow.cpp index 70948ed429..3c7daa1838 100644 --- a/src/plugins/debugger/moduleswindow.cpp +++ b/src/plugins/debugger/moduleswindow.cpp @@ -57,10 +57,9 @@ namespace Debugger { namespace Internal { -ModulesWindow::ModulesWindow(QWidget *parent) - : BaseWindow(parent) +ModulesTreeView::ModulesTreeView(QWidget *parent) + : BaseTreeView(parent) { - setWindowTitle(tr("Modules")); setSortingEnabled(true); setAlwaysAdjustColumnsAction(debuggerCore()->action(AlwaysAdjustModulesColumnWidths)); @@ -68,7 +67,7 @@ ModulesWindow::ModulesWindow(QWidget *parent) SLOT(moduleActivated(QModelIndex))); } -void ModulesWindow::moduleActivated(const QModelIndex &index) +void ModulesTreeView::moduleActivated(const QModelIndex &index) { DebuggerEngine *engine = debuggerCore()->currentEngine(); QTC_ASSERT(engine, return); @@ -76,7 +75,7 @@ void ModulesWindow::moduleActivated(const QModelIndex &index) engine->gotoLocation(index.sibling(index.row(), 1).data().toString()); } -void ModulesWindow::contextMenuEvent(QContextMenuEvent *ev) +void ModulesTreeView::contextMenuEvent(QContextMenuEvent *ev) { QString name; QString fileName; @@ -174,5 +173,11 @@ void ModulesWindow::contextMenuEvent(QContextMenuEvent *ev) handleBaseContextAction(act); } +ModulesWindow::ModulesWindow() + : BaseWindow(new ModulesTreeView) +{ + setWindowTitle(tr("Modules")); +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/moduleswindow.h b/src/plugins/debugger/moduleswindow.h index 41a8d11ef8..e80ec0823c 100644 --- a/src/plugins/debugger/moduleswindow.h +++ b/src/plugins/debugger/moduleswindow.h @@ -38,12 +38,12 @@ namespace Debugger { namespace Internal { -class ModulesWindow : public BaseWindow +class ModulesTreeView : public BaseTreeView { Q_OBJECT public: - explicit ModulesWindow(QWidget *parent = 0); + explicit ModulesTreeView(QWidget *parent = 0); private slots: void moduleActivated(const QModelIndex &index); @@ -52,6 +52,12 @@ private: void contextMenuEvent(QContextMenuEvent *ev); }; +class ModulesWindow : public BaseWindow +{ +public: + ModulesWindow(); +}; + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/qml/qmladapter.cpp b/src/plugins/debugger/qml/qmladapter.cpp index 7ab699eb19..46d9cdcb9d 100644 --- a/src/plugins/debugger/qml/qmladapter.cpp +++ b/src/plugins/debugger/qml/qmladapter.cpp @@ -67,7 +67,7 @@ public: QWeakPointer<DebuggerEngine> m_engine; QmlDebuggerClient *m_qmlClient; - QmlJsDebugClient::QDeclarativeEngineDebug *m_engineDebugClient; + QmlJsDebugClient::QmlEngineDebugClient *m_engineDebugClient; QTimer m_connectionTimer; QDeclarativeDebugConnection *m_conn; QHash<QString, QmlDebuggerClient*> debugClients; @@ -304,14 +304,24 @@ QHash<QString, Internal::QmlDebuggerClient*> QmlAdapter::debuggerClients() return d->debugClients; } -QmlJsDebugClient::QDeclarativeEngineDebug *QmlAdapter::engineDebugClient() const +QmlJsDebugClient::QmlEngineDebugClient *QmlAdapter::engineDebugClient() const { return d->m_engineDebugClient; } -void QmlAdapter::setEngineDebugClient(QmlJsDebugClient::QDeclarativeEngineDebug *client) +void QmlAdapter::setEngineDebugClient(QmlJsDebugClient::QmlEngineDebugClient *client) { + Internal::QmlEngine *engine = + qobject_cast<Internal::QmlEngine *>(d->m_engine.data()); + if (engine && d->m_engineDebugClient) + disconnect(d->m_engineDebugClient, SIGNAL(result(quint32,QVariant,QByteArray)), + engine, + SLOT(expressionEvaluated(quint32,QVariant))); d->m_engineDebugClient = client; + if (engine && d->m_engineDebugClient) + connect(d->m_engineDebugClient, SIGNAL(result(quint32,QVariant,QByteArray)), + engine, + SLOT(expressionEvaluated(quint32,QVariant))); } QmlJsDebugClient::QDebugMessageClient *QmlAdapter::messageClient() const diff --git a/src/plugins/debugger/qml/qmladapter.h b/src/plugins/debugger/qml/qmladapter.h index 9abaf2d5aa..8851518836 100644 --- a/src/plugins/debugger/qml/qmladapter.h +++ b/src/plugins/debugger/qml/qmladapter.h @@ -40,7 +40,7 @@ #include <QAbstractSocket> namespace QmlJsDebugClient { -class QDeclarativeEngineDebug; +class QmlEngineDebugClient; class QDeclarativeDebugConnection; class QDebugMessageClient; } @@ -76,8 +76,8 @@ public: Internal::QmlDebuggerClient *activeDebuggerClient(); QHash<QString, Internal::QmlDebuggerClient*> debuggerClients(); - QmlJsDebugClient::QDeclarativeEngineDebug *engineDebugClient() const; - void setEngineDebugClient(QmlJsDebugClient::QDeclarativeEngineDebug *client); + QmlJsDebugClient::QmlEngineDebugClient *engineDebugClient() const; + void setEngineDebugClient(QmlJsDebugClient::QmlEngineDebugClient *client); QDebugMessageClient *messageClient() const; diff --git a/src/plugins/debugger/qml/qmlcppengine.cpp b/src/plugins/debugger/qml/qmlcppengine.cpp index 2ee94881b6..890789fe86 100644 --- a/src/plugins/debugger/qml/qmlcppengine.cpp +++ b/src/plugins/debugger/qml/qmlcppengine.cpp @@ -40,6 +40,9 @@ #include <coreplugin/icore.h> #include <utils/qtcassert.h> +#include <texteditor/itexteditor.h> +#include <qmljseditor/qmljseditorconstants.h> +#include <cppeditor/cppeditorconstants.h> #include <QTimer> #include <QMainWindow> @@ -127,10 +130,20 @@ QmlCppEngine::~QmlCppEngine() delete d; } +bool QmlCppEngine::canDisplayTooltip() const +{ + return d->m_cppEngine->canDisplayTooltip() || d->m_qmlEngine->canDisplayTooltip(); +} + bool QmlCppEngine::setToolTipExpression(const QPoint & mousePos, TextEditor::ITextEditor *editor, const DebuggerToolTipContext &ctx) { - return d->m_activeEngine->setToolTipExpression(mousePos, editor, ctx); + bool success = false; + if (editor->id() == CppEditor::Constants::CPPEDITOR_ID) + success = d->m_cppEngine->setToolTipExpression(mousePos, editor, ctx); + else if (editor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) + success = d->m_qmlEngine->setToolTipExpression(mousePos, editor, ctx); + return success; } void QmlCppEngine::updateWatchData(const WatchData &data, @@ -216,9 +229,14 @@ bool QmlCppEngine::hasCapability(unsigned cap) const // ### this could also be an OR of both engines' capabilities bool hasCap = d->m_cppEngine->hasCapability(cap); if (d->m_activeEngine != d->m_cppEngine) { + //Some capabilities cannot be handled by QML Engine + //Expand this list as and when required if (cap == AddWatcherWhileRunningCapability) hasCap = hasCap || d->m_qmlEngine->hasCapability(cap); - if (cap == WatchWidgetsCapability) + if (cap == WatchWidgetsCapability || + cap == DisassemblerCapability || + cap == OperateByInstructionCapability || + cap == ReverseSteppingCapability) hasCap = hasCap && d->m_qmlEngine->hasCapability(cap); } return hasCap; @@ -268,7 +286,7 @@ bool QmlCppEngine::acceptsBreakpoint(BreakpointModelId id) const void QmlCppEngine::selectThread(int index) { - d->m_cppEngine->selectThread(index); + d->m_activeEngine->selectThread(index); } void QmlCppEngine::assignValueInDebugger(const WatchData *data, diff --git a/src/plugins/debugger/qml/qmlcppengine.h b/src/plugins/debugger/qml/qmlcppengine.h index efddd12f85..7d3483ed0a 100644 --- a/src/plugins/debugger/qml/qmlcppengine.h +++ b/src/plugins/debugger/qml/qmlcppengine.h @@ -50,6 +50,7 @@ public: QString *errorMessage); ~QmlCppEngine(); + bool canDisplayTooltip() const; bool setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor * editor, const DebuggerToolTipContext &); void updateWatchData(const WatchData &data, diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index abc050cf4c..f0e6ebc572 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -57,6 +57,7 @@ #include <extensionsystem/pluginmanager.h> #include <projectexplorer/applicationlauncher.h> #include <qmljsdebugclient/qdeclarativeoutputparser.h> +#include <qmljsdebugclient/qmlenginedebugclient.h> #include <qmljseditor/qmljseditorconstants.h> #include <qmljs/parser/qmljsast_p.h> #include <qmljs/qmljsmodelmanagerinterface.h> @@ -119,13 +120,16 @@ private: InteractiveInterpreter m_interpreter; bool m_validContext; QHash<QString,BreakpointModelId> pendingBreakpoints; + QList<quint32> queryIds; bool m_retryOnConnectFail; + bool m_automaticConnect; }; QmlEnginePrivate::QmlEnginePrivate(QmlEngine *q) : m_adapter(q), m_validContext(false), - m_retryOnConnectFail(false) + m_retryOnConnectFail(false), + m_automaticConnect(false) {} class ASTWalker: public Visitor @@ -367,6 +371,7 @@ QmlEngine::QmlEngine(const DebuggerStartParameters &startParameters, if (startParameters.useTerminal) { d->m_noDebugOutputTimer.setInterval(0); d->m_retryOnConnectFail = true; + d->m_automaticConnect = true; } } @@ -397,6 +402,9 @@ void QmlEngine::setupInferior() QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state()); notifyInferiorSetupOk(); + + if (d->m_automaticConnect) + beginConnection(); } void QmlEngine::appendMessage(const QString &msg, Utils::OutputFormat /* format */) @@ -421,12 +429,22 @@ void QmlEngine::tryToConnect(quint16 port) { showMessage(QLatin1String("QML Debugger: No application output received in time, trying to connect ..."), LogStatus); d->m_retryOnConnectFail = true; - beginConnection(port); + if (state() == EngineRunRequested + && !d->m_automaticConnect) + beginConnection(port); + else + d->m_automaticConnect = true; } void QmlEngine::beginConnection(quint16 port) { d->m_noDebugOutputTimer.stop(); + + if (state() != EngineRunRequested && d->m_retryOnConnectFail) + return; + + QTC_ASSERT(state() == EngineRunRequested, return) + if (port > 0) { QTC_CHECK(startParameters().communicationChannel == DebuggerStartParameters::CommunicationChannelTcpIp); @@ -1038,23 +1056,15 @@ void QmlEngine::synchronizeWatchers() } } -void QmlEngine::onDebugQueryStateChanged( - QmlJsDebugClient::QDeclarativeDebugQuery::State state) +void QmlEngine::expressionEvaluated(quint32 queryId, const QVariant &result) { - QmlJsDebugClient::QDeclarativeDebugExpressionQuery *query = - qobject_cast<QmlJsDebugClient::QDeclarativeDebugExpressionQuery *>( - sender()); - if (query && state != QmlJsDebugClient::QDeclarativeDebugQuery::Error) { + if (d->queryIds.contains(queryId)) { + d->queryIds.removeOne(queryId); QtMessageLogItem *item = constructLogItemTree(qtMessageLogHandler()->root(), - query->result()); + result); if (item) qtMessageLogHandler()->appendItem(item); - } else - qtMessageLogHandler()-> - appendItem(new QtMessageLogItem(qtMessageLogHandler()->root(), - QtMessageLogHandler::ErrorType, - _("Error evaluating expression."))); - delete query; + } } bool QmlEngine::hasCapability(unsigned cap) const @@ -1152,21 +1162,25 @@ bool QmlEngine::evaluateScriptExpression(const QString& expression) //is sent to V8DebugService. In all other cases, the //expression is evaluated by QDeclarativeEngine. if (state() != InferiorStopOk) { - QDeclarativeEngineDebug *engineDebug = + QmlEngineDebugClient *engineDebug = d->m_adapter.engineDebugClient(); int id = d->m_adapter.currentSelectedDebugId(); if (engineDebug && id != -1) { - QDeclarativeDebugExpressionQuery *query = - engineDebug->queryExpressionResult(id, expression); - connect(query, - SIGNAL(stateChanged( - QmlJsDebugClient::QDeclarativeDebugQuery - ::State)), - this, - SLOT(onDebugQueryStateChanged( - QmlJsDebugClient::QDeclarativeDebugQuery - ::State))); + quint32 queryId = + engineDebug->queryExpressionResult( + id, expression); + if (queryId) { + d->queryIds << queryId; + } else { + didEvaluate = false; + qtMessageLogHandler()-> + appendItem( + new QtMessageLogItem( + qtMessageLogHandler()->root(), + QtMessageLogHandler::ErrorType, + _("Error evaluating expression."))); + } } } else { executeDebuggerCommand(expression); diff --git a/src/plugins/debugger/qml/qmlengine.h b/src/plugins/debugger/qml/qmlengine.h index 3f285da4a3..5a4876b39c 100644 --- a/src/plugins/debugger/qml/qmlengine.h +++ b/src/plugins/debugger/qml/qmlengine.h @@ -34,7 +34,6 @@ #define DEBUGGER_QMLENGINE_H #include "debuggerengine.h" -#include <qmljsdebugclient/qdeclarativeenginedebug.h> #include <qmljsdebugclient/qdebugmessageclient.h> #include <utils/outputformat.h> #include <qmljs/qmljsdocument.h> @@ -58,7 +57,7 @@ namespace Internal { class QtMessageLogItem; class QmlEnginePrivate; -class QmlEngine : public DebuggerEngine +class DEBUGGER_EXPORT QmlEngine : public DebuggerEngine { Q_OBJECT @@ -96,6 +95,7 @@ public: public slots: void disconnected(); void documentUpdated(QmlJS::Document::Ptr doc); + void expressionEvaluated(quint32 queryId, const QVariant &result); private slots: void errorMessageBoxFinished(int result); @@ -171,8 +171,6 @@ private slots: void appendMessage(const QString &msg, Utils::OutputFormat); void synchronizeWatchers(); - void onDebugQueryStateChanged( - QmlJsDebugClient::QDeclarativeDebugQuery::State state); private: void closeConnection(); diff --git a/src/plugins/debugger/qml/qmljsprivateapi.h b/src/plugins/debugger/qml/qmljsprivateapi.h index a8654ba926..003938c548 100644 --- a/src/plugins/debugger/qml/qmljsprivateapi.h +++ b/src/plugins/debugger/qml/qmljsprivateapi.h @@ -32,8 +32,10 @@ #ifndef QMLJSPRIVATEAPI_H #define QMLJSPRIVATEAPI_H -#include <qmljsdebugclient/qdeclarativeenginedebug.h> +#include <qmljsdebugclient/qmlenginedebugclient.h> #include <qmljsdebugclient/qdeclarativedebugclient.h> +#include <qmljsdebugclient/qdeclarativeengineclient.h> +#include <qmljsdebugclient/qmldebuggerclient.h> using namespace QmlJsDebugClient; diff --git a/src/plugins/debugger/qtmessagelogeditor.cpp b/src/plugins/debugger/qtmessagelogeditor.cpp index 62e3fdf821..cb198077d0 100644 --- a/src/plugins/debugger/qtmessagelogeditor.cpp +++ b/src/plugins/debugger/qtmessagelogeditor.cpp @@ -67,6 +67,7 @@ QtMessageLogEditor::QtMessageLogEditor(const QModelIndex &index, format.setName(_("prompt")); format.setHeight(9); format.setWidth(9); + textCursor().insertText(_(" ")); textCursor().insertImage(format); textCursor().insertText(_(" ")); m_startOfEditableArea = textCursor().position(); diff --git a/src/plugins/debugger/qtmessagelogitemdelegate.h b/src/plugins/debugger/qtmessagelogitemdelegate.h index 7d35f50727..ffb76d85e2 100644 --- a/src/plugins/debugger/qtmessagelogitemdelegate.h +++ b/src/plugins/debugger/qtmessagelogitemdelegate.h @@ -180,7 +180,7 @@ private: public: static const int TASK_ICON_SIZE = 16; - static const int ITEM_PADDING = 7; + static const int ITEM_PADDING = 8; static const int ITEM_SPACING = 4; }; diff --git a/src/plugins/debugger/qtmessagelogwindow.cpp b/src/plugins/debugger/qtmessagelogwindow.cpp index 3be4b73af6..5a0a5d4e96 100644 --- a/src/plugins/debugger/qtmessagelogwindow.cpp +++ b/src/plugins/debugger/qtmessagelogwindow.cpp @@ -79,18 +79,17 @@ QtMessageLogWindow::QtMessageLogWindow(QWidget *parent) vbox->setMargin(0); vbox->setSpacing(0); - QWidget *statusbarContainer = new QWidget(); + QWidget *statusbarContainer = new Utils::StyledBar(); statusbarContainer->setFixedHeight(statusBarHeight); QHBoxLayout *hbox = new QHBoxLayout(statusbarContainer); hbox->setMargin(0); + hbox->setSpacing(5); + hbox->addSpacing(5); - const int spacing = 7; //Status Label m_statusLabel = new Utils::StatusLabel; - hbox->addSpacing(spacing); hbox->addWidget(m_statusLabel); hbox->addWidget(new Utils::StyledSeparator); - hbox->addSpacing(spacing); const int buttonWidth = 25; //Filters @@ -105,7 +104,6 @@ QtMessageLogWindow::QtMessageLogWindow(QWidget *parent) m_showLogAction->setIcon(QIcon(_(":/debugger/images/log.png"))); button->setDefaultAction(m_showLogAction); hbox->addWidget(button); - hbox->addSpacing(spacing); button = new QToolButton(this); button->setAutoRaise(true); @@ -118,7 +116,6 @@ QtMessageLogWindow::QtMessageLogWindow(QWidget *parent) m_showWarningAction->setIcon(QIcon(_(":/debugger/images/warning.png"))); button->setDefaultAction(m_showWarningAction); hbox->addWidget(button); - hbox->addSpacing(spacing); button = new QToolButton(this); button->setAutoRaise(true); @@ -131,7 +128,7 @@ QtMessageLogWindow::QtMessageLogWindow(QWidget *parent) m_showErrorAction->setIcon(QIcon(_(":/debugger/images/error.png"))); button->setDefaultAction(m_showErrorAction); hbox->addWidget(button); - hbox->addSpacing(spacing); + hbox->addWidget(new Utils::StyledSeparator); //Clear Button button = new QToolButton; @@ -141,7 +138,7 @@ QtMessageLogWindow::QtMessageLogWindow(QWidget *parent) m_clearAction->setIcon(QIcon(_(Core::Constants::ICON_CLEAN_PANE))); button->setDefaultAction(m_clearAction); hbox->addWidget(button); - hbox->addSpacing(spacing); + hbox->addWidget(new Utils::StyledSeparator); m_treeView = new QtMessageLogView(this); m_treeView->setSizePolicy(QSizePolicy::MinimumExpanding, diff --git a/src/plugins/debugger/registerwindow.cpp b/src/plugins/debugger/registerwindow.cpp index 37608353bd..bf796bb43d 100644 --- a/src/plugins/debugger/registerwindow.cpp +++ b/src/plugins/debugger/registerwindow.cpp @@ -163,16 +163,13 @@ public: // /////////////////////////////////////////////////////////////////////// -RegisterWindow::RegisterWindow(QWidget *parent) - : BaseWindow(parent) +RegisterTreeView::RegisterTreeView(QWidget *parent) + : BaseTreeView(parent) { - setWindowTitle(tr("Registers")); - setAlwaysAdjustColumnsAction(debuggerCore()->action(UseAlternatingRowColors)); setItemDelegate(new RegisterDelegate(this)); - setObjectName(QLatin1String("RegisterWindow")); } -void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev) +void RegisterTreeView::contextMenuEvent(QContextMenuEvent *ev) { QMenu menu; @@ -271,11 +268,17 @@ void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev) handleBaseContextAction(act); } -void RegisterWindow::reloadRegisters() +void RegisterTreeView::reloadRegisters() { // FIXME: Only trigger when becoming visible? currentEngine()->reloadRegisters(); } +RegisterWindow::RegisterWindow() + : BaseWindow(new RegisterTreeView) +{ + setWindowTitle(tr("Registers")); +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/registerwindow.h b/src/plugins/debugger/registerwindow.h index 8a7253f62e..c6c9e587c4 100644 --- a/src/plugins/debugger/registerwindow.h +++ b/src/plugins/debugger/registerwindow.h @@ -38,12 +38,12 @@ namespace Debugger { namespace Internal { -class RegisterWindow : public BaseWindow +class RegisterTreeView : public BaseTreeView { Q_OBJECT public: - explicit RegisterWindow(QWidget *parent = 0); + explicit RegisterTreeView(QWidget *parent = 0); public slots: void reloadRegisters(); @@ -52,6 +52,12 @@ private: void contextMenuEvent(QContextMenuEvent *ev); }; +class RegisterWindow : public BaseWindow +{ +public: + RegisterWindow(); +}; + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/snapshotwindow.cpp b/src/plugins/debugger/snapshotwindow.cpp index e29b7c6b2e..ebdc9ca0da 100644 --- a/src/plugins/debugger/snapshotwindow.cpp +++ b/src/plugins/debugger/snapshotwindow.cpp @@ -56,19 +56,19 @@ namespace Internal { // /////////////////////////////////////////////////////////////////////// -SnapshotWindow::SnapshotWindow(SnapshotHandler *handler) +SnapshotTreeView::SnapshotTreeView(SnapshotHandler *handler) { m_snapshotHandler = handler; setWindowTitle(tr("Snapshots")); setAlwaysAdjustColumnsAction(debuggerCore()->action(AlwaysAdjustSnapshotsColumnWidths)); } -void SnapshotWindow::rowActivated(const QModelIndex &index) +void SnapshotTreeView::rowActivated(const QModelIndex &index) { m_snapshotHandler->activateSnapshot(index.row()); } -void SnapshotWindow::keyPressEvent(QKeyEvent *ev) +void SnapshotTreeView::keyPressEvent(QKeyEvent *ev) { if (ev->key() == Qt::Key_Delete) { QItemSelectionModel *sm = selectionModel(); @@ -84,7 +84,7 @@ void SnapshotWindow::keyPressEvent(QKeyEvent *ev) QTreeView::keyPressEvent(ev); } -void SnapshotWindow::contextMenuEvent(QContextMenuEvent *ev) +void SnapshotTreeView::contextMenuEvent(QContextMenuEvent *ev) { QModelIndex idx = indexAt(ev->pos()); @@ -109,7 +109,7 @@ void SnapshotWindow::contextMenuEvent(QContextMenuEvent *ev) handleBaseContextAction(act); } -void SnapshotWindow::removeSnapshot(int i) +void SnapshotTreeView::removeSnapshot(int i) { m_snapshotHandler->at(i)->quitDebugger(); } diff --git a/src/plugins/debugger/snapshotwindow.h b/src/plugins/debugger/snapshotwindow.h index 69c1c5df2b..302f4fd830 100644 --- a/src/plugins/debugger/snapshotwindow.h +++ b/src/plugins/debugger/snapshotwindow.h @@ -40,12 +40,12 @@ namespace Internal { class SnapshotHandler; -class SnapshotWindow : public BaseWindow +class SnapshotTreeView : public BaseTreeView { Q_OBJECT public: - explicit SnapshotWindow(SnapshotHandler *handler); + explicit SnapshotTreeView(SnapshotHandler *handler); private: void rowActivated(const QModelIndex &index); @@ -56,6 +56,16 @@ private: SnapshotHandler *m_snapshotHandler; }; +class SnapshotWindow : public BaseWindow +{ +public: + explicit SnapshotWindow(SnapshotHandler *handler) + : BaseWindow(new SnapshotTreeView(handler)) + { + setWindowTitle(tr("Snapshots")); + } +}; + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/sourcefileswindow.cpp b/src/plugins/debugger/sourcefileswindow.cpp index e950ef4665..78c623ee84 100644 --- a/src/plugins/debugger/sourcefileswindow.cpp +++ b/src/plugins/debugger/sourcefileswindow.cpp @@ -56,21 +56,20 @@ namespace Debugger { namespace Internal { -SourceFilesWindow::SourceFilesWindow(QWidget *parent) - : BaseWindow(parent) +SourceFilesTreeView::SourceFilesTreeView(QWidget *parent) + : BaseTreeView(parent) { - setWindowTitle(tr("Source Files")); setSortingEnabled(true); } -void SourceFilesWindow::rowActivated(const QModelIndex &index) +void SourceFilesTreeView::rowActivated(const QModelIndex &index) { DebuggerEngine *engine = debuggerCore()->currentEngine(); QTC_ASSERT(engine, return); engine->gotoLocation(index.data().toString()); } -void SourceFilesWindow::contextMenuEvent(QContextMenuEvent *ev) +void SourceFilesTreeView::contextMenuEvent(QContextMenuEvent *ev) { DebuggerEngine *engine = debuggerCore()->currentEngine(); QTC_ASSERT(engine, return); @@ -107,6 +106,12 @@ void SourceFilesWindow::contextMenuEvent(QContextMenuEvent *ev) handleBaseContextAction(act); } +SourceFilesWindow::SourceFilesWindow() + : BaseWindow(new SourceFilesTreeView) +{ + setWindowTitle(tr("Source Files")); +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/sourcefileswindow.h b/src/plugins/debugger/sourcefileswindow.h index 8f150febfe..23088ec6fc 100644 --- a/src/plugins/debugger/sourcefileswindow.h +++ b/src/plugins/debugger/sourcefileswindow.h @@ -38,18 +38,24 @@ namespace Debugger { namespace Internal { -class SourceFilesWindow : public BaseWindow +class SourceFilesTreeView : public BaseTreeView { Q_OBJECT public: - SourceFilesWindow(QWidget *parent = 0); + SourceFilesTreeView(QWidget *parent = 0); private: void rowActivated(const QModelIndex &index); void contextMenuEvent(QContextMenuEvent *ev); }; +class SourceFilesWindow : public BaseWindow +{ +public: + SourceFilesWindow(); +}; + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/stackframe.cpp b/src/plugins/debugger/stackframe.cpp index 6c4fdbb62a..09841a7769 100644 --- a/src/plugins/debugger/stackframe.cpp +++ b/src/plugins/debugger/stackframe.cpp @@ -106,7 +106,26 @@ QString StackFrame::toToolTip() const str << "<tr><td>" << tr("From:") << "</td><td>" << from << "</td></tr>"; if (!to.isEmpty()) str << "<tr><td>" << tr("To:") << "</td><td>" << to << "</td></tr>"; - str << "</table></body></html>"; + str << "</table>"; + + str <<"<br> <br><i>" << tr("Note:") << " </i> "; + if (isUsable()) { + str << tr("Sources for this frame are available.<br>Double-click on " + "the file name to open an editor."); + } else if (line <= 0) { + str << tr("Binary debug information is not accessible for this " + "frame. This either means the core was not compiled " + "with debug information, or the debug information is not " + "accessible. Note that most distributions ship debug information " + "in separate packages."); + } else { + str << tr("Binary debug information is accessible for this " + "frame. However, matching sources have not been found. " + "Note that some distributions ship debug sources in " + "in separate packages."); + } + + str << "</body></html>"; return res; } diff --git a/src/plugins/debugger/stackhandler.cpp b/src/plugins/debugger/stackhandler.cpp index 04efb34b3c..674aa8709c 100644 --- a/src/plugins/debugger/stackhandler.cpp +++ b/src/plugins/debugger/stackhandler.cpp @@ -109,7 +109,7 @@ QVariant StackHandler::data(const QModelIndex &index, int role) const case 2: // File name return frame.file.isEmpty() ? frame.from : QFileInfo(frame.file).fileName(); case 3: // Line number - return frame.line >= 0 ? QVariant(frame.line) : QVariant(); + return frame.line > 0 ? QVariant(frame.line) : QVariant(); case 4: // Address if (frame.address) return QString::fromLatin1("0x%1").arg(frame.address, 0, 16); diff --git a/src/plugins/debugger/stackwindow.cpp b/src/plugins/debugger/stackwindow.cpp index cd70765e58..cf8a59d6ca 100644 --- a/src/plugins/debugger/stackwindow.cpp +++ b/src/plugins/debugger/stackwindow.cpp @@ -59,8 +59,8 @@ static DebuggerEngine *currentEngine() return debuggerCore()->currentEngine(); } -StackWindow::StackWindow(QWidget *parent) - : BaseWindow(parent) +StackTreeView::StackTreeView(QWidget *parent) + : BaseTreeView(parent) { setWindowTitle(tr("Stack")); setAlwaysAdjustColumnsAction(debuggerCore()->action(AlwaysAdjustStackColumnWidths)); @@ -74,19 +74,19 @@ StackWindow::StackWindow(QWidget *parent) showAddressColumn(false); } -void StackWindow::showAddressColumn(bool on) +void StackTreeView::showAddressColumn(bool on) { setColumnHidden(4, !on); } -void StackWindow::rowActivated(const QModelIndex &index) +void StackTreeView::rowActivated(const QModelIndex &index) { currentEngine()->activateFrame(index.row()); } -void StackWindow::setModel(QAbstractItemModel *model) +void StackTreeView::setModel(QAbstractItemModel *model) { - BaseWindow::setModel(model); + BaseTreeView::setModel(model); resizeColumnToContents(0); resizeColumnToContents(3); showAddressColumn(debuggerCore()->action(UseAddressInStackView)->isChecked()); @@ -100,8 +100,8 @@ static inline StackFrame inputFunctionForDisassembly() StackFrame frame; QInputDialog dialog; dialog.setInputMode(QInputDialog::TextInput); - dialog.setLabelText(StackWindow::tr("Function:")); - dialog.setWindowTitle(StackWindow::tr("Disassemble Function")); + dialog.setLabelText(StackTreeView::tr("Function:")); + dialog.setWindowTitle(StackTreeView::tr("Disassemble Function")); dialog.setWindowFlags(dialog.windowFlags() & ~Qt::WindowContextHelpButtonHint); if (dialog.exec() != QDialog::Accepted) return frame; @@ -119,7 +119,7 @@ static inline StackFrame inputFunctionForDisassembly() return frame; } -void StackWindow::contextMenuEvent(QContextMenuEvent *ev) +void StackTreeView::contextMenuEvent(QContextMenuEvent *ev) { DebuggerEngine *engine = currentEngine(); StackHandler *handler = engine->stackHandler(); @@ -213,7 +213,7 @@ void StackWindow::contextMenuEvent(QContextMenuEvent *ev) handleBaseContextAction(act); } -void StackWindow::copyContentsToClipboard() +void StackTreeView::copyContentsToClipboard() { QString str; int n = model()->rowCount(); @@ -233,7 +233,7 @@ void StackWindow::copyContentsToClipboard() clipboard->setText(str, QClipboard::Clipboard); } -void StackWindow::reloadFullStack() +void StackTreeView::reloadFullStack() { currentEngine()->reloadFullStack(); } diff --git a/src/plugins/debugger/stackwindow.h b/src/plugins/debugger/stackwindow.h index 1e7e73b942..239c043c0d 100644 --- a/src/plugins/debugger/stackwindow.h +++ b/src/plugins/debugger/stackwindow.h @@ -38,12 +38,12 @@ namespace Debugger { namespace Internal { -class StackWindow : public BaseWindow +class StackTreeView : public BaseTreeView { Q_OBJECT public: - explicit StackWindow(QWidget *parent = 0); + explicit StackTreeView(QWidget *parent = 0); private slots: void showAddressColumn(bool on); @@ -56,6 +56,15 @@ private: void copyContentsToClipboard(); }; +class StackWindow : public BaseWindow +{ +public: + StackWindow() : BaseWindow(new StackTreeView) + { + setWindowTitle(tr("Stack")); + } +}; + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/threadswindow.cpp b/src/plugins/debugger/threadswindow.cpp index d3065fa0ab..fb24b612ef 100644 --- a/src/plugins/debugger/threadswindow.cpp +++ b/src/plugins/debugger/threadswindow.cpp @@ -48,23 +48,20 @@ namespace Debugger { namespace Internal { -ThreadsWindow::ThreadsWindow(QWidget *parent) - : BaseWindow(parent) +ThreadsTreeView::ThreadsTreeView() { - setWindowTitle(tr("Thread")); setSortingEnabled(true); setAlwaysAdjustColumnsAction(debuggerCore()->action(AlwaysAdjustThreadsColumnWidths)); - setObjectName(QLatin1String("ThreadsWindow")); } -void ThreadsWindow::rowActivated(const QModelIndex &index) +void ThreadsTreeView::rowActivated(const QModelIndex &index) { debuggerCore()->currentEngine()->selectThread(index.row()); } -void ThreadsWindow::setModel(QAbstractItemModel *model) +void ThreadsTreeView::setModel(QAbstractItemModel *model) { - BaseWindow::setModel(model); + BaseTreeView::setModel(model); resizeColumnToContents(ThreadData::IdColumn); resizeColumnToContents(ThreadData::LineColumn); resizeColumnToContents(ThreadData::NameColumn); @@ -72,7 +69,7 @@ void ThreadsWindow::setModel(QAbstractItemModel *model) resizeColumnToContents(ThreadData::TargetIdColumn); } -void ThreadsWindow::contextMenuEvent(QContextMenuEvent *ev) +void ThreadsTreeView::contextMenuEvent(QContextMenuEvent *ev) { QMenu menu; addBaseContextActions(&menu); @@ -80,5 +77,12 @@ void ThreadsWindow::contextMenuEvent(QContextMenuEvent *ev) handleBaseContextAction(act); } +ThreadsWindow::ThreadsWindow() + : BaseWindow(new ThreadsTreeView) +{ + setWindowTitle(tr("Threads")); + setObjectName(QLatin1String("ThreadsWindow")); +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/threadswindow.h b/src/plugins/debugger/threadswindow.h index 9681c5ae04..15e1e152a6 100644 --- a/src/plugins/debugger/threadswindow.h +++ b/src/plugins/debugger/threadswindow.h @@ -38,12 +38,12 @@ namespace Debugger { namespace Internal { -class ThreadsWindow : public BaseWindow +class ThreadsTreeView : public BaseTreeView { Q_OBJECT public: - ThreadsWindow(QWidget *parent = 0); + ThreadsTreeView(); private: void rowActivated(const QModelIndex &index); @@ -51,6 +51,12 @@ private: void contextMenuEvent(QContextMenuEvent *ev); }; +class ThreadsWindow : public BaseWindow +{ +public: + ThreadsWindow(); +}; + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/watchutils.cpp b/src/plugins/debugger/watchutils.cpp index d95834e481..317a4887bc 100644 --- a/src/plugins/debugger/watchutils.cpp +++ b/src/plugins/debugger/watchutils.cpp @@ -47,7 +47,7 @@ #include <cpptools/cpptoolsconstants.h> #include <cpptools/abstracteditorsupport.h> -#include <cplusplus/ModelManagerInterface.h> +#include <cpptools/ModelManagerInterface.h> #include <cplusplus/ExpressionUnderCursor.h> #include <cplusplus/Overview.h> #include <Symbols.h> diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp index 0350bb03e4..7379c02915 100644 --- a/src/plugins/debugger/watchwindow.cpp +++ b/src/plugins/debugger/watchwindow.cpp @@ -83,7 +83,7 @@ static DebuggerEngine *currentEngine() class WatchDelegate : public QItemDelegate { public: - explicit WatchDelegate(WatchWindow *parent) + explicit WatchDelegate(WatchTreeView *parent) : QItemDelegate(parent), m_watchWindow(parent) {} @@ -142,7 +142,7 @@ public: } private: - WatchWindow *m_watchWindow; + WatchTreeView *m_watchWindow; }; // Watch model query helpers. @@ -199,10 +199,10 @@ static QString variableToolTip(const QString &name, const QString &type, { return offset ? //: HTML tooltip of a variable in the memory editor - WatchWindow::tr("<i>%1</i> %2 at #%3"). + WatchTreeView::tr("<i>%1</i> %2 at #%3"). arg(type, name).arg(offset) : //: HTML tooltip of a variable in the memory editor - WatchWindow::tr("<i>%1</i> %2").arg(type, name); + WatchTreeView::tr("<i>%1</i> %2").arg(type, name); } static int memberVariableRecursion(const QAbstractItemModel *model, @@ -318,7 +318,7 @@ static MemoryMarkupList const quint64 offset = it.key() - address; if (offset < size) { ranges[offset] = ColorNumberToolTip(registerColorNumber, - WatchWindow::tr("Register <i>%1</i>").arg(it.value())); + WatchTreeView::tr("Register <i>%1</i>").arg(it.value())); } else { break; // Sorted. } @@ -406,9 +406,9 @@ static void addVariableMemoryView(DebuggerEngine *engine, bool separateView, const unsigned flags = separateView ? DebuggerEngine::MemoryView|DebuggerEngine::MemoryReadOnly : 0; const QString title = deferencePointer - ? WatchWindow::tr("Memory Referenced by Pointer \"%1\" (0x%2)") + ? WatchTreeView::tr("Memory Referenced by Pointer \"%1\" (0x%2)") .arg(nameOf(m)).arg(address, 0, 16) - : WatchWindow::tr("Memory at Variable \"%1\" (0x%2)") + : WatchTreeView::tr("Memory at Variable \"%1\" (0x%2)") .arg(nameOf(m)).arg(address, 0, 16); engine->openMemoryView(address, flags, markup, p, title, parent); } @@ -443,8 +443,8 @@ static void addStackLayoutMemoryView(DebuggerEngine *engine, bool separateView, // Anything found and everything in a sensible range (static data in-between)? if (end <= start || end - start > 100 * 1024) { QMessageBox::information(parent, - WatchWindow::tr("Cannot Display Stack Layout"), - WatchWindow::tr("Could not determine a suitable address range.")); + WatchTreeView::tr("Cannot Display Stack Layout"), + WatchTreeView::tr("Could not determine a suitable address range.")); return; } // Take a look at the register values. Extend the range a bit if suitable @@ -468,7 +468,7 @@ static void addStackLayoutMemoryView(DebuggerEngine *engine, bool separateView, const unsigned flags = separateView ? (DebuggerEngine::MemoryView|DebuggerEngine::MemoryReadOnly) : 0; const QString title = - WatchWindow::tr("Memory Layout of Local Variables at 0x%1").arg(start, 0, 16); + WatchTreeView::tr("Memory Layout of Local Variables at 0x%1").arg(start, 0, 16); engine->openMemoryView(start, flags, markup, p, title, parent); } @@ -478,8 +478,8 @@ static void addStackLayoutMemoryView(DebuggerEngine *engine, bool separateView, // ///////////////////////////////////////////////////////////////////// -WatchWindow::WatchWindow(Type type, QWidget *parent) - : BaseWindow(parent), +WatchTreeView::WatchTreeView(Type type, QWidget *parent) + : BaseTreeView(parent), m_type(type) { setObjectName(QLatin1String("WatchWindow")); @@ -499,17 +499,17 @@ WatchWindow::WatchWindow(Type type, QWidget *parent) SLOT(collapseNode(QModelIndex))); } -void WatchWindow::expandNode(const QModelIndex &idx) +void WatchTreeView::expandNode(const QModelIndex &idx) { setModelData(LocalsExpandedRole, true, idx); } -void WatchWindow::collapseNode(const QModelIndex &idx) +void WatchTreeView::collapseNode(const QModelIndex &idx) { setModelData(LocalsExpandedRole, false, idx); } -void WatchWindow::keyPressEvent(QKeyEvent *ev) +void WatchTreeView::keyPressEvent(QKeyEvent *ev) { if (ev->key() == Qt::Key_Delete && m_type == WatchersType) { QModelIndexList indices = selectionModel()->selectedRows(); @@ -533,7 +533,7 @@ void WatchWindow::keyPressEvent(QKeyEvent *ev) QTreeView::keyPressEvent(ev); } -void WatchWindow::dragEnterEvent(QDragEnterEvent *ev) +void WatchTreeView::dragEnterEvent(QDragEnterEvent *ev) { //QTreeView::dragEnterEvent(ev); if (ev->mimeData()->hasText()) { @@ -542,7 +542,7 @@ void WatchWindow::dragEnterEvent(QDragEnterEvent *ev) } } -void WatchWindow::dragMoveEvent(QDragMoveEvent *ev) +void WatchTreeView::dragMoveEvent(QDragMoveEvent *ev) { //QTreeView::dragMoveEvent(ev); if (ev->mimeData()->hasText()) { @@ -551,7 +551,7 @@ void WatchWindow::dragMoveEvent(QDragMoveEvent *ev) } } -void WatchWindow::dropEvent(QDropEvent *ev) +void WatchTreeView::dropEvent(QDropEvent *ev) { if (ev->mimeData()->hasText()) { watchExpression(ev->mimeData()->text()); @@ -562,7 +562,7 @@ void WatchWindow::dropEvent(QDropEvent *ev) //QTreeView::dropEvent(ev); } -void WatchWindow::mouseDoubleClickEvent(QMouseEvent *ev) +void WatchTreeView::mouseDoubleClickEvent(QMouseEvent *ev) { const QModelIndex idx = indexAt(ev->pos()); if (!idx.isValid()) { @@ -577,24 +577,24 @@ void WatchWindow::mouseDoubleClickEvent(QMouseEvent *ev) static QString addWatchActionText(QString exp) { if (exp.isEmpty()) - return WatchWindow::tr("Evaluate Expression"); + return WatchTreeView::tr("Evaluate Expression"); if (exp.size() > 30) { exp.truncate(30); exp.append(QLatin1String("...")); } - return WatchWindow::tr("Evaluate Expression \"%1\"").arg(exp); + return WatchTreeView::tr("Evaluate Expression \"%1\"").arg(exp); } // Text for add watch action with truncated expression. static QString removeWatchActionText(QString exp) { if (exp.isEmpty()) - return WatchWindow::tr("Remove Evaluated Expression"); + return WatchTreeView::tr("Remove Evaluated Expression"); if (exp.size() > 30) { exp.truncate(30); exp.append(QLatin1String("...")); } - return WatchWindow::tr("Remove Evaluated Expression \"%1\"").arg(exp); + return WatchTreeView::tr("Remove Evaluated Expression \"%1\"").arg(exp); } static void copyToClipboard(const QString &clipboardText) @@ -606,7 +606,7 @@ static void copyToClipboard(const QString &clipboardText) clipboard->setText(clipboardText, QClipboard::Clipboard); } -void WatchWindow::contextMenuEvent(QContextMenuEvent *ev) +void WatchTreeView::contextMenuEvent(QContextMenuEvent *ev) { DebuggerEngine *engine = currentEngine(); WatchHandler *handler = engine->watchHandler(); @@ -970,7 +970,7 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev) } } -bool WatchWindow::event(QEvent *ev) +bool WatchTreeView::event(QEvent *ev) { if (m_grabbing && ev->type() == QEvent::MouseButtonPress) { QMouseEvent *mev = static_cast<QMouseEvent *>(ev); @@ -981,14 +981,14 @@ bool WatchWindow::event(QEvent *ev) return QTreeView::event(ev); } -void WatchWindow::editItem(const QModelIndex &idx) +void WatchTreeView::editItem(const QModelIndex &idx) { Q_UNUSED(idx) // FIXME } -void WatchWindow::setModel(QAbstractItemModel *model) +void WatchTreeView::setModel(QAbstractItemModel *model) { - BaseWindow::setModel(model); + BaseTreeView::setModel(model); setRootIsDecorated(true); if (header()) { header()->setDefaultAlignment(Qt::AlignLeft); @@ -999,12 +999,12 @@ void WatchWindow::setModel(QAbstractItemModel *model) connect(model, SIGNAL(layoutChanged()), SLOT(resetHelper())); } -void WatchWindow::resetHelper() +void WatchTreeView::resetHelper() { resetHelper(model()->index(0, 0)); } -void WatchWindow::resetHelper(const QModelIndex &idx) +void WatchTreeView::resetHelper(const QModelIndex &idx) { if (idx.data(LocalsExpandedRole).toBool()) { //qDebug() << "EXPANDING " << model()->data(idx, INameRole); @@ -1022,24 +1022,24 @@ void WatchWindow::resetHelper(const QModelIndex &idx) } } -void WatchWindow::watchExpression(const QString &exp) +void WatchTreeView::watchExpression(const QString &exp) { currentEngine()->watchHandler()->watchExpression(exp); } -void WatchWindow::removeWatchExpression(const QString &exp) +void WatchTreeView::removeWatchExpression(const QString &exp) { currentEngine()->watchHandler()->removeWatchExpression(exp); } -void WatchWindow::setModelData +void WatchTreeView::setModelData (int role, const QVariant &value, const QModelIndex &index) { QTC_ASSERT(model(), return); model()->setData(index, value, role); } -void WatchWindow::setWatchpointAtAddress(quint64 address, unsigned size) +void WatchTreeView::setWatchpointAtAddress(quint64 address, unsigned size) { BreakpointParameters data(WatchpointAtAddress); data.address = address; @@ -1053,7 +1053,7 @@ void WatchWindow::setWatchpointAtAddress(quint64 address, unsigned size) breakHandler()->appendBreakpoint(data); } -void WatchWindow::setWatchpointAtExpression(const QString &exp) +void WatchTreeView::setWatchpointAtExpression(const QString &exp) { BreakpointParameters data(WatchpointAtExpression); data.expression = exp; @@ -1066,6 +1066,7 @@ void WatchWindow::setWatchpointAtExpression(const QString &exp) breakHandler()->appendBreakpoint(data); } + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/watchwindow.h b/src/plugins/debugger/watchwindow.h index bf6658f389..b04f85c3f5 100644 --- a/src/plugins/debugger/watchwindow.h +++ b/src/plugins/debugger/watchwindow.h @@ -44,15 +44,16 @@ namespace Internal { // ///////////////////////////////////////////////////////////////////// -class WatchWindow : public BaseWindow +class WatchTreeView : public BaseTreeView { Q_OBJECT public: enum Type { ReturnType, LocalsType, TooltipType, WatchersType }; - explicit WatchWindow(Type type, QWidget *parent = 0); + explicit WatchTreeView(Type type, QWidget *parent = 0); Type type() const { return m_type; } + void setModel(QAbstractItemModel *model); public slots: void watchExpression(const QString &exp); @@ -63,7 +64,6 @@ private: Q_SLOT void expandNode(const QModelIndex &idx); Q_SLOT void collapseNode(const QModelIndex &idx); - void setModel(QAbstractItemModel *model); void keyPressEvent(QKeyEvent *ev); void contextMenuEvent(QContextMenuEvent *ev); void dragEnterEvent(QDragEnterEvent *ev); @@ -84,6 +84,15 @@ private: bool m_grabbing; }; +class WatchWindow : public BaseWindow +{ +public: + explicit WatchWindow(WatchTreeView::Type type) + : BaseWindow(new WatchTreeView(type)) + { + setWindowTitle(tr("Locals and Expressions")); + } +}; } // namespace Internal } // namespace Debugger |