Skip to content
Snippets Groups Projects
debuggerplugin.cpp 50.5 KiB
Newer Older
    connect(m_manager, SIGNAL(gotoLocationRequested(QString,int,bool)),
        this, SLOT(gotoLocation(QString,int,bool)));
hjk's avatar
hjk committed
    connect(m_manager, SIGNAL(stateChanged(int)),
        this, SLOT(handleStateChanged(int)));
con's avatar
con committed
    connect(m_manager, SIGNAL(previousModeRequested()),
        this, SLOT(activatePreviousMode()));
    connect(m_manager, SIGNAL(debugModeRequested()),
        this, SLOT(activateDebugMode()));

    connect(theDebuggerAction(SettingsDialog), SIGNAL(triggered()),
    handleStateChanged(DebuggerNotReady);
con's avatar
con committed
    return true;
}

void DebuggerPlugin::extensionsInitialized()
{
hjk's avatar
hjk committed
    // time gdb -i mi -ex 'debuggerplugin.cpp:800' -ex r -ex q bin/qtcreator.bin
    const QByteArray env = qgetenv("QTC_DEBUGGER_TEST");
hjk's avatar
hjk committed
    //qDebug() << "EXTENSIONS INITIALIZED:" << env;
hjk's avatar
hjk committed
    if (!env.isEmpty())
        m_manager->runTest(QString::fromLocal8Bit(env));
    if (m_attachRemoteParameters.attachPid || !m_attachRemoteParameters.attachCore.isEmpty())
        QTimer::singleShot(0, this, SLOT(attachCmdLine()));
void DebuggerPlugin::attachCmdLine()
    if (m_manager->state() != DebuggerNotReady)
        return;
    if (m_attachRemoteParameters.attachPid) {
        m_manager->showStatusMessage(tr("Attaching to PID %1.").arg(m_attachRemoteParameters.attachPid));
        const QString crashParameter =
                m_attachRemoteParameters.winCrashEvent ? QString::number(m_attachRemoteParameters.winCrashEvent) : QString();
        attachExternalApplication(m_attachRemoteParameters.attachPid, crashParameter);
        return;
    }
    if (!m_attachRemoteParameters.attachCore.isEmpty()) {
        m_manager->showStatusMessage(tr("Attaching to core %1.").arg(m_attachRemoteParameters.attachCore));
        attachCore(m_attachRemoteParameters.attachCore, QString());
    }
con's avatar
con committed
}

/*! Activates the previous mode when the current mode is the debug mode. */
void DebuggerPlugin::activatePreviousMode()
{
    Core::ModeManager *const modeManager = ICore::instance()->modeManager();
con's avatar
con committed

    if (modeManager->currentMode() == modeManager->mode(Constants::MODE_DEBUG)
            && !m_previousMode.isEmpty()) {
        modeManager->activateMode(m_previousMode);
        m_previousMode.clear();
    }
}

void DebuggerPlugin::activateDebugMode()
{
    ModeManager *modeManager = ModeManager::instance();
    m_previousMode = modeManager->currentMode()->id();
con's avatar
con committed
    modeManager->activateMode(QLatin1String(MODE_DEBUG));
}

void DebuggerPlugin::queryCurrentTextEditor(QString *fileName, int *lineNumber, QObject **object)
{
    EditorManager *editorManager = EditorManager::instance();
    if (!editorManager)
con's avatar
con committed
        return;
    Core::IEditor *editor = editorManager->currentEditor();
con's avatar
con committed
    ITextEditor *textEditor = qobject_cast<ITextEditor*>(editor);
    if (!textEditor)
        return;
    if (fileName)
        *fileName = textEditor->file()->fileName();
    if (lineNumber)
        *lineNumber = textEditor->currentLine();
    if (object)
        *object = textEditor->widget();
}

void DebuggerPlugin::editorOpened(Core::IEditor *editor)
{
    if (ITextEditor *textEditor = qobject_cast<ITextEditor *>(editor)) {
        connect(textEditor, SIGNAL(markRequested(TextEditor::ITextEditor*,int)),
            this, SLOT(requestMark(TextEditor::ITextEditor*,int)));
        connect(editor, SIGNAL(tooltipRequested(TextEditor::ITextEditor*,QPoint,int)),
            this, SLOT(showToolTip(TextEditor::ITextEditor*,QPoint,int)));
        connect(textEditor, SIGNAL(markContextMenuRequested(TextEditor::ITextEditor*,int,QMenu*)),
            this, SLOT(requestContextMenu(TextEditor::ITextEditor*,int,QMenu*)));
con's avatar
con committed
    }
}

void DebuggerPlugin::editorAboutToClose(Core::IEditor *editor)
{
    if (ITextEditor *textEditor = qobject_cast<ITextEditor *>(editor)) {
        disconnect(textEditor, SIGNAL(markRequested(TextEditor::ITextEditor*,int)),
            this, SLOT(requestMark(TextEditor::ITextEditor*,int)));
        disconnect(editor, SIGNAL(tooltipRequested(TextEditor::ITextEditor*,QPoint,int)),
            this, SLOT(showToolTip(TextEditor::ITextEditor*,QPoint,int)));
        disconnect(textEditor, SIGNAL(markContextMenuRequested(TextEditor::ITextEditor*,int,QMenu*)),
            this, SLOT(requestContextMenu(TextEditor::ITextEditor*,int,QMenu*)));
con's avatar
con committed
    }
}

void DebuggerPlugin::requestContextMenu(TextEditor::ITextEditor *editor,
    int lineNumber, QMenu *menu)
{
    QString fileName = editor->file()->fileName();
    QString position = fileName + QString(":%1").arg(lineNumber);
    BreakpointData *data = m_manager->findBreakpoint(fileName, lineNumber);

    if (data) {
        // existing breakpoint
        QAction *act = new QAction(tr("Remove Breakpoint"), menu);
        act->setData(position);
        connect(act, SIGNAL(triggered()),
            this, SLOT(breakpointSetRemoveMarginActionTriggered()));
        menu->addAction(act);

        QAction *act2;
        if (data->enabled)
            act2 = new QAction(tr("Disable Breakpoint"), menu);
        else
            act2 = new QAction(tr("Enable Breakpoint"), menu);
        act2->setData(position);
        connect(act2, SIGNAL(triggered()),
            this, SLOT(breakpointEnableDisableMarginActionTriggered()));
        menu->addAction(act2);
    } else {
        // non-existing
        QAction *act = new QAction(tr("Set Breakpoint"), menu);
        act->setData(position);
        connect(act, SIGNAL(triggered()),
            this, SLOT(breakpointSetRemoveMarginActionTriggered()));
        menu->addAction(act);
    }
}

void DebuggerPlugin::breakpointSetRemoveMarginActionTriggered()
{
    if (QAction *act = qobject_cast<QAction *>(sender())) {
        QString str = act->data().toString();
        int pos = str.lastIndexOf(':');
        m_manager->toggleBreakpoint(str.left(pos), str.mid(pos + 1).toInt());
    }
void DebuggerPlugin::breakpointEnableDisableMarginActionTriggered()
    if (QAction *act = qobject_cast<QAction *>(sender())) {
        QString str = act->data().toString();
        int pos = str.lastIndexOf(':');
        m_manager->toggleBreakpointEnabled(str.left(pos), str.mid(pos + 1).toInt());
    }
con's avatar
con committed
void DebuggerPlugin::requestMark(TextEditor::ITextEditor *editor, int lineNumber)
{
    m_manager->toggleBreakpoint(editor->file()->fileName(), lineNumber);
}

void DebuggerPlugin::showToolTip(TextEditor::ITextEditor *editor,
    const QPoint &point, int pos)
{
    if (!theDebuggerBoolSetting(UseToolTipsInMainEditor)
hjk's avatar
hjk committed
            || m_manager->state() == DebuggerNotReady)
    m_manager->setToolTipExpression(point, editor, pos);
con's avatar
con committed
}

void DebuggerPlugin::setSessionValue(const QString &name, const QVariant &value)
{
    //qDebug() << "SET SESSION VALUE" << name << value;
    QTC_ASSERT(sessionManager(), return);
    sessionManager()->setValue(name, value);
con's avatar
con committed
}

void DebuggerPlugin::querySessionValue(const QString &name, QVariant *value)
{
    QTC_ASSERT(sessionManager(), return);
    *value = sessionManager()->value(name);
con's avatar
con committed
    //qDebug() << "GET SESSION VALUE: " << name << value;
}


void DebuggerPlugin::setConfigValue(const QString &name, const QVariant &value)
{
hjk's avatar
hjk committed
    QTC_ASSERT(m_debugMode, return);
hjk's avatar
hjk committed
    settings()->setValue(name, value);
con's avatar
con committed
}

QVariant DebuggerPlugin::configValue(const QString &name) const
{
    QTC_ASSERT(m_debugMode, return QVariant());
    return settings()->value(name);
}

con's avatar
con committed
void DebuggerPlugin::queryConfigValue(const QString &name, QVariant *value)
{
hjk's avatar
hjk committed
    QTC_ASSERT(m_debugMode, return);
hjk's avatar
hjk committed
    *value = settings()->value(name);
con's avatar
con committed
}

void DebuggerPlugin::resetLocation()
{
    //qDebug() << "RESET_LOCATION: current:"  << currentTextEditor();
    //qDebug() << "RESET_LOCATION: locations:"  << m_locationMark;
    //qDebug() << "RESET_LOCATION: stored:"  << m_locationMark->editor();
    delete m_locationMark;
    m_locationMark = 0;
}

void DebuggerPlugin::gotoLocation(const QString &file, int line, bool setMarker)
con's avatar
con committed
{
    TextEditor::BaseTextEditor::openEditorAt(file, line);
    if (setMarker) {
        resetLocation();
        m_locationMark = new LocationMark(file, line);
con's avatar
con committed
    }
}

hjk's avatar
hjk committed
void DebuggerPlugin::handleStateChanged(int state)
con's avatar
con committed
{
hjk's avatar
hjk committed
    const bool startIsContinue = (state == InferiorStopped);
con's avatar
con committed
    if (startIsContinue) {
        core->addAdditionalContext(m_gdbRunningContext);
        core->updateContext();
    } else {
        core->removeAdditionalContext(m_gdbRunningContext);
        core->updateContext();
    }
hjk's avatar
hjk committed
    const bool started = state == InferiorRunning
        || state == InferiorRunningRequested
        || state == InferiorStopping
        || state == InferiorStopped;
hjk's avatar
hjk committed
    const bool starting = state == EngineStarting;
    //const bool running = state == InferiorRunning;
    const bool detachable = state == InferiorStopped
        && m_manager->startParameters()->startMode != AttachCore;

    m_startExternalAction->setEnabled(!started && !starting);
    m_attachExternalAction->setEnabled(!started && !starting);
#ifdef Q_OS_WIN
    m_attachCoreAction->setEnabled(false);
#else
    m_attachCoreAction->setEnabled(!started && !starting);
#endif
    m_startRemoteAction->setEnabled(!started && !starting);
    m_detachAction->setEnabled(detachable);
con's avatar
con committed
}

hjk's avatar
hjk committed
void DebuggerPlugin::writeSettings() const
{
    QTC_ASSERT(m_manager, return);
    QTC_ASSERT(m_manager->mainWindow(), return);

    QSettings *s = settings();
    DebuggerSettings::instance()->writeSettings(s);
hjk's avatar
hjk committed
    s->beginGroup(QLatin1String("DebugMode"));
    m_manager->mainWindow()->saveSettings(s);
hjk's avatar
hjk committed
    s->endGroup();
}

void DebuggerPlugin::readSettings()
{
    QSettings *s = settings();
    DebuggerSettings::instance()->readSettings(s);

    QString defaultCommand("gdb");
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
#ifdef Q_OS_WIN
    defaultCommand.append(".exe");
#endif
    //QString defaultScript = ICore::instance()->resourcePath() +
    //    QLatin1String("/gdb/qt4macros");
    QString defaultScript;
hjk's avatar
hjk committed
    s->beginGroup(QLatin1String("DebugMode"));
    m_manager->mainWindow()->restoreSettings(s);
    m_toggleLockedAction->setChecked(m_manager->mainWindow()->isLocked());
hjk's avatar
hjk committed
    s->endGroup();
}

void DebuggerPlugin::onModeChanged(IMode *mode)
kh's avatar
kh committed
     // FIXME: This one gets always called, even if switching between modes
     //        different then the debugger mode. E.g. Welcome and Help mode and
     //        also on shutdown.

    if (mode != m_debugMode)
hjk's avatar
hjk committed
        return;

    EditorManager *editorManager = EditorManager::instance();
    if (editorManager->currentEditor())
        editorManager->currentEditor()->widget()->setFocus();
}

void DebuggerPlugin::showSettingsDialog()
{
    Core::ICore::instance()->showOptionsDialog(
        QLatin1String(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY),
        QLatin1String(Debugger::Constants::DEBUGGER_COMMON_SETTINGS_ID));
void DebuggerPlugin::startExternalApplication()
{
hjk's avatar
hjk committed
    const DebuggerStartParametersPtr sp(new DebuggerStartParameters);
    StartExternalDialog dlg(m_manager->mainWindow());
    dlg.setExecutableFile(
            configValue(_("LastExternalExecutableFile")).toString());
    dlg.setExecutableArguments(
            configValue(_("LastExternalExecutableArguments")).toString());
    if (dlg.exec() != QDialog::Accepted)
    setConfigValue(_("LastExternalExecutableFile"),
                   dlg.executableFile());
    setConfigValue(_("LastExternalExecutableArguments"),
                   dlg.executableArguments());
    sp->executable = dlg.executableFile();
hjk's avatar
hjk committed
    sp->startMode = StartExternal;
    if (!dlg.executableArguments().isEmpty())
        sp->processArgs = dlg.executableArguments().split(QLatin1Char(' '));

    if (dlg.breakAtMain())
        m_manager->breakByFunctionMain();
    if (RunControl *runControl = m_debuggerRunControlFactory->create(sp))
        ProjectExplorerPlugin::instance()->startRunControl(runControl, ProjectExplorer::Constants::DEBUGMODE);
}

void DebuggerPlugin::attachExternalApplication()
{
    AttachExternalDialog dlg(m_manager->mainWindow());
    if (dlg.exec() == QDialog::Accepted)
        attachExternalApplication(dlg.attachPID());
}

void DebuggerPlugin::attachExternalApplication(qint64 pid, const QString &crashParameter)
{
    if (pid == 0) {
        QMessageBox::warning(m_manager->mainWindow(), tr("Warning"), tr("Cannot attach to PID 0"));
        return;
    }
hjk's avatar
hjk committed
    const DebuggerStartParametersPtr sp(new DebuggerStartParameters);
    sp->crashParameter = crashParameter;
    sp->startMode = crashParameter.isEmpty() ? AttachExternal : AttachCrashedExternal;
    if (RunControl *runControl = m_debuggerRunControlFactory->create(sp))
        ProjectExplorerPlugin::instance()->startRunControl(runControl, ProjectExplorer::Constants::DEBUGMODE);
    AttachCoreDialog dlg(m_manager->mainWindow());
    dlg.setExecutableFile(
            configValue(_("LastExternalExecutableFile")).toString());
    dlg.setCoreFile(
            configValue(_("LastExternalCoreFile")).toString());
    if (dlg.exec() != QDialog::Accepted)
        return;
    setConfigValue(_("LastExternalExecutableFile"),
                   dlg.executableFile());
    setConfigValue(_("LastExternalCoreFile"),
                   dlg.coreFile());
    attachCore(dlg.coreFile(), dlg.executableFile());
}

void DebuggerPlugin::attachCore(const QString &core, const QString &exe)
{
    const DebuggerStartParametersPtr sp(new DebuggerStartParameters);
    sp->executable = exe;
    sp->coreFile = core;
hjk's avatar
hjk committed
    sp->startMode = AttachCore;
    if (RunControl *runControl = m_debuggerRunControlFactory->create(sp))
        ProjectExplorerPlugin::instance()->
            startRunControl(runControl, ProjectExplorer::Constants::DEBUGMODE);
void DebuggerPlugin::startRemoteApplication()
hjk's avatar
hjk committed
    const DebuggerStartParametersPtr sp(new DebuggerStartParameters);
    StartRemoteDialog dlg(m_manager->mainWindow());
    QStringList arches;
    arches.append(_("i386:x86-64:intel"));
    arches.append(_("i386"));
    QString lastUsed = configValue(_("LastRemoteArchitecture")).toString();
    if (!arches.contains(lastUsed))
        arches.prepend(lastUsed);
    dlg.setRemoteArchitectures(arches);
    dlg.setRemoteChannel(
            configValue(_("LastRemoteChannel")).toString());
    dlg.setLocalExecutable(
            configValue(_("LastLocalExecutable")).toString());
    dlg.setDebugger(configValue(_("LastDebugger")).toString());
    dlg.setRemoteArchitecture(lastUsed);
    dlg.setServerStartScript(
            configValue(_("LastServerStartScript")).toString());
    dlg.setUseServerStartScript(
            configValue(_("LastUseServerStartScript")).toBool());
    dlg.setSysRoot(configValue(_("LastSysroot")).toString());
    if (dlg.exec() != QDialog::Accepted)
        return;
    setConfigValue(_("LastRemoteChannel"), dlg.remoteChannel());
    setConfigValue(_("LastLocalExecutable"), dlg.localExecutable());
    setConfigValue(_("LastDebugger"), dlg.debugger());
    setConfigValue(_("LastRemoteArchitecture"), dlg.remoteArchitecture());
    setConfigValue(_("LastServerStartScript"), dlg.serverStartScript());
    setConfigValue(_("LastUseServerStartScript"), dlg.useServerStartScript());
    setConfigValue(_("LastSysroot"), dlg.sysRoot());
    sp->remoteChannel = dlg.remoteChannel();
    sp->remoteArchitecture = dlg.remoteArchitecture();
    sp->executable = dlg.localExecutable();
    sp->debuggerCommand = dlg.debugger();
hjk's avatar
hjk committed
    sp->startMode = StartRemote;
    if (dlg.useServerStartScript())
        sp->serverStartScript = dlg.serverStartScript();
    if (RunControl *runControl = m_debuggerRunControlFactory->create(sp))
        ProjectExplorerPlugin::instance()
            ->startRunControl(runControl, ProjectExplorer::Constants::DEBUGMODE);
con's avatar
con committed
#include "debuggerplugin.moc"

Q_EXPORT_PLUGIN(DebuggerPlugin)