From 9cb980f2f65ca653181f32f8a5b3e6a2890148f1 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Sun, 10 Mar 2024 21:25:24 +0800 Subject: [PATCH] work save: #259 Remove hard-coded GDB-MI commands outside the gdbmi implementation. --- RedPandaIDE/debugger/dapdebugger.cpp | 20 ++-- RedPandaIDE/debugger/dapdebugger.h | 5 - RedPandaIDE/debugger/debugger.cpp | 82 +++++++++++++---- RedPandaIDE/debugger/debugger.h | 25 +++-- RedPandaIDE/debugger/gdbmidebugger.cpp | 87 +++++++++++++++-- RedPandaIDE/debugger/gdbmidebugger.h | 16 +++- RedPandaIDE/mainwindow.cpp | 123 +++++++------------------ RedPandaIDE/mainwindow.h | 1 - 8 files changed, 214 insertions(+), 145 deletions(-) diff --git a/RedPandaIDE/debugger/dapdebugger.cpp b/RedPandaIDE/debugger/dapdebugger.cpp index 374b8d8f..4d70715c 100644 --- a/RedPandaIDE/debugger/dapdebugger.cpp +++ b/RedPandaIDE/debugger/dapdebugger.cpp @@ -71,16 +71,16 @@ void DAPDebuggerClient::run() readed = mProcess->readAll(); buffer += readed; - if (readed.endsWith("\n")&& outputTerminated(buffer)) { - processDebugOutput(buffer); - buffer.clear(); - mCmdRunning = false; - runNextCmd(); - } else if (!mCmdRunning && readed.isEmpty()){ - runNextCmd(); - } else if (readed.isEmpty()){ - msleep(1); - } + // if (readed.endsWith("\n")&& outputTerminated(buffer)) { + // processDebugOutput(buffer); + // buffer.clear(); + // mCmdRunning = false; + // runNextCmd(); + // } else if (!mCmdRunning && readed.isEmpty()){ + // runNextCmd(); + // } else if (readed.isEmpty()){ + // msleep(1); + // } } if (errorOccured) { emit processFailed(mProcess->error()); diff --git a/RedPandaIDE/debugger/dapdebugger.h b/RedPandaIDE/debugger/dapdebugger.h index d87d0b6a..2a40cbee 100644 --- a/RedPandaIDE/debugger/dapdebugger.h +++ b/RedPandaIDE/debugger/dapdebugger.h @@ -31,13 +31,8 @@ protected: // DebuggerClient interface public: - void postCommand(const QString &Command, const QString &Params, DebugCommandSource Source) override; - void registerInferiorStoppedCommand(const QString &Command, const QString &Params) override; - void stopDebug() override; DebuggerType clientType() override; -protected: - void runNextCmd() override; private: void initializeRequest(); private: diff --git a/RedPandaIDE/debugger/debugger.cpp b/RedPandaIDE/debugger/debugger.cpp index a8fe4e2a..25dcf0b3 100644 --- a/RedPandaIDE/debugger/debugger.cpp +++ b/RedPandaIDE/debugger/debugger.cpp @@ -73,7 +73,12 @@ Debugger::~Debugger() // delete mMemoryModel; } -bool Debugger::start(int compilerSetIndex, const QString& inferior, const QStringList& binDirs, const QString& sourceFile) +bool Debugger::startClient(int compilerSetIndex, + const QString& inferior, + bool inferiorHasSymbols, + bool inferiorHasBreakpoints, + const QStringList& binDirs, + const QString& sourceFile) { mCurrentSourceFile = sourceFile; Settings::PCompilerSet compilerSet = pSettings->compilerSets().getSet(compilerSetIndex); @@ -206,15 +211,33 @@ bool Debugger::start(int compilerSetIndex, const QString& inferior, const QStrin connect(mClient, &DebuggerClient::inferiorStopped,this, &Debugger::refreshAll); - mClient->registerInferiorStoppedCommand("-stack-list-frames",""); mClient->start(); mClient->waitStart(); - pMainWindow->updateAppTitle(); + mClient->initialize(inferior, inferiorHasSymbols); + includeOrSkipDirsInSymbolSearch(compilerSet->libDirs(), pSettings->debugger().skipCustomLibraries()); + includeOrSkipDirsInSymbolSearch(compilerSet->CIncludeDirs(), pSettings->debugger().skipCustomLibraries()); + includeOrSkipDirsInSymbolSearch(compilerSet->CppIncludeDirs(), pSettings->debugger().skipCustomLibraries()); - //Application.HintHidePause := 5000; + //gcc system libraries is auto loaded by gdb + if (pSettings->debugger().skipSystemLibraries()) { + includeOrSkipDirsInSymbolSearch(compilerSet->defaultCIncludeDirs(),true); + includeOrSkipDirsInSymbolSearch(compilerSet->defaultCIncludeDirs(),true); + includeOrSkipDirsInSymbolSearch(compilerSet->defaultCppIncludeDirs(),true); + } + + sendAllBreakpointsToDebugger(); + pMainWindow->updateAppTitle(); + mInferiorHasBreakpoints = inferiorHasBreakpoints; return true; } + +void Debugger::runInferior() +{ + if (mClient) + mClient->runInferior(mInferiorHasBreakpoints); +} + void Debugger::stop() { if (mExecuting) { if (mTarget) { @@ -355,6 +378,17 @@ void Debugger::stepIntoInstruction() mClient->stepIntoInstruction(); } +void Debugger::runClientCommand(const QString &command, const QString ¶ms, DebugCommandSource source) +{ + if (!mClient) + return; + if (mClient->clientType()!=DebuggerType::GDB + && mClient->clientType()!=DebuggerType::LLDB_MI) + return; + GDBMIDebuggerClient* gdbmiClient = dynamic_cast(mClient); + gdbmiClient->postCommand(command, params, source); +} + bool Debugger::isForProject() const { return mBreakpointModel->isForProject(); @@ -930,6 +964,15 @@ void Debugger::addWatchVar(const PWatchVar &watchVar, bool forProject) sendWatchCommand(watchVar); } +void Debugger::includeOrSkipDirsInSymbolSearch(const QStringList &dirs, bool skip) +{ + if (skip) { + mClient->skipDirectoriesInSymbolSearch(dirs); + } else { + mClient->addSymbolSearchDirectories(dirs); + } +} + void Debugger::syncFinishedParsing() { bool spawnedcpuform = false; @@ -955,19 +998,23 @@ void Debugger::syncFinishedParsing() pMainWindow->addDebugOutput(line); } } else { - if (mClient->currentCmd() && mClient->currentCmd()->command == "disas") { + // if (mClient->currentCmd() && mClient->currentCmd()->command == "disas") { - } else { - for (const QString& line:mClient->consoleOutput()) { - pMainWindow->addDebugOutput(line); - } - if ( - (mClient->currentCmd() - && mClient->currentCmd()->source== DebugCommandSource::Console) - || !mClient->consoleOutput().isEmpty() ) { - pMainWindow->addDebugOutput("(gdb)"); - } + // } else { + // for (const QString& line:mClient->consoleOutput()) { + // pMainWindow->addDebugOutput(line); + // } + // if ( + // (mClient->currentCmd() + // && mClient->currentCmd()->source== DebugCommandSource::Console) + // || !mClient->consoleOutput().isEmpty() ) { + // pMainWindow->addDebugOutput("(gdb)"); + // } + // } + for (const QString& line:mClient->consoleOutput()) { + pMainWindow->addDebugOutput(line); } + pMainWindow->addDebugOutput("(gdb)"); } } @@ -1133,11 +1180,6 @@ void DebuggerClient::setDebuggerPath(const QString &debuggerPath) mDebuggerPath = debuggerPath; } -bool DebuggerClient::commandRunning() -{ - return !mCmdQueue.isEmpty(); -} - void DebuggerClient::waitStart() { mStartSemaphore.acquire(1); diff --git a/RedPandaIDE/debugger/debugger.h b/RedPandaIDE/debugger/debugger.h index 863d5de8..bc748f4b 100644 --- a/RedPandaIDE/debugger/debugger.h +++ b/RedPandaIDE/debugger/debugger.h @@ -302,7 +302,14 @@ public: explicit Debugger(QObject *parent = nullptr); ~Debugger(); // Play/pause - bool start(int compilerSetIndex, const QString& inferior, const QStringList& binDirs, const QString& sourceFile=QString()); + bool startClient( + int compilerSetIndex, + const QString& inferior, + bool inferiorHasSymbols, + bool inferiorHasBreakpoints, + const QStringList& binDirs, + const QString& sourceFile=QString()); + void runInferior(); bool commandRunning(); bool inferiorRunning(); void interrupt(); @@ -314,6 +321,8 @@ public: void stepOverInstruction(); void stepIntoInstruction(); + void runClientCommand(const QString &command, const QString ¶ms, DebugCommandSource source); + bool isForProject() const; void setIsForProject(bool newIsForProject); void clearForProject(); @@ -359,6 +368,8 @@ public: void refreshRegisters(); void disassembleCurrentFrame(bool blendMode); void setDisassemblyLanguage(bool isIntel); + void includeOrSkipDirsInSymbolSearch(const QStringList &dirs, bool skip); + // void notifyWatchVarUpdated(PWatchVar var); std::shared_ptr backtraceModel(); @@ -433,6 +444,7 @@ private: qint64 mLastLoadtime; qint64 mProjectLastLoadtime; QString mCurrentSourceFile; + bool mInferiorHasBreakpoints; }; class DebugTarget: public QThread { @@ -473,10 +485,8 @@ class DebuggerClient : public QThread Q_OBJECT public: explicit DebuggerClient(Debugger* debugger, QObject *parent = nullptr); - virtual void postCommand(const QString &Command, const QString &Params, DebugCommandSource Source) = 0; - virtual void registerInferiorStoppedCommand(const QString &Command, const QString &Params) = 0; virtual void stopDebug() = 0; - bool commandRunning(); + virtual bool commandRunning() = 0; QString debuggerPath() const; void setDebuggerPath(const QString &debuggerPath); void waitStart(); @@ -508,6 +518,9 @@ public: virtual DebuggerType clientType() = 0; //requests + virtual void initialize(const QString& inferior, bool hasSymbols) = 0; + virtual void runInferior(bool hasBreakpoints) = 0; + virtual void stepOver() = 0; virtual void stepInto() = 0; virtual void stepOut() = 0; @@ -542,6 +555,8 @@ public: virtual void disassembleCurrentFrame(bool blendMode) = 0; virtual void setDisassemblyLanguage(bool isIntel) = 0; + virtual void skipDirectoriesInSymbolSearch(const QStringList& lst) = 0; + virtual void addSymbolSearchDirectories(const QStringList& lst) = 0; signals: void parseStarted(); void invalidateAllVars(); @@ -579,8 +594,6 @@ signals: const QString& newType, int newNumChildren, bool hasMore); void varsValueUpdated(); -protected: - virtual void runNextCmd() = 0; protected: #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) QRecursiveMutex mCmdQueueMutex; diff --git a/RedPandaIDE/debugger/gdbmidebugger.cpp b/RedPandaIDE/debugger/gdbmidebugger.cpp index 13cff836..633793be 100644 --- a/RedPandaIDE/debugger/gdbmidebugger.cpp +++ b/RedPandaIDE/debugger/gdbmidebugger.cpp @@ -35,27 +35,28 @@ GDBMIDebuggerClient::GDBMIDebuggerClient( { mProcess = std::make_shared(); mAsyncUpdated = false; + registerInferiorStoppedCommand("-stack-list-frames",""); } -void GDBMIDebuggerClient::postCommand(const QString &Command, const QString &Params, - DebugCommandSource Source) +void GDBMIDebuggerClient::postCommand(const QString &command, const QString ¶ms, + DebugCommandSource source) { QMutexLocker locker(&mCmdQueueMutex); PDebugCommand pCmd = std::make_shared(); - pCmd->command = Command; - pCmd->params = Params; - pCmd->source = Source; + pCmd->command = command; + pCmd->params = params; + pCmd->source = source; mCmdQueue.enqueue(pCmd); // if (!mCmdRunning) // runNextCmd(); } -void GDBMIDebuggerClient::registerInferiorStoppedCommand(const QString &Command, const QString &Params) +void GDBMIDebuggerClient::registerInferiorStoppedCommand(const QString &command, const QString ¶ms) { QMutexLocker locker(&mCmdQueueMutex); PDebugCommand pCmd = std::make_shared(); - pCmd->command = Command; - pCmd->params = Params; + pCmd->command = command; + pCmd->params = params; pCmd->source = DebugCommandSource::Other; mInferiorStoppedHookCommands.append(pCmd); } @@ -874,6 +875,52 @@ const PDebugCommand &GDBMIDebuggerClient::currentCmd() const return mCurrentCmd; } +void GDBMIDebuggerClient::initialize(const QString& inferior, bool hasSymbols) +{ + postCommand("-gdb-set", "mi-async on"); + postCommand("-enable-pretty-printing",""); + postCommand("-data-list-register-names",""); + postCommand("-gdb-set", "width 0"); // don't wrap output, very annoying + postCommand("-gdb-set", "confirm off"); + postCommand("-gdb-set", "print repeats 10"); + postCommand("-gdb-set", "print null-stop"); + postCommand("-gdb-set", QString("print elements %1").arg(pSettings->debugger().arrayElements())); // limit array elements to 30 + postCommand("-gdb-set", QString("print characters %1").arg(pSettings->debugger().characters())); // limit array elements to 300 + postCommand("-environment-cd", QString("\"%1\"").arg(extractFileDir(inferior))); // restore working directory + + if (hasSymbols) { + postCommand("-file-exec-and-symbols", '"' + inferior + '"'); + } else { + postCommand("-file-exec-file", '"' + inferior + '"'); + } +} + +void GDBMIDebuggerClient::runInferior(bool hasBreakpoints) +{ + if (debugger()->useDebugServer()) { + postCommand("-target-select",QString("remote localhost:%1").arg(pSettings->debugger().GDBServerPort())); + if (!hasBreakpoints) { + postCommand("-break-insert","-t main"); + } + if (pSettings->executor().useParams()) { + postCommand("-exec-arguments", pSettings->executor().params()); + } + postCommand("-exec-continue",""); + } else { +#ifdef Q_OS_WIN + postCommand("-gdb-set", "new-console on"); +#endif + if (pSettings->executor().useParams()) { + postCommand("-exec-arguments", pSettings->executor().params()); + } + if (!hasBreakpoints) { + postCommand("-exec-run","--start"); + } else { + postCommand("-exec-run",""); + } + } +} + void GDBMIDebuggerClient::stepOver() { postCommand("-exec-next", ""); @@ -1058,6 +1105,25 @@ void GDBMIDebuggerClient::setDisassemblyLanguage(bool isIntel) } } +void GDBMIDebuggerClient::skipDirectoriesInSymbolSearch(const QStringList &lst) +{ + foreach(const QString &dirName, lst) { + postCommand( + "skip", + QString("-gfi \"%1/%2\"") + .arg(dirName,"*.*")); + } +} + +void GDBMIDebuggerClient::addSymbolSearchDirectories(const QStringList &lst) +{ + foreach(const QString &dirName, lst) { + postCommand( + "-environment-directory", + QString("\"%1\"").arg(dirName)); + } +} + void GDBMIDebuggerClient::runInferiorStoppedHook() { QMutexLocker locker(&mCmdQueueMutex); @@ -1071,3 +1137,8 @@ void GDBMIDebuggerClient::clearCmdQueue() QMutexLocker locker(&mCmdQueueMutex); mCmdQueue.clear(); } + +bool GDBMIDebuggerClient::commandRunning() +{ + return !mCmdQueue.isEmpty(); +} diff --git a/RedPandaIDE/debugger/gdbmidebugger.h b/RedPandaIDE/debugger/gdbmidebugger.h index c86d4bba..a52f035f 100644 --- a/RedPandaIDE/debugger/gdbmidebugger.h +++ b/RedPandaIDE/debugger/gdbmidebugger.h @@ -42,11 +42,15 @@ public: // DebuggerClient interface public: - void postCommand(const QString &Command, const QString &Params, DebugCommandSource Source = DebugCommandSource::Other) override; - void registerInferiorStoppedCommand(const QString &Command, const QString &Params) override; + void postCommand(const QString &command, const QString ¶ms, DebugCommandSource source = DebugCommandSource::Other); + void stopDebug() override; DebuggerType clientType() override; const PDebugCommand ¤tCmd() const; + bool commandRunning() override; + + void initialize(const QString& inferior, bool hasSymbols) override; + void runInferior(bool hasBreakpoints) override; void stepOver() override; void stepInto() override; @@ -76,14 +80,19 @@ public: void evalExpression(const QString& expression) override; + void selectFrame(PTrace trace) override; void refreshFrame() override; void refreshRegisters() override; void disassembleCurrentFrame(bool blendMode) override; void setDisassemblyLanguage(bool isIntel) override; + + + void skipDirectoriesInSymbolSearch(const QStringList& lst) override; + void addSymbolSearchDirectories(const QStringList& lst) override; // QThread interface protected: void run() override; - void runNextCmd() override; + void runNextCmd(); private: QStringList tokenize(const QString& s) const; bool outputTerminated(const QByteArray& text) const; @@ -108,6 +117,7 @@ private: QByteArray removeToken(const QByteArray& line) const; void runInferiorStoppedHook(); void clearCmdQueue(); + void registerInferiorStoppedCommand(const QString &command, const QString ¶ms); private slots: void asyncUpdate(); private: diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 8e10719a..16b8e4dc 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -2283,7 +2283,7 @@ void MainWindow::debug() QStringList binDirs; QSet unitFiles; switch(getCompileTarget()) { - case CompileTarget::Project: + case CompileTarget::Project: { compilerSet=pSettings->compilerSets().getSet(mProject->options().compilerSet); if (!compilerSet) compilerSet = pSettings->compilerSets().defaultSet(); @@ -2384,21 +2384,29 @@ void MainWindow::debug() unitFiles.insert(unit->fileName()); } mDebugger->deleteInvalidProjectBreakpoints(unitFiles); - if (!mDebugger->start(mProject->options().compilerSet, filePath, binDirs)) - return; - filePath.replace('\\','/'); - mDebugger->sendCommand("-file-exec-and-symbols", '"' + filePath + '"'); - + bool inferiorHasSymbols { true }; + QString inferior { filePath }; if (mProject->options().type == ProjectType::DynamicLib) { - QString host =mProject->options().hostApplication; - host.replace('\\','/'); - mDebugger->sendCommand("-file-exec-file", '"' + host + '"'); + inferior=mProject->options().hostApplication; + inferiorHasSymbols = false; } + inferior.replace('\\','/'); + if (!mDebugger->startClient( + mProject->options().compilerSet, + inferior, + inferiorHasSymbols, + debugInferiorhasBreakpoint(), + binDirs + )) + return; - includeOrSkipDirs(mProject->options().includeDirs, - pSettings->debugger().skipProjectLibraries()); - includeOrSkipDirs(mProject->options().libDirs, - pSettings->debugger().skipProjectLibraries()); + mDebugger->includeOrSkipDirsInSymbolSearch( + mProject->options().includeDirs, + pSettings->debugger().skipProjectLibraries()); + mDebugger->includeOrSkipDirsInSymbolSearch( + mProject->options().libDirs, + pSettings->debugger().skipProjectLibraries()); + } break; case CompileTarget::File: { binDirs = compilerSet->binDirs(); @@ -2480,9 +2488,14 @@ void MainWindow::debug() prepareDebugger(); QString filePath = debugFile.filePath().replace('\\','/'); - if (!mDebugger->start(pSettings->compilerSets().defaultIndex(),filePath, binDirs,e->filename())) + if (!mDebugger->startClient( + pSettings->compilerSets().defaultIndex(), + filePath, + true, + debugInferiorhasBreakpoint(), + binDirs, + e->filename())) return; - mDebugger->sendCommand("-file-exec-and-symbols", QString("\"%1\"").arg(filePath)); } } break; @@ -2494,53 +2507,7 @@ void MainWindow::debug() updateEditorActions(); - // Add library folders - includeOrSkipDirs(compilerSet->libDirs(), pSettings->debugger().skipCustomLibraries()); - includeOrSkipDirs(compilerSet->CIncludeDirs(), pSettings->debugger().skipCustomLibraries()); - includeOrSkipDirs(compilerSet->CppIncludeDirs(), pSettings->debugger().skipCustomLibraries()); - - //gcc system libraries is auto loaded by gdb - if (pSettings->debugger().skipSystemLibraries()) { - includeOrSkipDirs(compilerSet->defaultCIncludeDirs(),true); - includeOrSkipDirs(compilerSet->defaultCIncludeDirs(),true); - includeOrSkipDirs(compilerSet->defaultCppIncludeDirs(),true); - } - - mDebugger->sendAllBreakpointsToDebugger(); - - // Run the debugger - mDebugger->sendCommand("-gdb-set", "mi-async on"); - mDebugger->sendCommand("-enable-pretty-printing",""); - mDebugger->sendCommand("-data-list-register-names",""); - mDebugger->sendCommand("-gdb-set", "width 0"); // don't wrap output, very annoying - mDebugger->sendCommand("-gdb-set", "confirm off"); - mDebugger->sendCommand("-gdb-set", "print repeats 10"); - mDebugger->sendCommand("-gdb-set", "print null-stop"); - mDebugger->sendCommand("-gdb-set", QString("print elements %1").arg(pSettings->debugger().arrayElements())); // limit array elements to 30 - mDebugger->sendCommand("-gdb-set", QString("print characters %1").arg(pSettings->debugger().characters())); // limit array elements to 300 - mDebugger->sendCommand("-environment-cd", QString("\"%1\"").arg(extractFileDir(filePath))); // restore working directory - if (mDebugger->useDebugServer()) { - mDebugger->sendCommand("-target-select",QString("remote localhost:%1").arg(pSettings->debugger().GDBServerPort())); - if (!debugInferiorhasBreakpoint() || !debugEnabled) { - mDebugger->sendCommand("-break-insert","-t main"); - } - if (pSettings->executor().useParams()) { - mDebugger->sendCommand("-exec-arguments", pSettings->executor().params()); - } - mDebugger->sendCommand("-exec-continue",""); - } else { -#ifdef Q_OS_WIN - mDebugger->sendCommand("-gdb-set", "new-console on"); -#endif - if (pSettings->executor().useParams()) { - mDebugger->sendCommand("-exec-arguments", pSettings->executor().params()); - } - if (!debugInferiorhasBreakpoint()) { - mDebugger->sendCommand("-exec-run","--start"); - } else { - mDebugger->sendCommand("-exec-run",""); - } - } + mDebugger->runInferior(); } void MainWindow::showSearchPanel(bool showReplace) @@ -3184,24 +3151,6 @@ void MainWindow::scanActiveProject(bool parse) }; } -void MainWindow::includeOrSkipDirs(const QStringList &dirs, bool skip) -{ - Q_ASSERT(mDebugger); - foreach (QString dir,dirs) { - QString dirName = dir.replace('\\','/'); - if (skip) { - mDebugger->sendCommand( - "skip", - QString("-gfi \"%1/%2\"") - .arg(dirName,"*.*")); - } else { - mDebugger->sendCommand( - "-environment-directory", - QString("\"%1\"").arg(dirName)); - } - } -} - void MainWindow::onBookmarkContextMenu(const QPoint &pos) { QMenu menu(this); @@ -6150,7 +6099,7 @@ void MainWindow::cleanUpCPUDialog() void MainWindow::onDebugCommandInput(const QString& command) { if (mDebugger->executing()) { - mDebugger->sendCommand(command,"", DebugCommandSource::Console); + mDebugger->runClientCommand(command,"", DebugCommandSource::Console); } } @@ -6399,16 +6348,6 @@ bool MainWindow::debugInferiorhasBreakpoint() return true; } } -// if (!e->inProject()) { - -// } else { -// for (const PBreakpoint& breakpoint:mDebugger->breakpointModel()->breakpoints(e->inProject())) { -// Editor* e1 = mEditorList->getOpenedEditorByFilename(breakpoint->filename); -// if (e1 && e1->inProject()) { -// return true; -// } -// } -// } return false; } @@ -8770,7 +8709,7 @@ void MainWindow::switchCurrentStackTrace(int idx) if (e) { e->setCaretPositionAndActivate(trace->line,1); } - mDebugger->sendCommand("-stack-select-frame", QString("%1").arg(trace->level)); + mDebugger->selectFrame(trace); mDebugger->refreshStackVariables(); mDebugger->refreshWatchVars(); if (this->mCPUDialog) { diff --git a/RedPandaIDE/mainwindow.h b/RedPandaIDE/mainwindow.h index 126f756e..61526824 100644 --- a/RedPandaIDE/mainwindow.h +++ b/RedPandaIDE/mainwindow.h @@ -310,7 +310,6 @@ private: const QString& objectName, QKeySequence shortcut=QKeySequence()); void scanActiveProject(bool parse=false); - void includeOrSkipDirs(const QStringList& dirs, bool skip); void showSearchReplacePanel(bool show); void clearIssues(); void doCompileRun(RunType runType);