diff --git a/src/debuggerlaunchers.cpp b/src/debuggerlaunchers.cpp index d447a861..a68cb110 100644 --- a/src/debuggerlaunchers.cpp +++ b/src/debuggerlaunchers.cpp @@ -1,117 +1,134 @@ /* Copyright (C) 2009 George Kiagiadakis This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "debuggerlaunchers.h" #include #include #include #include "drkonqi_debug.h" #include "detachedprocessmonitor.h" #include "drkonqi.h" #include "crashedapplication.h" DefaultDebuggerLauncher::DefaultDebuggerLauncher(const Debugger & debugger, DebuggerManager *parent) : AbstractDebuggerLauncher(parent), m_debugger(debugger) { m_monitor = new DetachedProcessMonitor(this); connect(m_monitor, &DetachedProcessMonitor::processFinished, this, &DefaultDebuggerLauncher::onProcessFinished); } QString DefaultDebuggerLauncher::name() const { return m_debugger.name(); } void DefaultDebuggerLauncher::start() { if ( static_cast(parent())->debuggerIsRunning() ) { qCWarning(DRKONQI_LOG) << "Another debugger is already running"; return; } QString str = m_debugger.command(); Debugger::expandString(str, Debugger::ExpansionUsageShell); emit starting(); int pid = KProcess::startDetached(KShell::splitArgs(str)); if ( pid > 0 ) { m_monitor->startMonitoring(pid); } else { qCWarning(DRKONQI_LOG) << "Could not start debugger:" << name(); emit finished(); } } void DefaultDebuggerLauncher::onProcessFinished() { emit finished(); } #if 0 TerminalDebuggerLauncher::TerminalDebuggerLauncher(const Debugger & debugger, DebuggerManager *parent) : DefaultDebuggerLauncher(debugger, parent) { } void TerminalDebuggerLauncher::start() { DefaultDebuggerLauncher::start(); //FIXME } #endif -DBusOldInterfaceLauncher::DBusOldInterfaceLauncher(DebuggerManager *parent) - : AbstractDebuggerLauncher(parent) +DBusInterfaceLauncher::DBusInterfaceLauncher(const QString &name, DBusInterfaceAdaptor *parent) + : AbstractDebuggerLauncher(parent), m_name(name) { - m_adaptor = new DBusOldInterfaceAdaptor(this); - QDBusConnection::sessionBus().registerObject(QStringLiteral("/krashinfo"), this); } -QString DBusOldInterfaceLauncher::name() const +QString DBusInterfaceLauncher::name() const { return m_name; } -void DBusOldInterfaceLauncher::start() +void DBusInterfaceLauncher::start() { emit starting(); - emit m_adaptor->acceptDebuggingApplication(); + emit static_cast(parent())->acceptDebuggingApplication(m_name); } -DBusOldInterfaceAdaptor::DBusOldInterfaceAdaptor(DBusOldInterfaceLauncher *parent) +DBusInterfaceAdaptor::DBusInterfaceAdaptor(DebuggerManager *parent) : QDBusAbstractAdaptor(parent) { Q_ASSERT(parent); + + if (QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.drkonqi-%1").arg(pid()))) { + QDBusConnection::sessionBus().registerObject(QStringLiteral("/debugger"), parent); + } } -int DBusOldInterfaceAdaptor::pid() +int DBusInterfaceAdaptor::pid() { return DrKonqi::crashedApplication()->pid(); } -void DBusOldInterfaceAdaptor::registerDebuggingApplication(const QString & name) +void DBusInterfaceAdaptor::registerDebuggingApplication(const QString &name) { - if ( static_cast(parent())->m_name.isEmpty() && !name.isEmpty() ) { - static_cast(parent())->m_name = name; - emit static_cast(parent())->available(); + if (!name.isEmpty() && !m_launchers.contains(name)) { + auto launcher = new DBusInterfaceLauncher(name, this); + m_launchers.insert(name, launcher); + static_cast(parent())->addDebugger(launcher, true); } } +void DBusInterfaceAdaptor::debuggingFinished(const QString &name) +{ + auto it = m_launchers.find(name); + if (it != m_launchers.end()) { + emit it.value()->finished(); + } +} +void DBusInterfaceAdaptor::debuggerClosed(const QString &name) +{ + auto it = m_launchers.find(name); + if (it != m_launchers.end()) { + emit it.value()->invalidated(); + } +} diff --git a/src/debuggerlaunchers.h b/src/debuggerlaunchers.h index 4aa7e651..5325315b 100644 --- a/src/debuggerlaunchers.h +++ b/src/debuggerlaunchers.h @@ -1,112 +1,111 @@ /* Copyright (C) 2009 George Kiagiadakis This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef DEBUGGERLAUNCHERS_H #define DEBUGGERLAUNCHERS_H #include #include "debugger.h" #include "debuggermanager.h" class DetachedProcessMonitor; class AbstractDebuggerLauncher : public QObject { Q_OBJECT Q_PROPERTY(QString name READ name) public: - explicit AbstractDebuggerLauncher(DebuggerManager *parent = nullptr) : QObject(parent) {} + explicit AbstractDebuggerLauncher(QObject *parent = nullptr) : QObject(parent) {} virtual QString name() const = 0; public Q_SLOTS: virtual void start() = 0; Q_SIGNALS: void starting(); void finished(); void invalidated(); }; class DefaultDebuggerLauncher : public AbstractDebuggerLauncher { Q_OBJECT public: explicit DefaultDebuggerLauncher(const Debugger & debugger, DebuggerManager *parent = nullptr); QString name() const override; public Q_SLOTS: void start() override; private Q_SLOTS: void onProcessFinished(); private: const Debugger m_debugger; DetachedProcessMonitor *m_monitor = nullptr; }; #if 0 class TerminalDebuggerLauncher : public DefaultDebuggerLauncher { Q_OBJECT public: explicit TerminalDebuggerLauncher(const Debugger & debugger, DebuggerManager *parent = 0); public slots: virtual void start(); }; #endif -class DBusOldInterfaceAdaptor; +class DBusInterfaceAdaptor; /** This class handles the old drkonqi dbus interface used by kdevelop */ -class DBusOldInterfaceLauncher : public AbstractDebuggerLauncher +class DBusInterfaceLauncher : public AbstractDebuggerLauncher { Q_OBJECT - friend class DBusOldInterfaceAdaptor; public: - explicit DBusOldInterfaceLauncher(DebuggerManager *parent = nullptr); + explicit DBusInterfaceLauncher(const QString &name, DBusInterfaceAdaptor *parent = nullptr); QString name() const override; public Q_SLOTS: void start() override; -Q_SIGNALS: - void available(); - private: QString m_name; - DBusOldInterfaceAdaptor *m_adaptor; }; -class DBusOldInterfaceAdaptor : public QDBusAbstractAdaptor +class DBusInterfaceAdaptor : public QDBusAbstractAdaptor { Q_OBJECT - Q_CLASSINFO("D-Bus Interface", "org.kde.Krash") - friend class DBusOldInterfaceLauncher; + Q_CLASSINFO("D-Bus Interface", "org.kde.drkonqi") public: - explicit DBusOldInterfaceAdaptor(DBusOldInterfaceLauncher *parent); + explicit DBusInterfaceAdaptor(DebuggerManager *parent); public Q_SLOTS: int pid(); - Q_NOREPLY void registerDebuggingApplication(const QString & name); + Q_NOREPLY void registerDebuggingApplication(const QString &name); + Q_NOREPLY void debuggingFinished(const QString &name); + Q_NOREPLY void debuggerClosed(const QString &name); Q_SIGNALS: - void acceptDebuggingApplication(); + void acceptDebuggingApplication(const QString &name); + +private: + QHash m_launchers; }; #endif // DEBUGGERLAUNCHERS_H diff --git a/src/debuggermanager.cpp b/src/debuggermanager.cpp index 7c9305b6..ad102467 100644 --- a/src/debuggermanager.cpp +++ b/src/debuggermanager.cpp @@ -1,123 +1,121 @@ /* Copyright (C) 2009 George Kiagiadakis This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "debuggermanager.h" #include #include "debugger.h" #include "debuggerlaunchers.h" #include "backtracegenerator.h" struct DebuggerManager::Private { BacktraceGenerator *btGenerator; bool debuggerRunning; QList externalDebuggers; - DBusOldInterfaceLauncher *dbusOldInterfaceLauncher; + DBusInterfaceAdaptor *dbusInterfaceAdaptor; }; DebuggerManager::DebuggerManager(const Debugger & internalDebugger, const QList & externalDebuggers, QObject *parent) : QObject(parent), d(new Private) { d->debuggerRunning = false; d->btGenerator = new BacktraceGenerator(internalDebugger, this); connect(d->btGenerator, &BacktraceGenerator::starting, this, &DebuggerManager::onDebuggerStarting); connect(d->btGenerator, &BacktraceGenerator::done, this, &DebuggerManager::onDebuggerFinished); connect(d->btGenerator, &BacktraceGenerator::someError, this, &DebuggerManager::onDebuggerFinished); connect(d->btGenerator, &BacktraceGenerator::failedToStart, this, &DebuggerManager::onDebuggerFinished); foreach(const Debugger & debugger, externalDebuggers) { if (debugger.isInstalled()) { - AbstractDebuggerLauncher *l = new DefaultDebuggerLauncher(debugger, this); //FIXME - d->externalDebuggers.append(l); - connect(l, &AbstractDebuggerLauncher::starting, this, &DebuggerManager::onDebuggerStarting); - connect(l, &AbstractDebuggerLauncher::finished, this, &DebuggerManager::onDebuggerFinished); - connect(l, &AbstractDebuggerLauncher::invalidated, this, &DebuggerManager::onDebuggerInvalidated); + // TODO: use TerminalDebuggerLauncher instead + addDebugger(new DefaultDebuggerLauncher(debugger, this)); } } //setup kdevelop compatibility - d->dbusOldInterfaceLauncher = new DBusOldInterfaceLauncher(this); - connect(d->dbusOldInterfaceLauncher, &DBusOldInterfaceLauncher::starting, this, &DebuggerManager::onDebuggerStarting); - connect(d->dbusOldInterfaceLauncher, &DBusOldInterfaceLauncher::available, this, &DebuggerManager::onDBusOldInterfaceDebuggerAvailable); + d->dbusInterfaceAdaptor = new DBusInterfaceAdaptor(this); } DebuggerManager::~DebuggerManager() { if (d->btGenerator->state() == BacktraceGenerator::Loading) { //if the debugger is running, kill it and continue the process. delete d->btGenerator; onDebuggerFinished(); } delete d; } bool DebuggerManager::debuggerIsRunning() const { return d->debuggerRunning; } bool DebuggerManager::showExternalDebuggers() const { KConfigGroup config(KSharedConfig::openConfig(), "DrKonqi"); return config.readEntry("ShowDebugButton", false); } QList DebuggerManager::availableExternalDebuggers() const { return d->externalDebuggers; } BacktraceGenerator* DebuggerManager::backtraceGenerator() const { return d->btGenerator; } +void DebuggerManager::addDebugger(AbstractDebuggerLauncher *launcher, bool emitsignal) +{ + d->externalDebuggers.append(launcher); + connect(launcher, &DBusInterfaceLauncher::starting, this, &DebuggerManager::onDebuggerStarting); + connect(launcher, &DBusInterfaceLauncher::finished, this, &DebuggerManager::onDebuggerFinished); + connect(launcher, &AbstractDebuggerLauncher::invalidated, this, &DebuggerManager::onDebuggerInvalidated); + if (emitsignal) { + emit externalDebuggerAdded(launcher); + } +} + void DebuggerManager::onDebuggerStarting() { d->debuggerRunning = true; emit debuggerStarting(); emit debuggerRunning(true); } void DebuggerManager::onDebuggerFinished() { d->debuggerRunning = false; emit debuggerFinished(); emit debuggerRunning(false); } void DebuggerManager::onDebuggerInvalidated() { AbstractDebuggerLauncher *launcher = qobject_cast(sender()); Q_ASSERT(launcher); int index = d->externalDebuggers.indexOf(launcher); Q_ASSERT(index >= 0); d->externalDebuggers.removeAt(index); emit externalDebuggerRemoved(launcher); } - -void DebuggerManager::onDBusOldInterfaceDebuggerAvailable() -{ - d->externalDebuggers.append(d->dbusOldInterfaceLauncher); - emit externalDebuggerAdded(d->dbusOldInterfaceLauncher); -} - - diff --git a/src/debuggermanager.h b/src/debuggermanager.h index c96811a3..f97cce88 100644 --- a/src/debuggermanager.h +++ b/src/debuggermanager.h @@ -1,58 +1,58 @@ /* Copyright (C) 2009 George Kiagiadakis This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef DEBUGGERMANAGER_H #define DEBUGGERMANAGER_H #include class BacktraceGenerator; class Debugger; class AbstractDebuggerLauncher; class DebuggerManager : public QObject { Q_OBJECT public: explicit DebuggerManager(const Debugger & internalDebugger, const QList & externalDebuggers, QObject *parent = nullptr); ~DebuggerManager() override; bool debuggerIsRunning() const; bool showExternalDebuggers() const; QList availableExternalDebuggers() const; BacktraceGenerator *backtraceGenerator() const; + void addDebugger(AbstractDebuggerLauncher *launcher, bool emitsignal = false); Q_SIGNALS: void debuggerStarting(); void debuggerFinished(); void debuggerRunning(bool running); void externalDebuggerAdded(AbstractDebuggerLauncher *launcher); void externalDebuggerRemoved(AbstractDebuggerLauncher *launcher); private Q_SLOTS: void onDebuggerStarting(); void onDebuggerFinished(); void onDebuggerInvalidated(); - void onDBusOldInterfaceDebuggerAvailable(); private: struct Private; Private *const d; }; #endif // DEBUGGERMANAGER_H