File indexing completed on 2024-03-24 05:29:42
0001 /* 0002 SPDX-FileCopyrightText: 2009 George Kiagiadakis <gkiagia@users.sourceforge.net> 0003 SPDX-FileCopyrightText: 2021 Harald Sitter <sitter@kde.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 #include "debuggermanager.h" 0008 0009 #include <KConfigGroup> 0010 0011 #include "backtracegenerator.h" 0012 #include "debugger.h" 0013 #include "debuggerlaunchers.h" 0014 #include "drkonqibackends.h" 0015 0016 struct DebuggerManager::Private { 0017 BacktraceGenerator *btGenerator = nullptr; 0018 bool debuggerRunning = false; 0019 QList<AbstractDebuggerLauncher *> externalDebuggers; 0020 DBusInterfaceAdaptor *dbusInterfaceAdaptor = nullptr; 0021 }; 0022 0023 DebuggerManager::DebuggerManager(const Debugger &internalDebugger, const QList<Debugger> &externalDebuggers, AbstractDrKonqiBackend *backendParent) 0024 : QObject(backendParent) 0025 , d(new Private) 0026 { 0027 d->btGenerator = new BacktraceGenerator(internalDebugger, this); 0028 connect(d->btGenerator, &BacktraceGenerator::starting, this, &DebuggerManager::onDebuggerStarting); 0029 connect(d->btGenerator, &BacktraceGenerator::done, this, &DebuggerManager::onDebuggerFinished); 0030 connect(d->btGenerator, &BacktraceGenerator::someError, this, &DebuggerManager::onDebuggerFinished); 0031 connect(d->btGenerator, &BacktraceGenerator::failedToStart, this, &DebuggerManager::onDebuggerFinished); 0032 connect(d->btGenerator, &BacktraceGenerator::preparing, backendParent, &AbstractDrKonqiBackend::prepareForDebugger); 0033 connect(backendParent, &AbstractDrKonqiBackend::failedToPrepare, d->btGenerator, &BacktraceGenerator::setBackendFailed); 0034 connect(backendParent, &AbstractDrKonqiBackend::preparedForDebugger, d->btGenerator, &BacktraceGenerator::setBackendPrepared); 0035 0036 for (const Debugger &debugger : std::as_const(externalDebuggers)) { 0037 if (debugger.isInstalled()) { 0038 // TODO: use TerminalDebuggerLauncher instead 0039 addDebugger(new DefaultDebuggerLauncher(debugger, this)); 0040 } 0041 } 0042 0043 // DBus API to inject additional external debuggers at runtime. Used by KDevelop to add itself. 0044 if (qobject_cast<KCrashBackend *>(backendParent)) { 0045 // Runtime debugger injection is only allowed with KCrash because the API sports no interfaces for the debugger 0046 // to describe its compatibility and it was introduced when only KCrash was around. To not have apps break 0047 // randomly on different backends we require that our backend be KCrash. 0048 d->dbusInterfaceAdaptor = new DBusInterfaceAdaptor(this); 0049 } 0050 } 0051 0052 DebuggerManager::~DebuggerManager() 0053 { 0054 if (d->btGenerator->state() == BacktraceGenerator::Loading) { 0055 // if the debugger is running, kill it and continue the process. 0056 delete d->btGenerator; 0057 onDebuggerFinished(); 0058 } 0059 0060 delete d; 0061 } 0062 0063 bool DebuggerManager::debuggerIsRunning() const 0064 { 0065 return d->debuggerRunning; 0066 } 0067 0068 bool DebuggerManager::showExternalDebuggers() const 0069 { 0070 KConfigGroup config(KSharedConfig::openConfig(), QStringLiteral("DrKonqi")); 0071 return config.readEntry("ShowDebugButton", false); 0072 } 0073 0074 QList<AbstractDebuggerLauncher *> DebuggerManager::availableExternalDebuggers() const 0075 { 0076 return d->externalDebuggers; 0077 } 0078 0079 BacktraceGenerator *DebuggerManager::backtraceGenerator() const 0080 { 0081 return d->btGenerator; 0082 } 0083 0084 void DebuggerManager::addDebugger(AbstractDebuggerLauncher *launcher, bool emitsignal) 0085 { 0086 d->externalDebuggers.append(launcher); 0087 connect(launcher, &AbstractDebuggerLauncher::starting, this, &DebuggerManager::onDebuggerStarting); 0088 connect(launcher, &AbstractDebuggerLauncher::finished, this, &DebuggerManager::onDebuggerFinished); 0089 connect(launcher, &AbstractDebuggerLauncher::invalidated, this, &DebuggerManager::onDebuggerInvalidated); 0090 if (emitsignal) { 0091 Q_EMIT externalDebuggerAdded(launcher); 0092 } 0093 } 0094 0095 void DebuggerManager::onDebuggerStarting() 0096 { 0097 d->debuggerRunning = true; 0098 Q_EMIT debuggerStarting(); 0099 Q_EMIT debuggerRunning(true); 0100 } 0101 0102 void DebuggerManager::onDebuggerFinished() 0103 { 0104 d->debuggerRunning = false; 0105 Q_EMIT debuggerFinished(); 0106 Q_EMIT debuggerRunning(false); 0107 } 0108 0109 void DebuggerManager::onDebuggerInvalidated() 0110 { 0111 auto *launcher = qobject_cast<AbstractDebuggerLauncher *>(sender()); 0112 Q_ASSERT(launcher); 0113 int index = d->externalDebuggers.indexOf(launcher); 0114 Q_ASSERT(index >= 0); 0115 d->externalDebuggers.removeAt(index); 0116 Q_EMIT externalDebuggerRemoved(launcher); 0117 } 0118 0119 #include "moc_debuggermanager.cpp"